I am recently learning Android. I tried to implement the function that searches for Bluetooth devices. I am able to list all the previously paired devices, but I am not able to discover new devices.
Permissions are set in AndroidManifest.xml.
Here is my code:
public void listDiscoverableDevices(boolean status) {
// Create a BroadcastReceiver for ACTION_FOUND
mBluetoothAdapter.cancelDiscovery();
mArrayAdapter.clear();
mDisplay.setText("Search");
mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//BluetoothDevice.
if(BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
mArrayAdapter.add(device.getAddress());
} else if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
//mDisplay.setText(action);
mArrayAdapter.add(action);
} else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
//mDisplay.setText(action);
mArrayAdapter.add(action);
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
if(!mBluetoothAdapter.startDiscovery()) {
mDisplay.setText("Discover failed!");
}
}
It seems to me that the BluetoothDevice.ACTION_FOUND action is never received. I have been struggling with this for two days. Any idea?
It took me two days. Today I finally found out that why my program didn't work the first time. Starting from Android 6.0, you also need either android.permission.ACCESS_FINE_LOCATION or android.permission.ACCESS_FINE_LOCATION permission to scan for remote Bluetooth devices.
And you may need to go to "Settings"->"Apps"->yourApp->"Permissions" to turn on the location service permission. Or I guess you can also request the permission programmatically.
Related
I have a bluetooth device.
If:
They have already paired and connected to the device
it becomes unplugged
then it becomes plugged back in
I would like to auto-connect to it. That's why I'm listening to ACTION_FOUND.
My code is fairly simple. The ACTION_BOND_STATE_CHANGED and ACTION_ACL_DISCONNECTED work just fine. I am completely unable to get the ACTION_FOUND to catch though. My "INTENT RECEIVED" log message never prints…
I feel like I am missing something simple. Thanks!
public void registerReceiver() {
if (BuildConfig.DEBUG) Log.e(TAG, "REGISTERING RECEIVER");
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
mainActivity.registerReceiver(receiver, filter);
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BuildConfig.DEBUG) Log.e(TAG, "INTENT RECEIVED: " + String.valueOf(action));
if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// … some stuff …
} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
autoConnectDevice();
} else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
disconnectDevice();
}
}
};
public void unregisterReceiver() {
if (BuildConfig.DEBUG) Log.e(TAG, "UNREGISTERING RECEIVER");
mainActivity.unregisterReceiver(receiver);
}
I believe the ACTION_FOUND event only fires when you are running device discovery with the intent to pair your device to another. It would not fire when an already paired device comes back into range. Unfortunately, there does not appear to be an event for the case that you want.
Your best bet will be to start an AsycTask or Thread when the connection is lost and try to reconnect until successful or until you hit an arbitrary time limit and give up.
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.
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
I have written my first Android app and everything is working really well, except...in the routine, below, the ACTION_DISCOVERY_FINISHED never seems to get called (or broadcast or received or whatever). No matter what the block of code in that "else if" is not working.
I have only tested on my Motorola Atrix, so I am wondering if that is the issue. Since I am testing bluetooth functionality, I don't think I can use the Android emulator for effective testing.
Thoughts?
private BluetoothAdapter mBtAdapter;
mBtAdapter.startDiscovery();
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)) {
//do something
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
//do something else
}
}
}
2 possibles solutions:
Instead of creating an annonymous receiver, subclass BroadcastReceiver with just the same implementation, then declare it in your project manifest (Remember to declare that your receiver receives these actions you want).
Dynamically register it from your activity/service, this way:
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);
I'm not sure if you have to unregister it when registering it from an activity/service (I know you have to when registering from app's context) so check it out.
You need to add the line
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
to your manifest
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