Having trouble displaying bluetooth devices in textView - android

I would like the device names to show up in the textView of my app when they are found during scanning but nothing shows up.
I see the bluetooth is successfully enabled and my other device is visible but nothing ever shows up.
bluetoothAdapter = (BluetoothAdapter.getDefaultAdapter());
bluetoothAdapter.enable();
bluetoothAdapter.startDiscovery();
BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//Finding devices
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
textView.append(device.getAddress());
}
}
};
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
I know the above code was kinda intended for use in a listView but would it not still work in textView?

I think i have found the problem here.
What's happening is there is a problem when you call bluetoothAdapter.startDiscovery(); right after bluetoothAdapter.enable();
The adapter apparently needs a few seconds to get everything set up before you start doing stuff with it.
So i put a little delay in between those like so:
bluetoothAdapter.enable();
try {
Thread.sleep(3000);//3 seconds
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
bluetoothAdapter.startDiscovery();
And now everything seems to work.

Related

Bluetooth on Android: Debuging startDiscovery()

I'm working on an app that searches for discoverable devices and displays them as buttons.
When calling startDiscovery() I would say it works 30% of the time, based on the way I'm currently debugging it, with the BroadcastReceiver and ACTION_DISCOVERY_FINISHED.
I'm also using isDiscovering() to test if the startDiscovery() function is called but it returns false.
Is there a way to know if startDiscovery() is called successfully? And can you identify something in my code that would make it not fail?
Obs.: I have both BLUETOOTH AND BLUETOOTH_ADMIN permissions.
Here is my code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String Address;
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Address = device.getAddress();
System.out.println("Found Address: " + Address ); //DEBUG
//Do something with Address
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
System.out.println("Discovery finished");
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
MainActivity.mBluetoothAdapter.startDiscovery();
if (MainActivity.mBluetoothAdapter.isDiscovering()) {
System.out.println("Discovering..."); //DEBUG
}
}
Although I have a few discoverable devices available, none of them trigger onReceive() with ACTION_FOUND
UPDATE: I went to "Scan" under Bluetooth Settings while the app was running and I could not scan for new devices. I disabled/enabled Bluetooth and returned to the app and the problem was resolved. I don't know if that indicates that the adapter is busy or halted somehow.
I confirm this issue.
On some telephones you just need to disable/active BT. You can doit programatically with
mBluetoothAdapter.disable();
mBluetoothAdapter.enable();
On some telephones its not enough ( Samsung S5 ). To detect it, I use timer, and if on end of timeout the change of BT broadcast state (BluetoothAdapter.ACTION_DISCOVERY_STARTED or BluetoothAdapter.ACTION_DISCOVERY_FINISHED ) wasnt received => its sign that BT is not working. Actually I show dialog which propose to user reboot the telephone.

How to check if a bluetooth device is paired

I'm trying to check if there is a bluetooth device paired when running my app.
In the main activity, I find bluetooth devices and pair to them. In the second activity, I must check if there is a device paired or not.
If a device is conected, it starts automatically sending data, but if there is no conexion, then it simply shows a toast.
I need to do this just when the second activity starts. I found this code, but I don't know how to make it to start when the activity is just created.
public void onCreate() {
//...
IntentFilter filter1 = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
IntentFilter filter2 = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
this.registerReceiver(mReceiver, filter1);
this.registerReceiver(mReceiver, filter2);
}
//The BroadcastReceiver that listens for bluetooth broadcasts
private final BroadcastReceiver BTReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
//Do something if connected
}
else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
//Do something if disconnected
}
}
};
Here is a complete description of the problem, with the correct answer to solve it:
Action to know if there is any bluetooth paired device

Bluetooth status on statusbar

I have my own application home screen as default home screen for my android device. I have a status bar in my application and I am managing the Bluetooth connection status with an Imageview(onclick) in that status bar.
If I click on the Imageview in my statusbar I am turning the bluetooth on/off. I am changing the background of imageview according to the status of bluetooth.
If bluetooth is ON - Blueimage
If bluetooth is OFF - greyImage
So my question is - If I enable/disable the bluetooth in bluetoth settings page and press the back button and navigate to my home screen then Imageview(background image) in my status bar should get changed automatically.
I tried a lot updating the image of imageview on back button press(by overriding onbackpressed method) but no result.
Is there any similar API with which we can read/store the status of bluetooth in a variable as soon as we enable/disable the bluetooth in bluetooth settings page and according to that the status bar imageview backround will get changed automatically?
Any help is greatly appreciated, Thanks
you can put the code that checked for the Bluetooth status in the onRestart() method
like this:
public class yourClass {
public void onCreate(Bundle savedInstanceState) {
// your code
}
public void onRestart() {
// put the checked code for the Bluetooth status here
}
You need to add broadcast receivers in your code to receive once bluetooth is switched on or off in your activity class. for your reference :
public void onCreate() {
IntentFilter filter1 = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
IntentFilter filter2 = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
IntentFilter filter3 = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
this.registerReceiver(mReceiver, filter1);
this.registerReceiver(mReceiver, filter2);
this.registerReceiver(mReceiver, filter3);
}
//The BroadcastReceiver that listens for bluetooth broadcasts
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
... //Device found
}
else if (BluetoothAdapter.ACTION_ACL_CONNECTED.equals(action)) {
... //Device is now connected
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
... //Done searching
}
else if (BluetoothAdapter.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) {
... //Device is about to disconnect
}
else if (BluetoothAdapter.ACTION_ACL_DISCONNECTED.equals(action)) {
... //Device has disconnected
}
once you receives the status do your functionality .. done !!

Detect when bluetooth device disappears on Android

I'm creating a simple application that will communicate via Bluetooth. I have already created a simple Activity that lists the nearby devices with bluetooth turned on but unfortunately I can't figure out how could I detect when some devices disappear from the bluetooth network (bt gets turned off) so that I could remove that item from the list.
This is my code I wrote to add nearby BT devices to a ListView:
mNewDevicesArrayAdapter = new BluetoothDeviceArrayAdapter(this, 0, new ArrayList<BluetoothDevice>());
lvDiscovered = (ListView)findViewById(R.id.bt_dev_discovered_list);
lvDiscovered.setAdapter(mNewDevicesArrayAdapter);
...
// The BroadcastReceiver that listens for discovered devices and
// changes the title when discovery is finished
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// If it's already paired, skip it, because it's been listed already
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
mNewDevicesArrayAdapter.add(device);
}
// When discovery is finished, change the Activity title
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
// TODO show no devices found!
}
}
};
I found no applicable ACTION intent of the case when a device gets disappeared. Maybe ACTION_DISCOVERY_FINISHED could be used, but how?
Thanks in advance!
I found an easy way to remove those devices from the list that was previously discovered.
Extending my code above I introduced an update list where I'm storing the newly discovered devices. When ACTION_DISCOVERY_FINISHED appears I'll update the ListView with this update list.
...
private ArrayList<BluetoothDevice> btDevicesUpdateList;
...
// The BroadcastReceiver that listens for discovered devices and
// changes the title when discovery is finished
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// If it's already paired, skip it, because it's been listed already
// in the paired devices list
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
if(mNewDevicesArrayAdapter.getCount() == 0){
// if the list is empty we add the device immediately to it
mNewDevicesArrayAdapter.add(device);
}
btDevicesUpdateList.add(device);
}
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
mNewDevicesArrayAdapter.setItems(btDevicesUpdateList);
btDevicesUpdateList.clear();
mBtAdapter.startDiscovery();
}
}
}
// BluetoothDeviceArrayAdapter.java
public void setItems(ArrayList<BluetoothDevice> items){
this.items.clear();
this.items.addAll(items);
}
Devices that are unavailable will not be in the list.

Is there any other way to discover Bluetooth apart from using BroadcastReceiver?

I have created a BroadcastReceiver for BluetoothDevice.ACTION_FOUND in a Service to scan and Log the Bluetooth Device available. Part of this Service is to keep on checking every 30 seconds if the any of the previously found bluetooth devices is still available or not. Currently it throws me an error for Leaked IntendReceiver, I can fix that error, however I am just not convinced this is the right way to do this.
I am creating a new thread to handle bluetooth scanning, creating a while loop which runs every 30 seconds and inside that loop registering the BroadcastReceiver, putting thread on sleep, by the time sleep time is over the onReceive gives me results of the current scan, then I unregister BroadcastReceiver and repeat the loop.
I am unregistering the BroadcastReceiver after every single completion of while loop because the next scan gives me list of currently available devices and then I compare that with previous scan's data.
It is fulfilling my requirement however I have a strong feeling that its not the correct design. Could you please advice me on an alternate approach? Thanks..
Below is the relevant code from the Service-
class ScanBT extends Thread
{
static final long DELAYBT = 30000;
#Override
public void run()
{
isBTRunning = true;
Looper.prepare();
BluetoothAdapter mBluetoothAdapter =BluetoothAdapter.getDefaultAdapter();
try {
Log.d(TAG, "BT Scanning started");
while(isBTRunning)
{
if (!mBluetoothAdapter.isEnabled())
{
mBluetoothAdapter.enable();
Thread.sleep(15000);
}
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
mBluetoothAdapter.startDiscovery();
Log.d(TAG,"Inside while loop for BT");
Thread.sleep(DELAYBT);
unregisterReceiver(mReceiver);
}
Looper.loop();
}
catch (InterruptedException e) {
Log.d(TAG, "BT Scanning stopped");
Looper.myLooper().quit();
}
}
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
BTDevice = device.getName();
BTAddress = device.getAddress();
Log.d(TAG,"BT Found name: " + BTDevice);
Log.d(TAG,"BT Found address: " + BTAddress);
//Code to compare with previous scan results
}
}
};
Figured it out. There is no other way to achieve this. To keep the performance under control, I am now registering the receiver only once and then starting the discovery inside a loop with a sleep interval of 60 seconds.

Categories

Resources