How to make the android Bluetooth keep scanning - android

Hi this is my first time posting.
Im making an android application that only discover Bluetooth device by using the friendly name and the mac address . Not pairing.
The problem im facing is my device fail to detect new device that enter the range after is start the scan about 10 to 12 second.
final BroadcastReceiver bReceiver = 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 the MAC address of the object to the arrayAdapter
// System.out.println(device.getAddress());
for(int i=0;i<listmac.size();i++)
{
if(listmac.get(i).equals(device.getAddress())){
System.out.println(listname.get(i));
myListView.setItemChecked(i, true);
}
}
}
}
};
public void find(View view) {
if (myBluetoothAdapter.isDiscovering()) {
// the button is pressed when it discovers, so cancel the discovery
myBluetoothAdapter.cancelDiscovery();
}
else {
myBluetoothAdapter.startDiscovery();
registerReceiver(bReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
isBreceiverRegisted = true;
}
}
public void off(){
myBluetoothAdapter.disable();
Toast.makeText(getApplicationContext(),"Bluetooth turned off",
Toast.LENGTH_LONG).show();
}
Sorry for my broke english

Simply because the discovery task has a timeout to prevent endless searched.
To be able to detect that discovery ended you need add this intent
if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
// When discovery is finished , start discovery again
myBluetoothAdapter.startDiscovery();
}
}
Be very careful in general about accidentally leaving your device in discovery-mode. Performing device discovery is a heavy procedure for the Bluetooth adapter and will consume a lot of its resources.

Related

Strange behaviour with bluetooth discovery

I am implementing an app with bluetooth.Here I am facing a strange problem.I want to show all the devices available when I scan my bluetooth.But my app is only discovering the bluetooth`s of pc.The bluetooth of mobile phones or tabs are not showing.To implement bluetooth functionality I have used this tutorial.Here is the code to find bluetooth devices:
final BroadcastReceiver bReceiver = 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 the MAC address of the object to the arrayAdapter
BTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
BTArrayAdapter.notifyDataSetChanged();
}
}
};
public void find(View view) {
if (myBluetoothAdapter.isDiscovering()) {
// the button is pressed when it discovers, so cancel the discovery
myBluetoothAdapter.cancelDiscovery();
}
else {
BTArrayAdapter.clear();
myBluetoothAdapter.startDiscovery();
registerReceiver(bReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
}
}
I have searched google but did not find any solution.Any help will be great.
First be sure that Bluetooth is enabled on the other devices. Then make the other devices discoverable. There should be an option in the bluetooth menu to make the device discoverable. The device will only be discoverable temporarily (usually about 2 minutes).

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.

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.

How identify *which* bluetooth device causes an ACTION_ACL_CONNECTED broadcast?

I want to listen for connection/disconnection with a number of specific bluetooth devices whose MAC addresses I know, but which are not necessarily paired (I don't want to mess with the user's list of paired devices and vice versa). I'm only interested in discovering their presence, not communicating with them.
This works very well with my code below! But my problem is that I cannot find out which specific device is connecting/disconnecting, only that it happens to someone of them. How can I find out which one the action concerns?
First I instantiate objects for my two specific physical bluetooth devices and add them to my intent filter:
BluetoothDevice myPinkHeadset = mBluetoothAdapter.getRemoteDevice("18:17:0C:EB:9C:81");
BluetoothDevice myPcBluetoothDongle = mBluetoothAdapter.getRemoteDevice("5A:7A:CC:4B:C5:08");
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(myPinkHeadset.ACTION_ACL_CONNECTED);
intentFilter.addAction(myPinkHeadset.ACTION_ACL_DISCONNECTED);
intentFilter.addAction(myPcBluetoothDongle.ACTION_ACL_CONNECTED);
intentFilter.addAction(myPcBluetoothDongle.ACTION_ACL_DISCONNECTED);
Then I listen for broadcasts about them:
final BroadcastReceiver intentReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Now I want to find out which one has been connected and/or disconnected, and I don't see how I can do that.
Either 1) I use "BluetoothDevice" directly. It reacts to the broadcast alright, but it doesn't tell me which of the two physical devices the action concerns. Is their a way to find out? Bluetooth.getName() is not allowed because it's not a static class.
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
}
or 2) I listen for both actions for both devices.
if (myPinkHeadset .ACTION_ACL_CONNECTED.equals(action)) {
Log.v(TAG, "Connected to myPinkHeadset ");
}
else if (myPinkHeadset .ACTION_ACL_DISCONNECTED.equals(action)) {
Log.v(TAG, "Disconnected from myPinkHeadset ");
}
else if (myPcBluetoothDongle .ACTION_ACL_CONNECTED.equals(action)) {
Log.v(TAG, "Connected to myPcBluetoothDongle ");
}
else if (myPcBluetoothDongle .ACTION_ACL_DISCONNECTED.equals(action)) {
Log.v(TAG, "Disconnected from myPcBluetoothDongle ");
But then it logs that it connects with myPinkHeadset even if it is myPvBluetoothDongle I activate physically. It always goes for the one which comes first of the if tests. It cares only about the action itself, not about which object it concerns.
I saw that EXTRA_DEVICE is "Used as a Parcelable BluetoothDevice extra field in every intent broadcast by this class." But it only returns null to me:
String extra = intent.getStringExtra(BluetoothDevice.EXTRA_DEVICE);
This gives the device connected to:
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
As a newbie, I misunderstood the parcelable concept. EXTRA_DEVICE is a String, but it's just a tag for the object. So there's no need to register or listen to individual instances of BluetoothDevice. When an action is broadcasted, the intent will tell which physical device caused it. (Can I +1 myself for this :-D)
intentFilter.addAction(myPinkHeadset.ACTION_ACL_CONNECTED);
intentFilter.addAction(myPcBluetoothDongle.ACTION_ACL_CONNECTED);
and
intentFilter.addAction(myPinkHeadset.ACTION_ACL_DISCONNECTED);
intentFilter.addAction(myPcBluetoothDongle.ACTION_ACL_DISCONNECTED);
are the same value. It's static value.
BluetoothDevice.ACTION_ACL_CONNECTED and BluetoothDeviceACTION_ACL_DISCONNECTED
private void register() {
context.registerReceiver(bluetoothBroadCast, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
context.registerReceiver(bluetoothBroadCast, new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED ));
}
private final BroadcastReceiver bluetoothBroadCast = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action) {
case BluetoothDevice.ACTION_ACL_CONNECTED: {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(device.getAddress().equals(myPinkHeadset.getAddress)) {
//Do what you want
}
break;
}
case BluetoothDevice.ACTION_ACL_DISCONNECTED: {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
break;
}
}
}
};
I hope this can help you

How to detect if bluetooth device is connected

In android how can my Activity will get to know if a Bluetooth A2DP device is connected to my device.
Is there any broadcast receiver for that?
How to write this broadcast receiver?
Starting from API 11 (Android 3.0) you can use BluetoothAdapter to discover devices connected to a specific bluetooth profile. I used the code below to discover a device by its name:
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.A2DP) {
boolean deviceConnected = false;
BluetoothA2dp btA2dp = (BluetoothA2dp) proxy;
List<BluetoothDevice> a2dpConnectedDevices = btA2dp.getConnectedDevices();
if (a2dpConnectedDevices.size() != 0) {
for (BluetoothDevice device : a2dpConnectedDevices) {
if (device.getName().contains("DEVICE_NAME")) {
deviceConnected = true;
}
}
}
if (!deviceConnected) {
Toast.makeText(getActivity(), "DEVICE NOT CONNECTED", Toast.LENGTH_SHORT).show();
}
mBluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, btA2dp);
}
}
public void onServiceDisconnected(int profile) {
// TODO
}
};
mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.A2DP);
You can do that for every bluetooth profile. Take a look at Working with profiles in Android's guide.
However, as written in other answers, you can register a BroadcastReceiver to listen to connection events (like when you're working on android < 3.0).
You cannot get the list of connected devices by calling any API.
You need instead to listen to the intents ACTION_ACL_CONNECTED, ACTION_ACL_DISCONNECTED that notifies about devices being connected or disconnected.
No way to get the initial list of connected devices.
I had this problem in my app and the way I handle it (didn't find better...) is to bounce off/on the Bluetooth at application start to be sure to start with an empty list of connected devices, and then listen to the above intents.
muslidrikk's answer is broadly correct; however you can alternatively use fetchUUIDsWithSDP() and see what you get back... it's a bit of a hack though -- you'd have to know what UUIDs (capabilities) you could expect from the device, if it were turned on. And that might be difficult to guarantee.
For BluetoothHeadset specifically, you can call getConnectedDevices() to get connected devices for this specific profile.
Reference: http://developer.android.com/reference/android/bluetooth/BluetoothHeadset.html
Other cases you need to register a receiver for that.
In your activity, define broadcast receiver...
// Create a BroadcastReceiver for ACTION_FOUND
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);
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy

Categories

Resources