Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Developer
Posts: 78
Registered: ‎12-03-2009
My Device: Not Specified
Accepted Solution

Probably multi-thread issue

[ Edited ]

Greetings!

 

Not sure what kind of problem I facing, but still quite interesting.

 

I have an UiApplication which start a thread to listen for incoming SMS and automatically answer them. This same class implements PhoneListener as bellow:

 

 

public class SMSSenderReceiver extends Thread implements PhoneListener {

	private static DatagramConnection _dc;
	private static int _callIdIncoming;
	private static int _callIdAnswered;
	public static String _phoneNumber;
	
	static {
	try {
		_dc = (DatagramConnection) Connector.open("sms://");
		} catch (IOException e) {
			System.out.println(e);
		}
	}

	public SMSSenderReceiver() {
		super();
		_callIdIncoming = -1;
		_callIdAnswered = -1;
		Phone.addPhoneListener(this);
	}

	public void run() {
		try {
			for (;;) {
				Datagram d = _dc.newDatagram(_dc.getMaximumLength());
				_dc.receive(d);
				String address = d.getAddress();
				if (address.startsWith("//")) {
					address = address.substring(2);
				}
				String answer = getResponseByPhone(address);
				if (answer != null) {
					answer.getBytes();
					Datagram returnpacket = _dc.newDatagram(_dc
							.getMaximumLength());
					returnpacket.setAddress(d.getAddress());
					returnpacket.setData(answer.getBytes(), 0, answer.length());
					_dc.send(returnpacket);
				}
			}
		} catch (IOException ioe) {
			System.out.println(ioe);
			Phone.removePhoneListener(this);
		}
	}

	private static String getResponseByPhone(final String phone) {
		TextResponses tr = TextResponses.getInstance();
		MultiMap mm = tr.getResponses();
		Enumeration valuesEnum = mm.keys();
		while (valuesEnum.hasMoreElements()) {
			String element = valuesEnum.nextElement().toString();
			if (mm.containsValue(element, phone)) {
				return element;
			} else {
				continue;
			}
		}
		return null;
	}

	//	public void missedCallSMSSender(final String address) {
	//		try {
	//			if(_callIdAnswered != _callIdIncoming){
	//				//				if (address.startsWith("//")) {
	//				//					address = address.substring(2);
	//				//				}
	//				String answer = this.getResponseByPhone(address);
	//				if (answer != null) {
	//					answer.getBytes();
	//					Datagram returnpacket = _dc.newDatagram(_dc
	//							.getMaximumLength());
	//					returnpacket.setAddress("//" + address);
	//					returnpacket.setData(answer.getBytes(), 0, answer
	//							.length());
	//					_dc.send(returnpacket);
	//				}
	//				_callIdAnswered = _callIdIncoming = -1;
	//				//_phoneCallsHash.remove("" + _callIdIncoming);
	//			}
	//		} catch (Exception e) {
	//			System.out.println(e);
	//		}
	//	}

	public void callIncoming(final int callId) {
		if(_callIdIncoming != callId){
			UiApplication.getUiApplication().invokeLater(new Runnable(){
				public void run() {
					_callIdIncoming = callId;
					PhoneCall phoneCall = Phone.getCall( callId );
					_phoneNumber = null;
					try {
						_phoneNumber = phoneCall.getDisplayPhoneNumber();

						String tempNumber = null;
						for(int i = _phoneNumber.length() -1 ;i >= 0; --i) {
							if(Character.isDigit(_phoneNumber.charAt(i))){
								tempNumber = _phoneNumber.charAt(i) + ((tempNumber == null) ? "" : tempNumber) ;
							}
						}
						_phoneNumber = tempNumber;

						System.out.println("**bleep** Phone Number: " + _phoneNumber);
					} catch(NullPointerException npe) {
						_phoneNumber = "0";
						System.out.println("NULL!!!!" + npe);
					}
				}
			});
		}
	}

	public void callAnswered(int callId) {
		_callIdAnswered = callId;
	}

	public void callDisconnected(int callId) {
		UiApplication.getUiApplication().invokeLater(new Runnable(){
			public void run() {
				//System.out.println("**bleep** Phone Number: " + _phoneNumber);
				//SMSSenderReceiver.this.missedCallSMSSender(_phoneNumber);
				String address = _phoneNumber;
				if(_callIdAnswered != _callIdIncoming){
					//					if (address.startsWith("//")) {
					//						address = address.substring(2);
					//					}
					String answer = getResponseByPhone(address);
					if (answer != null) {
						answer.getBytes();
						try {
							Datagram returnpacket = _dc.newDatagram(_dc.getMaximumLength());
							returnpacket.setAddress("//" + address);
							returnpacket.setData(answer.getBytes(), 0, answer
									.length());
							_dc.send(returnpacket);
						} catch(Exception e) {
							System.out.println(e);
						}
					}
					_callIdAnswered = _callIdIncoming = -1;
				}
			}
		});
	}
...

The goal is to send a SMS for each missed call. So, on incomingCall I catch the call Id and the phone number assign them to the static variables. If the call is answered I catch the call id also. Once the the call is disconnected I just check the call answered id and incoming id in case they differ from each other I got a miss call and I have to send a SMS.

 

The problem is once the callDisconneted is called I no longer have the _phoneNumber value. On incomingCall I able to see the number, but not after all. Why? Seems to be a basic fundamental about multi-thread.

 

Does anybody know what is happening?

Thanks in advance!

 

--

 

 

--
Feel free to press the kudos button on the left side to thank the user that helped you.
Please mark posts as solved if you found a solution.
Highlighted
Developer
Posts: 4,764
Registered: ‎07-21-2008
My Device: Not Specified

Re: Probably multi-thread issue

[ Edited ]

This issue probably has to do with the fact that the call listener is actually coming into your code on the phone application thread. Each application gets a separate copy of static context. Consequently, you will not see the same data when you access this variable in your own application process.

 

You probably have two choices here: (a) send yourself a global event form the call listener, then pick up this event in your own process, or (b) use the runtime store to retain the value so that both processes can *see* it.