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
BroadcastReceiver not called on bluetooth pairing
Hi you need to register you broadcast receiver for following filters
ACTION_BOND_STATE_CHANGED
and then in onReceive
add them like this
if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)){
mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (mDevice .getBondState() == BluetoothDevice.BOND_BONDED) {
//means device paired
}
}
Read more Here Bluetooth Device Page
int BOND_BONDED //Indicates the remote device is bonded (paired).
int BOND_BONDING //Indicates bonding (pairing) is in progress with the remote device.
int BOND_NONE //Indicates the remote device is not bonded (paired).
Edit: after last Comment
you also need to add
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
registerReceiver(mReceiver, filter);
Broadcast Receiver inside an object or inside a service?
Android Broadcast Receiver bluetooth events catching
It seems that what I was looking for it was:
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);
with this, when the adapter is scanning is trigered.
Broadcast if a bluetooth device is connecting/disconnecting?
<intent-filter>
<action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
</intent-filter>
These are the filters you have to add with your broadcast receiver.
ACL_CONNECTED
signals when bluetooth is connected and ACL_DISCONNECTED
signals bluetooth disconnection
For specific device you have to check intents/context in broadcast receiver
The two permission you have to add are:
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
I think this should solve your problem.
setting up broadcast Receiver to turn on bluetooth
BatteryManager: Seems like using the ACTION_BATTERY_CHANGED intent is the way to go, and setting up a broadcast receiver for when this changes. Is it correct?
Yes, that is one way to monitor things like when a charger has been connected (including plugging to a USB port with charge capability). You can also use ACTION_POWER_CONNECTED
.
is plugging in the phone a explicit user action?
NO - most definitely not unless you create a pop-up asking for the user's consent. To quote the docs for the enable()
method...
Bluetooth should never be enabled without direct user consent. If you want to turn on Bluetooth in order to create a wireless connection, you should use the ACTION_REQUEST_ENABLE Intent, which will raise a dialog that requests user permission to turn on Bluetooth. The enable() method is provided only for applications that include a user interface for changing system settings, such as a "power manager" app.
When I plug my device to charge, 9 times out of 10 I don't want it to do anything but charge. If I had your app installed on my phone and found out it was enabling Bluetooth silently and without my knowledge, your app would be un-installed straight away.
There are known security issues with Bluetooth and, depending on user settings, you could put somebody's device at risk if it is enabled without their knowledge.
Can an intent be a method, and not just activity?
No, an Intent
is part of a messaging system. See Intents and Intent Filters. Yes, I know it's not very 'newbie-friendly' but Android is a complex beast and if you really want to program successfully for it you've got to read this sort of stuff.
BroadcastReceiver onRecive does not work correctly
Please turn on GPS and try again. Please make sure that you ask Location permission to your user.
Reason: From Android 6.0 you need Location permission for Bluetooth Discovery.
More reference:
- https://developer.android.com/guide/topics/connectivity/bluetooth
- https://getlief.zendesk.com/hc/en-us/articles/360007600233-Why-does-Android-require-Location-Permissions-for-Bluetooth-
Can't call a Bluetooth BroadcastReceiver method in a Service
maybe the fact that your receiver is static causing the problem.
BroadcastReceiver
should never be static. it can cause lots of problems.
other really bad design problem with your code - holding reference to activity inside service, and using it to modify views is really wrong thing to do. it can cause easily to memory leek.
the right why to communicate between Service
and Activity
is by implement android's Messanger
, or sending broadcasts between them via BroadcastReceiver
.
if you'll listen to my advice - you won't be have to make your receiver static (I guess you've made it static only because you are using the mActivity static instance inside)
and I'm pretty sure it will solve your problem
you can read about Messanger
here: http://developer.android.com/reference/android/os/Messenger.html
sure you'll find lots of usage examples in the net.
example of broadcasting updates to the activity from service:
public class MyService extends Service {
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
super.onCreate();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
this.registerReceiver(bluetoothReceiver, intentFilter);
}
@Override
public void onDestroy() {
if (bluetoothReceiver != null) {
this.unregisterReceiver(bluetoothReceiver);
}
super.onDestroy();
}
public BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
updateUIWithNewState(state);
}
}
};
protected void updateUIWithNewState(int state) {
Intent intent = new Intent("serviceUpdateReceivedAction");
intent.putExtra("state", state);
sendBroadcast(intent);
}
}
and that's the activity:
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(mServiceUpdatesReceiver, new IntentFilter("serviceUpdateReceivedAction"));
}
@Override
protected void onPause() {
unregisterReceiver(mServiceUpdatesReceiver);
super.onPause();
}
private BroadcastReceiver mServiceUpdatesReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra("state", -1);
// do what ever you want in the UI according to the state
}
};
}
Related Topics
How to Change a Layer-List Drawable
How to Set Time to Device Programmatically
How to Solve Execution Failed for Task ':App:Compileflutterbuilddebug'
Gradle Dsl Method Not Found: 'Runproguard'
Bypass Android Usb Host Permission Confirmation Dialog
Sqlite Android Database Cursor Window Allocation of 2048 Kb Failed
Using Seekbar to Control Volume in Android
Converting Bitmap to Bytearray Android
How to Change Default Images of Checkbox
Connecting 2 Emulator Instances in Android
Android - Getting Audio to Play Through Earpiece
How to Transfer an Image from Its Url to the Sd Card
How Can Make My Viewpager Load Only One Page at a Time Ie Setoffscreenpagelimit(0);
What Is the Purpose of Android's <Merge> Tag in Xml Layouts
Android: Share Plain Text Using Intent (To All Messaging Apps)
Best Practice for Defining Button Events in Android
Encryption Error on Android 4.2
"Realm Migration Needed", Exception in Android While Retrieving Values from Realm Db