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
Regular Contributor
Posts: 78
Registered: ‎04-05-2010
My Device: Storm
Accepted Solution

Sometimes it detects one device sometimes all please help how to detect all everytime

[ Edited ]

Following is the code. In listbox sometimes only 1 device appears sometimes all 3 devices, I tried to put lock but application use to geet hang please help me to identify where I am committing the mistake. Im using Blackberry 9000. The funcitonality I wish to implement is to show list of devices available and when user select some device by clicking on it, software start moniutoring it. It is not refined code but working:

 

package Btooth;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

//import net.rim.device.api.bluetooth.BluetoothSerialPortInfo;
import net.rim.device.api.collection.List;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.ListFieldCallback;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.decor.Background;
import net.rim.device.api.ui.decor.BackgroundFactory;

import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.microedition.content.ContentHandlerException;
import javax.microedition.content.Invocation;
import javax.microedition.content.Registry;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;


public final class AppScreen extends MainScreen 
{    
	LocalDevice local;
	private DiscoveryAgent discoveryAgent;
	private Hashtable bluetoothDevices = new Hashtable();
	private Hashtable bluetoothDevicesforMonitoring = new Hashtable();
	List deviceList;
	net.rim.device.api.ui.component.ButtonField buttonSaveSelected;
	boolean  is_monitoring = false;

	ListField _listField;
	Vector _listElements;
	bluetoothDiscovery btoothdiscov;
	bluetoothDiscovery btoothdiscovFind;
	LocalDevice localDevice = null;
	RemoteDevice devices[];


	private static Object lock=new Object();


	public AppScreen()
	{
		try {
			setTitle("Test App");
			Background solidBackground = BackgroundFactory.createSolidBackground(Color.LIGHTSTEELBLUE);
			LabelField welcome = new LabelField("Test App", LabelField.FIELD_HCENTER);
			welcome.setBackground(solidBackground);
			add(welcome);
			btoothdiscov = new bluetoothDiscovery();
			btoothdiscov.run();



		} catch (Exception e) {
			net.rim.device.api.ui.component.Dialog.alert("App screen: "+e.getMessage());
			e.printStackTrace();
		}

	}



	public class bluetoothDiscovery extends Thread implements DiscoveryListener {

		private boolean _stop = false;

		private class ListCallback implements ListFieldCallback 
		{
			public void drawListRow(ListField list, Graphics g, int index, int y, int w) 
			{ 
				try {
					String text = (String)_listElements.elementAt(index); 
					g.drawText(text, 0, y, 0, w);
				} catch (Exception e) {
					net.rim.device.api.ui.component.Dialog.alert("List call back draw list: "+e.getMessage());
					e.printStackTrace();
				} 
			} 
			public Object get(ListField list, int index) 
			{
				return _listElements.elementAt(index); 
			} 
			public int indexOfList(ListField list, String prefix, int string) 
			{ 
				return _listElements.indexOf(prefix, string); 
			} 
			public int getPreferredWidth(ListField list) 
			{ 
				return 150;
				//return Display.getWidth(); 
			} 
		}


		private synchronized void stop()
		{
			_stop = true;

		}   


		public void run() {

			if(_stop != true)
			{



				try {
					localDevice = LocalDevice.getLocalDevice();

				} catch (BluetoothStateException e) {

					net.rim.device.api.ui.component.Dialog.alert("Bluetooth Discovery Local Device: "+e.getMessage());
					e.printStackTrace();

				}

				discoveryAgent = localDevice.getDiscoveryAgent();



				if(is_monitoring == true)
				{

					verifyExistanceofDevices();

				}
				else
				{

					finddevicesasfirsttime();

				}
			}


		}

		public void finddevicesasfirsttime()
		{

			devices = discoveryAgent.retrieveDevices(DiscoveryAgent.CACHED);

			if (devices != null) {

				for (int i=0; i < devices.length; i++) {



					try {
						String nameofbluetoothdevice = devices[i].getFriendlyName(true);
						if(nameofbluetoothdevice != null)
						{
							if(is_monitoring == false)
							{
								bluetoothDevices.put(nameofbluetoothdevice, "0");
							}
							else
							{
								bluetoothDevicesforMonitoring.put(nameofbluetoothdevice, "0");
							}
						}
					} catch (IOException e) {

						net.rim.device.api.ui.component.Dialog.alert("Bluetooth Discovery Cached: "+e.getMessage());
						e.printStackTrace();
					}

				}
			}

			devices = discoveryAgent.retrieveDevices(DiscoveryAgent.PREKNOWN);

			if (devices != null) {

				for (int i=0; i < devices.length; i++) {

					try {
						String nameofbluetoothdevice = devices[i].getFriendlyName(true);
						if(nameofbluetoothdevice != null)
						{
							if(is_monitoring == false)
							{
								bluetoothDevices.put(nameofbluetoothdevice, "0");
							}
							else
							{
								bluetoothDevicesforMonitoring.put(nameofbluetoothdevice, "0");

							}
						}
					} catch (IOException e) {

						net.rim.device.api.ui.component.Dialog.alert("Preknown: "+e.getMessage());
						e.printStackTrace();
					}


				} 
			}


			try {

				discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);

			} catch (BluetoothStateException e) {
				net.rim.device.api.ui.component.Dialog.alert("Device Discovered: "+e.getMessage());
				e.printStackTrace();
			}


			/*
			try {

				synchronized(lock){
					lock.wait();
				}
			} 
			catch (InterruptedException e) {
				net.rim.device.api.ui.component.Dialog.alert("In lock sync "+e.getMessage());
				e.printStackTrace();
			}

			 */

		}

		public void verifyExistanceofDevices()
		{

			bluetoothDevicesforMonitoring.clear(); //14/07/2011
			devices = discoveryAgent.retrieveDevices(DiscoveryAgent.CACHED);

			if (devices != null) {

				for (int i=0; i < devices.length; i++) {



					try {
						String nameofbluetoothdevice = devices[i].getFriendlyName(true);
						if(nameofbluetoothdevice != null)
						{

							bluetoothDevicesforMonitoring.put(nameofbluetoothdevice, "0");

						}
					} catch (IOException e) {

						net.rim.device.api.ui.component.Dialog.alert("Bluetooth Discovery Cached: "+e.getMessage());
						e.printStackTrace();
					}

				}
			}

			devices = discoveryAgent.retrieveDevices(DiscoveryAgent.PREKNOWN);

			if (devices != null) {

				for (int i=0; i < devices.length; i++) {

					try {
						String nameofbluetoothdevice = devices[i].getFriendlyName(true);
						if(nameofbluetoothdevice != null)
						{

							bluetoothDevicesforMonitoring.put(nameofbluetoothdevice, "0");

						}
					} catch (IOException e) {

						net.rim.device.api.ui.component.Dialog.alert("Preknown: "+e.getMessage());
						e.printStackTrace();
					}


				}


				try {

					discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);

				} catch (BluetoothStateException e) {
					net.rim.device.api.ui.component.Dialog.alert("Device Discovered: "+e.getMessage());
					e.printStackTrace();
				}


			}





		}

		public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass cod) {
			try{

				String nameofbluetoothdevice = remoteDevice.getFriendlyName(true);
				if(nameofbluetoothdevice != null)
				{
					if(is_monitoring == false)
					{
						bluetoothDevices.put(nameofbluetoothdevice, "0");
					}
					else
					{
						bluetoothDevicesforMonitoring.put(nameofbluetoothdevice, "0");

					}
				}
				//discoveryForm.append("found: " + remoteDevice.getFriendlyName(true));
			} catch(Exception e){
				net.rim.device.api.ui.component.Dialog.alert("Device Discovered: "+e.getMessage());
				e.printStackTrace();
			} finally{
				//remoteDevices.addElement(remoteDevice);
			}
		}

		//net.rim.device.api.ui.component.Dialog.alert("You must enter password");



		public void inquiryCompleted(int discType) {




			try {
				if(is_monitoring == false)
				{
					_listField =  new ListField(ListField.MULTI_SELECT);
					_listElements = new Vector();
					Enumeration names;



					ListCallback _callback = new ListCallback();
					_listField.setCallback(_callback);


					names = bluetoothDevices.keys(); 
					while(names.hasMoreElements()) { 

						_listElements.addElement((String) names.nextElement()); 


					}

					add(_listField);




					//buttonSaveSelected = new net.rim.device.api.ui.component.ButtonField("Save and Monitor selected",net.rim.device.api.ui.component.ButtonField.CONSUME_CLICK);

					reloadList();

				}
				else
				{
					checkandinform();			
				}
			} catch (Exception e) {
				net.rim.device.api.ui.component.Dialog.alert("Inquiry Completed: "+e.getMessage());
				e.printStackTrace();
			}

		}


		public String get(ListField list, int index) {
			String toreturn = null;

			try {
				toreturn = (String)_listElements.elementAt(index);
			} catch (Exception e) {
				net.rim.device.api.ui.component.Dialog.alert("Get field list "+e.getMessage());
				e.printStackTrace();
			}

			return toreturn;
		}


		private void reloadList()
		{
			try {
				_listField.setSize(_listElements.size());
			} catch (Exception e) {
				net.rim.device.api.ui.component.Dialog.alert(e.getMessage());
				e.printStackTrace();
			}
		}

		public void serviceSearchCompleted(int transID, int respCode) {
			// TODO Auto-generated method stub

		}
		public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
			// TODO Auto-generated method stub

		}
	}









	protected boolean navigationClick(int status, int time)
	{
		btoothdiscov.stop();
		btoothdiscovFind = new bluetoothDiscovery ();  //Because if earlier bluetooth disc object is used it is putting stop

		is_monitoring = true;
		bluetoothDevicesforMonitoring.clear();
		btoothdiscovFind.run();
		//checkandinform();

		return true;
	}

	public void checkandinform()
	{


		//btoothdiscov.stop();

		boolean find = true;
		try {
			Enumeration names;
			names = bluetoothDevicesforMonitoring.keys(); 
			if(bluetoothDevicesforMonitoring.isEmpty())
			{
				if(!bluetoothDevices.isEmpty())
				{
					find =false;
				}
			}

			String listelem  = (String)_listElements.elementAt(_listField.getSelectedIndex());
			while(names.hasMoreElements()) {
				Object oj = names.nextElement();
				String nextelem = null;
				if(oj != null)
				{
					nextelem = (String)oj;
				}


				if(nextelem.equals(listelem))
				{
					find = true;
					break;
				}
				else
				{
					find = false;

				}

			}
			if( find == false)
			{

				playthesound("file:///store/home/user/test.mp3");
				if(btoothdiscov != null)
				{
					btoothdiscov.stop();
				}
				if(btoothdiscovFind != null)
				{
					btoothdiscovFind.stop();
				}
				btoothdiscov = null;
				btoothdiscovFind = null;
				net.rim.device.api.ui.component.Dialog.alert("Test App remember");
				System.exit(0);
			}
			else
			{
				//If  everything is ok then again send for search
				btoothdiscovFind.run();

			}

		} catch (Exception e) {
			net.rim.device.api.ui.component.Dialog.alert("Navigation Clicked"+ e.getMessage());
			e.printStackTrace();
		}
		//net.rim.device.api.ui.component.Dialog.inform("Clear Button Pressed!");

	}

	public void playthesound(String filename)
	{
		//Code to play sound

	}

}

 

 

 

 

 

Retired
Retired
Posts: 150
Registered: ‎10-19-2010
My Device: Not Specified
My Carrier: Rogers

Re: Sometimes it detects one device sometimes all please help how to detect all everytime

Hi mobiledeveloper!

 

Bluetooth isn't really my area of expertise, but here are a few suggestions:

 

Try logging a lot more information to see what's going on.  For example, when you add devices to your hashtables you always check if the nameofbluetoothdevice != null, but if it is null you do nothing - try logging these cases and see if the devices aren't being added in the first place.

 

Similarly, in your inquiryCompleted method you are ignoring the discType parameter.  It may be returning an error which means that the discovery finished prematurely which can lead to the behaviour you are seeing, but unless you check you don't know.

 

Also, it looks to me like you are not replacing the listfield in your screen, rather you repeatedly add new ones - can this be leading to the appearance that the list is missing devices since you're looking at or adding the wrong field?

 

There are also threading issues between deviceDiscovered, inquiryCompleted, and especially navigationClick.  SInce you have an (unused) lock object I assume you are aware, but there is unsynchronized access to your hashtables which can lead to problems.  For example, if inquiryCompleted is called before all of your deviceDiscovered have finished processing then I can see this leading to the behaviour you are seeing.  Also if navigationClick is clicked twice quickly, the problem is compounded by the fact that you may have multiple discoveries going on (if that's possible).

 

If it helps, you probably don't need to populate your lists with cached devices then go discover new ones, since there will likely be repeats - this is probably why you chose hashtables rather than an array or Vector to store the names, but not using the cached values and only working with discoveries should remove the need to do this.  I suggest use the cached list to present something right away to the user, but then in the background go check with a discovery and update accordingly as new information arrives and don't work with the cache (since it will always be out of date from the first discovery and on anyway). 

 

Along those lines, you loop discoveries very quickly.  Since this is likely an expensive operation (as implied by the fact that the cache of devices previously discovered is exposed) I would suggest putting it on a timer, perhaps run a discovery every 30 or 60 seconds or more - what you choose should depend on how long a discovery is actually taking, which I don't know.  Otherwise battery drain would probably be severe if you loop very quickly and plan to leave the app running for long periods of time.

 

Finally, in your checkandinform method, you are re-running btoothdiscovFind.run(); in-line rather than starting it in it's own thread again, is this intentional?  It could be a problem if you called checkandinform from your event thread, it will block until all of this work completes again causing UI delays and freezes.

 

Hope these help!

Regular Contributor
Posts: 78
Registered: ‎04-05-2010
My Device: Storm

Re: Sometimes it detects one device sometimes all please help how to detect all everytime

[ Edited ]

Thank you so much BVP for guidance. The code works fine if I do not ask the device to bring friendlyname of the device. I will try your advices also.You are right may be anyone of them can be the problem. Again thank you so much for replying.

Regular Contributor
Posts: 78
Registered: ‎04-05-2010
My Device: Storm

Re: Sometimes it detects one device sometimes all please help how to detect all everytime

[ Edited ]

Thanks you so much, not calling btoothdiscovFind.run() from inline as you have adivsed solved the problem. I have also tweaked the code according to your recommendations. Now it is working fine.