How to detect Bluetooth state change using a broadcast receiver?
AS far as permissions go, to detect the state change of bluetooth you need to add this to your AndroidManifest.xml.
<uses-permission android:name="android.permission.BLUETOOTH" />
An example receiver would look like this, you add this code to where you want to handle the broadcast, for example an activity:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive (Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
if(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)
== BluetoothAdapter.STATE_OFF)
// Bluetooth is disconnected, do handling here
}
}
};
To use the receiver, you need to register it. Which you can do as follows. I register the receiver in my main activity.
registerReceiver(this, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
You could also decide to add all of it to your AndroidManifest.xml. This way you can make a special class for the receiver and handle it there. No need to register the receiver, just make the class and add the below code to the AndroidManifest
<receiver
android:name=".packagename.NameOfBroadcastReceiverClass"
android:enabled="true">
<intent-filter>
<action android:name="android.bluetooth.adapter.action.STATE_CHANGED"/>
</intent-filter>
</receiver>
Android Broadcast Receiver bluetooth events catching
In order to catch Bluetooth state changes (STATE_OFF
, STATE_TURNING_ON
, STATE_ON
, STATE_TURNING_OFF
), do this:
First, add Bluetooth permission to your AndroidManifest file:
<uses-permission android:name="android.permission.BLUETOOTH" />
Create a BroadcastReceiver in your Activity or Service:
private final BroadcastReceiver mBroadcastReceiver1 = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
switch(state) {
case BluetoothAdapter.STATE_OFF:
..
break;
case BluetoothAdapter.STATE_TURNING_OFF:
..
break;
case BluetoothAdapter.STATE_ON:
..
break;
case BluetoothAdapter.STATE_TURNING_ON:
..
break;
}
}
}
};
Create an IntentFilter and register it with BroadcastReceiver in your Activity/Service's onCreate()
method:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter1 = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(mBroadcastReceiver1, filter1);
...
}
Unregister BroadcastReceiver in your onDestroy()
method:
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mBroadcastReceiver1);
}
In order to catch changes of discoverability of device (SCAN_MODE_NONE
, SCAN_MODE_CONNECTABLE
, SCAN_MODE_CONNECTABLE_DISCOVERABLE
), create another BroadcastReceiver and register/unregister to your Activity as I mentioned above. Only difference between those BroadcastReceivers is the first one uses BluetoothAdapter.EXTRA_STATE
and the other one uses BluetoothAdapter.EXTRA_SCAN_MODE
. Here is the example code for BroadcastReceiver to catch discoverability changes:
Create an IntentFilter and register it in onCreate()
method:
IntentFilter filter2 = new IntentFilter();
filter2.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter2.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
filter2.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
registerReceiver(mBroadcastReceiver2, filter2);
Create the BroadcastReciver in Activity/Service to catch discoverability changes:
private final BroadcastReceiver mBroadcastReceiver2 = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if(action.equals(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)) {
int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.ERROR);
switch(mode){
case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
..
break;
case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
..
break;
case BluetoothAdapter.SCAN_MODE_NONE:
..
break;
}
}
}
};
And lastly unregister BroadcastReciver in onDestroy()
:
unregisterReceiver(mBroadcastReceiver2);
Note that, you don't need to add any <intent-filter>
or <receiver>
to your AndroidManifest file, except you need to add Bluetooth permission of course.
If you want to catch (ACTION_ACL_CONNECTED
, ACTION_ACL_DISCONNECTED
, ACTION_ACL_DISCONNECT_REQUESTED
), now you need to add an <intent-filter>
to your AndroidManifest file:
<intent-filter>
<action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
</intent-filter>
Create filter and register it in onCreate()
method:
IntentFilter filter3 = new IntentFilter();
filter3.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter3.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(mBroadcastReceiver3, filter3);
Then create the BroadcastReceiver in your Activity/Service:
private final BroadcastReceiver mBroadcastReceiver3 = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action){
case BluetoothDevice.ACTION_ACL_CONNECTED:
..
break;
case BluetoothDevice.ACTION_ACL_DISCONNECTED:
..
break;
}
}
};
And lastly, unregister:
unregisterReceiver(mBroadcastReceiver3);
If you want to read more about state constants, this is from the documentation:
public static final String EXTRA_STATE:
Used as an int extra field in ACTION_STATE_CHANGED intents to request
the current power state. Possible values are: STATE_OFF,
STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFFpublic static final String EXTRA_SCAN_MODE:
Used as an int extra field in ACTION_SCAN_MODE_CHANGED intents to
request the current scan mode. Possible values are: SCAN_MODE_NONE,
SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE_DISCOVERABLE
Detect Enable/Disable Bluetooth
To detect the state change of bluetooth you need to add following permission to your AndroidManifest.xml.
<uses-permission android:name="android.permission.BLUETOOTH" />
Use a Local broadcast preferably. You do not need to register it in Manifest . register it at runtime where you need it.(If need throughout the app then register it in Manifest)
private final BroadcastReceiver bStateReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_OFF) {
// Bluetooth is disconnected, do handling here
}
}
}
};
Runtime register:
LocalBroadcastManager.getInstance(this).registerReceiver(bStateReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
Runtime unregister : Don't forget to unregister the broadcast.
LocalBroadcastManager.getInstance(this).unregisterReceiver(bStateReceiver);
Static Register:
<receiver
android:name=".FullyQualifiedBroadcastReceiverClassName"
android:enabled="true">
<intent-filter>
<action android:name="android.bluetooth.adapter.action.STATE_CHANGED"/>
</intent-filter>
How to track BluetoothAdapter state changes dynamically in Jetpack Compose?
I was able to solve this just by using mutableStateOf
. It doesn't have to be initialized inside of a @Composable
function to be reactive, which is what I misunderstood in the first place.
- Define a
mutableStateOf
value and aBroadcastReceiver
that will track the state ofBluetoothAdapter
. When Bluetooth state changes, update the value.
private var isBluetoothEnabled = mutableStateOf(false)
private val mReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.action == BluetoothAdapter.ACTION_STATE_CHANGED) {
when (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
BluetoothAdapter.STATE_OFF -> {
isBluetoothEnabled.value = false
Log.i("Bluetooth", "State OFF")
}
BluetoothAdapter.STATE_ON -> {
isBluetoothEnabled.value = true
Log.i("Bluetooth", "State ON")
}
}
}
}
}
- Inside of a
@Composable
function, use this value as usual:
@Composable
private fun MainScreen(
isBluetoothEnabled: Boolean
) {
if (isBluetoothEnabled) {
// Display some UI
} else {
// Display different UI
}
}
And that's it!
Detecting state changes made to the BluetoothAdapter?
You will want to register a BroadcastReceiver
to listen for any changes in the state of the BluetoothAdapter
:
As a private instance variable in your Activity
(or in a separate class file... whichever one you prefer):
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.ERROR);
switch (state) {
case BluetoothAdapter.STATE_OFF:
setButtonText("Bluetooth off");
break;
case BluetoothAdapter.STATE_TURNING_OFF:
setButtonText("Turning Bluetooth off...");
break;
case BluetoothAdapter.STATE_ON:
setButtonText("Bluetooth on");
break;
case BluetoothAdapter.STATE_TURNING_ON:
setButtonText("Turning Bluetooth on...");
break;
}
}
}
};
Note that this assumes that your Activity
implements a method setButtonText(String text)
that will change the Button
's text accordingly.
And then in your Activity
, register and unregister the BroadcastReceiver
as follows,
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* ... */
// Register for broadcasts on BluetoothAdapter state change
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(mReceiver, filter);
}
@Override
public void onDestroy() {
super.onDestroy();
/* ... */
// Unregister broadcast listeners
unregisterReceiver(mReceiver);
}
Related Topics
Change Device Language via Adb
Android 5.0: How to Change Recent Apps Title Color
How to Add PDFbox to an Android Project or Suggest Alternative
Android 4.4 Giving Err_Cache_Miss Error in Onreceivederror for Webview Back
Folder Added on Android Is Not Visible via Usb
Noclassdeffounderror Below Sdk 21
Firebase Authentication Not Working in Signed APK
Detecting Gps On/Off Switch in Android Phones
How to Set Text of Text View in Another Thread
How to Create Multiple Pendingintents with the Same Requestcode and Different Extras
Setting a Maximum Width on a Viewgroup
How to Check If Running on UI Thread in Android
Android App Integrated with Ok Google
How to Force a Cache Clearing Using Universal Image Loader Android