Android auto pair (bond) Bluetooth (BLE) device with pin code - android

I'm trying to pair a Bluetooth (BLE) device without user interaction - meaning that the pairing will be done only programmatically, and the user will not choose Bluetooth device and will not enter the pin code.
I'm using the following code:
//request receiver
IntentFilter pairingRequestFilter = new
IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
pairingRequestFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY - 1);
this.registerReceiver(mPairingRequestRecevier, pairingRequestFilter);
BluetoothManager bluetoothManager = (BluetoothManager)
this.getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
BluetoothDevice mDevice = bluetoothAdapter.getRemoteDevice("macaddress");
mDevice.setPairingConfirmation(true);
mDevice.setPin("1234".getBytes());
mDevice.createBond();
private final BroadcastReceiver mPairingRequestRecevier = new
BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals
(intent.getAction()))
{
final BluetoothDevice device =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int type =
intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
BluetoothDevice.ERROR);
if (type == BluetoothDevice.PAIRING_VARIANT_PIN)
{
device.setPin("1234".getBytes());
abortBroadcast();
}
else
{
}
}
}
};
<!-- permissions -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
Few things happened:
the app tries to pair the device, but I get a toast message - "can't pair the device try again later".
the BroadcastReceiver doesn't get called.
Can someone help me with this issue?

Related

Why my Bluetooth app is not discovering devices with Xamarin C#?

I am building a Bluetooth application in Xamarin Android and my app has three BroadcastReceivers. One for detecting when the adapter has started device discovery ActionDiscoveryStarted, a second one when a Bluetooth device has been discovered ActionFound and a third one for detecting when the device discovery has finished ActionDiscoveryFinished. My application toasts a message to the user when an intent is intercepted from the system. Both the first and the third intents work from the screenshots below.
Now I have a Bluetooth device here and it is the laptop am typing this on, I expected my app to detect my laptop and toast the device found message from the second broadcast receiver but that is not working and it shows 0 devices found. I have all the location and bluetooth permissions in my manifest like
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
and the code for the three broadcast receivers is listed below
DeviceDiscoveryStarted receiver
//register a broadcast for listening when the device discovery process has started
[IntentFilter(new[] { BluetoothAdapter.ActionDiscoveryStarted })]
[BroadcastReceiver(Enabled = true, Exported = false)]
public class DeviceDiscoveryStarted : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action == BluetoothAdapter.ActionDiscoveryStarted)
{
Toast.MakeText(context,"Bluetooth device discovery started",ToastLength.Long).Show();
}
}
}
This receiver is not working despite having mylaptop bluetooth on
DeviceFound receiver
//register a listener for listening when a new bluetooth device has been discovered
[IntentFilter(new[] { BluetoothDevice.ActionFound })]
[BroadcastReceiver(Enabled = true, Exported = false)]
public class DeviceFound : BroadcastReceiver
{
private List<BluetoothDevice> _bluetoothDevices;
//declare the default constructor
public DeviceFound()
{
}
//declare the custom constructor and require the bluetooth device list from the other class
public DeviceFound(List<BluetoothDevice> devicelist)
{
_bluetoothDevices = devicelist;
}
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action == BluetoothDevice.ActionFound)
{
//toast to the user that a bluetooth device has been found
Toast.MakeText(context,"New device found",ToastLength.Long).Show();
//get the device as an extra parcelable
BluetoothDevice device =(BluetoothDevice) intent.GetParcelableExtra(BluetoothDevice.ExtraDevice);
//if device is not equal to null append to the list
if(device!= null)
_bluetoothDevices.Add(device);
}
}
}
ActionDiscoveryFinished reciever
//program a receiver for the intent ACTION_DISCOVERY_COMPLETED
[IntentFilter(new[] { BluetoothAdapter.ActionDiscoveryFinished })]
[BroadcastReceiver(Enabled = true, Exported = false)]
public class DiscoveryFinished : BroadcastReceiver
{
private List<BluetoothDevice> _devices;
//default ctor
public DiscoveryFinished()
{
}
public DiscoveryFinished(List<BluetoothDevice> devices)
{
_devices = devices;
}
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action == BluetoothAdapter.ActionDiscoveryFinished)
{
//toast to the user that the discovery has been finished
Toast.MakeText(context,"Discovery has finished...Found"+_devices.Count,ToastLength.Short).Show();
}
}
}
and this is how I registered my receivers in the OnCreate of my app
//register a receiver for a bluetooth device discovery process started
DeviceDiscoveryStarted started = new DeviceDiscoveryStarted();
RegisterReceiver(started, new IntentFilter(BluetoothAdapter.ActionDiscoveryStarted));
//register a receiver for a bluetooth device discovered
DeviceFound found = new DeviceFound(_bluetoothDevices);
RegisterReceiver(found, new IntentFilter(BluetoothDevice.ActionFound));
//register listener for discovery finished
DiscoveryFinished finished = new DiscoveryFinished(_bluetoothDevices);
IntentFilter filter = new IntentFilter(BluetoothAdapter.ActionDiscoveryFinished);
RegisterReceiver(finished, filter);
The app is working fine, the reason as to why it was not discovering the laptop as a bluetooth device is because it was already a paired device, I made the laptop forget my phone and the device found broadcast receiver worked.

BLE Scan Failed

I am using MI note 4(Android 7.0) and Moto x play (Android 7.1.1)
I am doing BLE scan in sperate service.
While scanning I am getting scan response as "scan failed"
Turning ON/OFF Bluetooth is not affecting in scan response.
Turning ON/OFF Wifi is also not affecting in scan response.
(But in this case android inbuilt(from Settings->Bluetooth) Bluetooth scanning was working fine).
I used BLE scanner app also but that app is also not detecting BLE advertisement!
I tried with Turn ON/OFF airplane mode with this and my device is able to scan without fail.
Scan Function:
mLeScanner.startScan(filters, scanSettings, mScanCallback);
ScanCallback:
ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
Log.e("TAG","onScanResult");
}
#Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Log.e("TAG","onScanFailed");
}
}
ScanSettings:
scanSettings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
filters:
List<ScanFilter> filters = new ArrayList<>();
ScanFilter filter = new ScanFilter.Builder().setDeviceAddress("device address").build();
filters.add(filter);
Beacon Scan filter
ScanFilter.Builder builder = new ScanFilter.Builder();
builder.setManufacturerData(0x004c, new byte[]{});
Anyone have an idea why it only worked with switching airplane mode?
will network affect for BLE scanning?
The error code 0x02 means SCAN_FAILED_APPLICATION_REGISTRATION_FAILED(Fails to start scan as app cannot be registered). This means, before moving to scan we need to initialize Bluetooth adapter
/**
* Initialize BluetoothAdapter
* Check the device has the hardware feature BLE
* Then enable the hardware,
*/
public boolean init(Context context) {
BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
return mBluetoothAdapter != null && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
}
Then register receiver
**
* Register GATT update receiver
*/
private void registerServiceReceiver() {
this.registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
registerReceiver(mReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}
The service initialization method also including in the answer. The Service creation is optional.
/**
* Initialize Bluetooth service.
*/
public void initBLEService(Context context) {
try {
this.mContext = context;
if (mBLEService == null) {
Intent gattServiceIntent = new Intent(mContext, BLEService.class);
if (this.mContext != null) {
isBind = mContext.bindService(gattServiceIntent, mServiceConnection, mContext.BIND_AUTO_CREATE);
}
}
} catch (Exception e) {
AppLog.logError(TAG, e.getMessage());
}
}
I hope you have already added permission in the manifest given below
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
I hope this will help you.
My issue was resolved after user permission ACCESS_COARSE_LOCATION is granted. You could ask user permission in onStart()
Java Syntax
if (ContextCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
PERMISSIONS_REQUEST_LOCATION);
}
Kotlin syntax
if (ContextCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION),
PERMISSIONS_REQUEST_LOCATION)
}

Android Bluetooth enable

I am developing a Bluetooth chat application. The problem is that when i enable Bluetooth the application enables Bluetooth but causes force close. the next time i launch the same application(with Bluetooth enabled) it works smoothly ! i have searched and only got some information saying that when i start the intent for enable Bluetooth the code proceeds not waiting for the result of Intent
public void run() {
// 1. Check if Bluetooth is Enabled
if (!blue.isEnabled()) {
Intent enable_Bluetooth = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enable_Bluetooth, 1);
}
// 2. Start Bluetooth Server
try {
Server = blue.listenUsingRfcommWithServiceRecord("dhiraj",
MY_UUID);
first:
Declare the Bluetooth permission(s) in your application manifest file.
For example:
<manifest ... >
<uses-permission android:name="android.permission.BLUETOOTH" />
...
</manifest>
Setting up bluetooth:
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
}
Enable bluetooth:
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
Finding devices:
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
discovering devices:
// Create a BroadcastReceiver for ACTION_FOUND
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);
// 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
Enabling discovery
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);

Android WIFI How To Detect When Specific WIFI Connection is Available

I need to detect when I have network connectivity to a SPECIFIC WIFI network.
For example: As soon as you walk into your house, and your phone picks up your home WiFi network, I would like a notification that says "You are not at your home network, would you like to connect to you Home?" But I would like that to only happen when I am at my specific house.
What should I listen for and what tests should I do to make sure it is my specific home network, and not another network?
You can use BroadcastReceiver to find out that wifi network has changed:
BroadcastReceiver broadcastReceiver = new WifiBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
context.registerReceiver(broadcastReceiver, intentFilter);
The BroadcastReceiver may look like this.
And to check for specific MAC address see the checkConnectedToDesiredWifi() method bellow.
public class WifiBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION .equals(action)) {
SupplicantState state = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
if (SupplicantState.isValidState(state)
&& state == SupplicantState.COMPLETED) {
boolean connected = checkConnectedToDesiredWifi();
}
}
}
/** Detect you are connected to a specific network. */
private boolean checkConnectedToDesiredWifi() {
boolean connected = false;
String desiredMacAddress = "router mac address";
WifiManager wifiManager =
(WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifi = wifiManager.getConnectionInfo();
if (wifi != null) {
// get current router Mac address
String bssid = wifi.getBSSID();
connected = desiredMacAddress.equals(bssid);
}
return connected;
}
}
As long, as we are nothing like code as you need, for free service, I can only recommend you, to read everything possible about Android and its Network/Wifi possibilities, when creating such app.
Sources you should read up and study
http://developer.android.com/reference/android/net/wifi/package-summary.html
how to see if wifi is connected in android
How to get my wifi hotspot ssid in my current android system
How to get name of wifi-network out of android using android API?
Get Wifi Interface name on Android
Permissions you should ask for when creating application manifest
AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
(the last one, only if you want it to detect your location, to prevent unnecessary calls)
You should also declare, that your application needs wifi to be available in device, to work properly:
AndroidManifest.xml
<uses-feature android:name="android.hardware.wifi" />
Use the standard code to list all available networks:
start the scan
String connectivity_context = Context.WIFI_SERVICE;
final WifiManager wifi = (WifiManager) getSystemService(connectivity_context);
if (wifi.isWifiEnabled()) {
wifi.startScan();
}
register a receiver for the data
IntentFilter i = new IntentFilter();
i.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent i) {
// TODO Auto-generated method stub
ScanWiFiActivity a = ScanWiFiActivity.instance();
WifiManager w = (WifiManager) context
.getSystemService(Context.WIFI_SERVICE);
List<ScanResult> l = w.getScanResults();
a.Clear();
for (ScanResult r : l) {
//use r.SSID or r.BSSID to identify your home network and take action
a.setText(r.SSID + "" + r.level + "\r\n");
}
}
};
registerReceiver(receiver, i);
In the FOR block work your magic and take action when you identify your network by SSID or BSSID
I had exactly the same problem for a project of mine and it took a while to find a solution.
First of all, "connecting to a WiFi" is something very abstract, and it turns out rightly so. In practice, people usually mean all of the following:
authenticated with a WiFi access point
associated with the access point
got an ip address from the network
All these stages (and several more) are associated with different Andoid events. So, without further ado, here is my (slightly modified) code:
public class MyService extends Activity { // or Service
//... Other stuff
BroadcastReceiver awaitIPAddress = null;
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
if (intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE) == SupplicantState.COMPLETED) {
//WiFi is associated
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wi = wifiManager.getConnectionInfo();
if (wi != null) {
// Wifi info available (should be, we are associated)
if (wi.getIpAddress() != 0) {
// Lucky us, we already have an ip address.
// This happens when a connection is complete, e.g. after rekeying
if (wi.getBSSID().equals("c0:ff:ee:c0:ff:ee")) {
// ... Do your stuff here
// ...
// ...
}
} else {
// No ip address yet, we need to wait...
// Battery friendly method, using events
if (awaitIPAddress == null) {
awaitIPAddress = new BroadcastReceiver() {
#Override
public void onReceive(Context ctx, Intent in) {
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wi = wifiManager.getConnectionInfo();
if (wi != null) {
if (wi.getIpAddress() != 0) {
if (wi.getBSSID().equals("c0:ff:ee:c0:ff:ee")) {
// ... Do your stuff here
// ...
// ...
}
}
} else {
ctx.unregisterReceiver(this);
awaitIPAddress = null;
}
}
};
// We register a new receiver for connectivity events
// (getting a new IP address for example)
context.registerReceiver(awaitIPAddress, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
}
}
} else {
// wifi connection not complete, release ip address receiver if registered
if (awaitIPAddress != null) {
context.unregisterReceiver(awaitIPAddress);
awaitIPAddress = null;
}
}
}
}
};
//... Other stuff
#Override
public void onCreate() {
super.onCreate();
//... Other stuff
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
registerReceiver(receiver, filter);
//... Other stuff
}
//... Other stuff
}
Also, don't neglect the appropriate permissions to the manifest:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
And I strongly suspect you will also need:
<uses-permission android:name="android.permission.INTERNET"/>

How can I programmatically tell if a Bluetooth device is connected?

I understand how to get a list of paired devices, but how can I tell if they are connected?
It must be possible since I see them listed in my phone's Bluetooth device list and it states their connection status.
Add the Bluetooth permission to your AndroidManifest,
<uses-permission android:name="android.permission.BLUETOOTH" />
Then use intent filters to listen to the ACTION_ACL_CONNECTED, ACTION_ACL_DISCONNECT_REQUESTED, and ACTION_ACL_DISCONNECTED broadcasts:
public void onCreate() {
...
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
this.registerReceiver(mReceiver, filter);
}
//The BroadcastReceiver that listens for bluetooth broadcasts
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
... //Device found
}
else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
... //Device is now connected
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
... //Done searching
}
else if (BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) {
... //Device is about to disconnect
}
else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
... //Device has disconnected
}
}
};
A few notes:
There is no way to retrieve a list of connected devices at application startup. The Bluetooth API does not allow you to query, instead it allows you to listen to changes.
A hoaky workaround to the above problem would be to retrieve the list of all known/paired devices... then trying to connect to each one (to determine if you're connected).
Alternatively, you could have a background service watch the Bluetooth API and write the device states to disk for your application to use at a later date.
In my use case I only wanted to see if a Bluetooth headset is connected for a VoIP app. The following solution worked for me.
Kotlin:
fun isBluetoothHeadsetConnected(): Boolean {
val mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
return (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled
&& mBluetoothAdapter.getProfileConnectionState(BluetoothHeadset.HEADSET) == BluetoothHeadset.STATE_CONNECTED)
}
Java:
public static boolean isBluetoothHeadsetConnected() {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()
&& mBluetoothAdapter.getProfileConnectionState(BluetoothHeadset.HEADSET) == BluetoothHeadset.STATE_CONNECTED;
}
Of course you'll need the Bluetooth permission:
<uses-permission android:name="android.permission.BLUETOOTH" />
There is an isConnected function in the BluetoothDevice system API in https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth/BluetoothDevice.java.
If you want to know if a bounded (paired) device is currently connected or not, the following function works fine for me:
public static boolean isConnected(BluetoothDevice device) {
try {
Method m = device.getClass().getMethod("isConnected", (Class[]) null);
boolean connected = (boolean) m.invoke(device, (Object[]) null);
return connected;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
For some reason, BluetoothAdapter.ACTION_ACL_CONNECTED could not be resolved by Android Studio. Perhaps it was deprecated in Android 4.2.2?
Here is a modification of Skylarsutton's code (Big thanks to Skylarsutton for his answer.) . The registration code is the same; the receiver code differs slightly. I use this in a service which updates a Bluetooth-connected flag that other parts of the app reference.
public void onCreate() {
//...
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
this.registerReceiver(BTReceiver, filter);
}
//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
Toast.makeText(getApplicationContext(), "BT Connected", Toast.LENGTH_SHORT).show();
}
else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
//Do something if disconnected
Toast.makeText(getApplicationContext(), "BT Disconnected", Toast.LENGTH_SHORT).show();
}
//else if...
}
};
This code is for the headset profiles, and probably it will work for other profiles too.
First you need to provide a profile listener (Kotlin code):
private val mProfileListener = object : BluetoothProfile.ServiceListener {
override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
if (profile == BluetoothProfile.HEADSET)
mBluetoothHeadset = proxy as BluetoothHeadset
}
override fun onServiceDisconnected(profile: Int) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = null
}
}
}
Then while checking Bluetooth:
mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET)
if (!mBluetoothAdapter.isEnabled) {
return Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
}
It takes a bit of time until onSeviceConnected is called. After that you may get the list of the connected headset devices from:
mBluetoothHeadset!!.connectedDevices
BluetoothAdapter.getDefaultAdapter().isEnabled ->
returns true when Bluetooth is open.
val audioManager = this.getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.isBluetoothScoOn ->
returns true when a device connected
I was really looking for a way to fetch the connection status of a device, not listen to connection events. Here's what worked for me:
BluetoothManager bm = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
List<BluetoothDevice> devices = bm.getConnectedDevices(BluetoothProfile.GATT);
int status = -1;
for (BluetoothDevice device : devices) {
status = bm.getConnectionState(device, BLuetoothGatt.GATT);
// compare status to:
// BluetoothProfile.STATE_CONNECTED
// BluetoothProfile.STATE_CONNECTING
// BluetoothProfile.STATE_DISCONNECTED
// BluetoothProfile.STATE_DISCONNECTING
}

Categories

Resources