Problem: I am being notified when a bluetooth device is pairing, or becomes paired. However, I do not know how to get notified when a device is being unpaired. How could I get my app to recognize when it has become unpaired with my device?
Example: Let's say that I pair my surface tablet and my android phone through code. My broadcast receiver will register the ACTION_BOND_STATE_CHANGED intent and allow me to process it however I want. Now, if I want to unpair my surface tablet, I do not get notified on my phone that the device has become unpaired. If I check, device.getBondState() for the device after it has been unpaired, it equals BOND_BONDED (which it clearly isnt) I can get it to recognize it is unpaired again after I try to connect to the unpaired device, then the app crashes and then when I turn the app on again, only then does it recognize it as unpaired.
Scenario: I have a BroadcastReceiver registered to listen for intents caused by a BluetoothDevice
getActivity().registerReceiver(broadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
getActivity().registerReceiver(broadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
getActivity().registerReceiver(broadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED));
getActivity().registerReceiver(broadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
I process these Actions with this BroadcastReciever:
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
System.out.println("ACTION: "+ action);
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
list();
// Get the BluetoothDevice object from the intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
System.out.println("FOUND: " + device.getName() + " STATE: " + device.getBondState());
mapInput(device);
// Add the name and the mac address of the object to the array adapter
BTSimpleAdapter.notifyDataSetChanged();
} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
System.out.println("UPDATE Name " + device.getName() + " Value " + device.getAddress() + " Bond state " + device.getBondState());
for (Map<String, String> entry : data) {
if (entry.get("Name").equals(device.getName()) && entry.get("Value").equals(device.getAddress())) {
if (device.getBondState() == BluetoothDevice.BOND_NONE) {
entry.put("Paired", "Unpaired");
} else if (device.getBondState() == BluetoothDevice.BOND_BONDING) {
entry.put("Paired", "Pairing");
} else {
entry.put("Paired", "Paired");
}
BTSimpleAdapter.notifyDataSetChanged();
}
}
}
}
};
Related
I am trying to make an android application about localization, i am trying however to make a list of Bluetooth devises found by my smartphone and refresh that lists information every 10 seconds. I want to do that because I am also recording the signal strength (RSSI) and want to record when a beacon is getting out of range when moved or the signal is getting weaker. So refreshing the list will help with that. I have provided some of my code below.
#Override protected void onResume() {
super.onResume();
registerReceiver(devicesFoundReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
registerReceiver(devicesFoundReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED));
registerReceiver(devicesFoundReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
}
private final BroadcastReceiver devicesFoundReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int rssid = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
listAdapter.add(device.getName() + "\n" + device.getAddress() + "\n" + " RSSI: " + rssid + "dBm");
listAdapter.notifyDataSetChanged();
}else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
scanningButton.setText("Scan Bluetooth Devices");
}else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
scanningButton.setText("Scanning in progress ...");
}
}
};
use a listview then call notifyDataSetChanged() on your Adapter object
I want the device which user selects in list paired. in program search in bluetooth device and show list of bluetooth device to user.
if(ba.isEnabled()){
if (ba.isDiscovering()) {
ba.cancelDiscovery();
}
ba.startDiscovery();
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);
// Add the name and address to an array adapter to show in a ListView
arr.add(device.getName() + "\n" + device.getAddress());
adapter.notifyDataSetChanged();
adapter.notifyDataSetInvalidated();
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
}
Go in your sdk>sample>android-7>BluetoothChat .import BluetoothChat demo app in your eclipse.It will be helpfull for you
I am trying to write a small android app (4.4) which searches for several Bluetooth LE devices. Once it has found each device it needs to connect to it and then continually read the RSSI of each device as quickly as it can. I have been trying to get this to work with 6 devices. My current code is as follows:
public class BluetoothGatt extends Activity {
private BluetoothAdapter mBluetoothAdapter;
private static final int REQUEST_ENABLE_BT = 1;
int count = 0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
// Initializes Bluetooth adapter.
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
System.out.println("Adapter: " + mBluetoothAdapter);
BTScanStart();
}
// Start the Bluetooth Scan
private void BTScanStart() {
if (mBluetoothAdapter == null) {
System.out.println("Bluetooth NOT supported. Aborting.");
return;
} else {
if (mBluetoothAdapter.isEnabled()) {
System.out.println("Bluetooth is enabled...");
// Starting the device discovery
mBluetoothAdapter.startLeScan(mLeScanCallback);
}
}
}
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) {
count++;
System.out.println("Found " + count + ":" + device + " " + rssi + "db");
device.connectGatt(null, false, mGattCallback);
if (count > 5) mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
};
// Gatt Callback
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
System.out.println(gatt.getDevice() + ": Connected.. ");
gatt.readRemoteRssi();
}
if (newState == BluetoothProfile.STATE_DISCONNECTED) {
System.out.println(gatt.getDevice() + ": Disconnected.. ");
}
}
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
System.out.println(gatt.getDevice() + " RSSI:" + rssi + "db ");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
gatt.readRemoteRssi();
}
};
}
I am having the following problems:
1) It connects to the devices successfully, but they all disconnect after around 5 seconds with a 'btm_sec_disconnected - Clearing Pending flag' error. Is there a was to keep them connected?
2) The code works fine for a single device, however when using more than one device only one device prints RSSI updates regularly, others update randomly and some don't update at all.
3) I am not sure what context I should supply when calling device.connectGatt .
Thank you in advance for your thoughts!
For the RSSI issue I will second Sam's answer (https://stackoverflow.com/a/20676785/4248895). It seems that for your use case continuously scanning should be sufficient. You don't want to add the overhead of connection if you can avoid it.
I will answer your other question in that if you do need to connect to these devices for some reason, your stability issues may be related to the fact that you're connecting and scanning simultaneously. Generally speaking, you should not perform any two gatt operations (scanning, connecting, reading, writing, etc.) at the same time.
How about just use startLeScan and get rssi?
If your android device filter the ble devices (like nexus 7), you could stopLeScan/ startLeScan repeatedly.
If not(like samsung s4 with android 4.3), just let it scan, onLeScan(...) will give every devices' rssi continuously.
I am developing a android application using Eclipse to return the RSSI values of a Bluetooth device. I have modified the Android Bluetooth Chat example to fit my needs, but I am having problems returning the RSSI value. After hitting the scan button to discover nearby devices it returns the device name, device address, and is also suppose to return the RSSI value but instead it says null for the RSSI.
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress() + getRssi());
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
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);
// Get the Bluetooth RSSI
short Rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
// If it's already paired, skip it, because it's been listed already
// Added getRssi()
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress() + getRssi());
}
// When discovery is finished, change the Activity title
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
setProgressBarIndeterminateVisibility(false);
setTitle(R.string.select_device);
if (mNewDevicesArrayAdapter.getCount() == 0) {
String noDevices = getResources().getText(R.string.none_found).toString();
mNewDevicesArrayAdapter.add(noDevices);
}
}
}
};
I haven't tried it myself, but maybe this SO answer will help:
https://stackoverflow.com/a/2361630/831918
Supposedly it is possible using the NDK. Good luck!
This is how I am getting RSSI
String deviceRSSI =
(intent.getExtras()).get(BluetoothDevice.EXTRA_RSSI).toString();
private final BroadcastReceiver ActionFoundReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceRSSI = (intent.getExtras()).get(BluetoothDevice.EXTRA_RSSI).toString();
btArrayAdapter.add(device.getName() + "\n" + device.getAddress() + "\n" + deviceRSSI);
btArrayAdapter.notifyDataSetChanged();
}
if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_STARTED)) {
} else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
}
}
};
I am implementing Bluetooth support via implementing a task which searches for devices in the background and provides a list when the search is complete. However, this list occasionally contains a No devices found entry (added only when ACTION_DISCOVERY_FINISHED is received with no devices already in the list) before listing other devices!
private BroadcastReceiver mBlueToothInfoDiscoveryListener = new BroadcastReceiver() {
/**
* This is an overridden function called by the framework whenever there
* is some broadcast message for Bluetooth info discovery listener
*/
#Override
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);
// If it's already paired, skip it, because it's been listed
// already
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
mNewBtDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
// When discovery is finished, change the Activity title
setProgressBarIndeterminateVisibility(false);
setTitle("device list");
if (mNewBtDevicesArrayAdapter.getCount() == 0) {
String noDevices = "No devices found";
mNewBtDevicesArrayAdapter.add(noDevices);
}
}
}
};
I don't expect ACTION_DISCOVERY_FINISHED to ever come before a ACTION_FOUND event, so why would the No devices found string be added to the list before a device is located?
Simply because the discovery task has a timeout to prevent endless searched. So, in case there is no available device around, you'll get your "No Devices found"...