Can automatically connect to paired bluetooth device when in range? - android

I have two Android phones. I want to make an auto connection between them via Bluetooth. For example,
I have my android phone which paired to another Bluetooth. When I put these phone near together, they need to detect Bluetooth device, and automatically connect to a selected android phone (known Adress/MAC/Paired before). I don't need to connect it again. I want this kind of connectivity in my Android application.
I google and found some related reference, but they are did not solve the issue yet. I think that I need to create a thread/service to automatically connect Bluetooth when they are in range. However, I can not implement it. If you have a good solution, please let me know. Thank you
Automatically connect to paired bluetooth device when in range
Find already paired bluetooth devices automatically, when they are in range
/**
* 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();
// 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);
// If it's already paired, skip it, because it's been listed already
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
// When discovery is finished, change the Activity title
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
setProgressBarIndeterminateVisibility(false);
setTitle(R.string.select_device);
if (mNewDevicesArrayAdapter.getCount() == 0) {
String noDevices = getResources().getText(R.string.none_found).toString();
mNewDevicesArrayAdapter.add(noDevices);
}
}
}
};

These broadcast receivers will fire only after the discovery process runs.
Discovery can be started in two ways: either manually in Bluetooth settings, or programatically by calling BluetoothAdapter#startDiscovery(). However, the documentation states that:
Device discovery is a heavyweight procedure. New connections to remote Bluetooth devices should not be attempted while discovery is in progress, and existing connections will experience limited bandwidth and high latency. Use cancelDiscovery() to cancel an ongoing discovery. Discovery is not managed by the Activity, but is run as a system service, so an application should always call cancelDiscovery() even if it did not directly request a discovery, just to be sure.
This implies that discovery should be done as a one-off procedure, not continuously running in the background—apart from slowing down other Bluetooth connections, it will drain the battery quickly.

Related

Bluetooth scan results increase with manual scan in Android

I have implemented a broadcast receiver in Android to listen to all available Bluetooth signals. The receiver works, but only shows four devices. When I manually scan for devices in the android menu, I suddenly see eight different devices in my app.
How can I see all available devices without using manual scan?
code:
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
int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
Log.d("bluetoothSignal", "name: "+ device.getName() + " adress: "+ device.getAddress() + "strength: "+ rssi + " Data: " + intent.getData());
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
Be aware that in the 'android menu' scanning results can show the paired devices, as well as scanned devices. So this could account for the duplicates. This case however is not very likely because any good Bluetooth scanning results should prevent duplicate results but there may be special cases where duplicates could be allowed.
What I suspect is actually occurring is that the system settings is returning tradition Bluetooth Devices (using rfcomm) and Bluetooth LE devices. The problem is, most Bluetooth device menus don't show a identifier that indicates whether a device is tradition or Bluetooth LE device, just the device name. Furthermore, when using BluetoothAdapter.startDiscovery() it tends to prefer traditional Bluetooth Devices and only occasionally returns Bluetooth LE devices. For example in my experience, 85 percent of the time it does not discover Bluetooth LE devices in the time it takes to to complete a discovery process, 13 seconds. I recommend using a use both the traditional scanning mechanism and the Bluetooth LE scanning mechanism. To perform a Bluetooth LE scan get a reference to the BluetoothLeScanner get calling BluetoothAdapter.getBluetoothLeScanner(). Once you have a reference, call BluetoothLeScanner.startScan(ScanCallback callback). The ScanCallback will get fired with discovered Bluetooth LE devices that you can add to your ListView's adapter. Try this and see if you get similar results with the 'android menu'.

Pairing to a Bluetooth Low Energy device in Android

Is it possible to automatically connect to Bluetooth Low Energy (BLE) devices?
The Android documentation indicates that the [BluetoothDevice.connectGatt()](https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback)) has a autoConnect parameter:
boolean indicating whether to automatically connect to the BLE device
as soon as it becomes available
However, to call this, you need a BluetoothDevice first. AFAIK the only way to get this is by scanning available devices. Setting up a scan every time to connect to a device doesn't seem like a desirable way. Also, I tried using nRF Control Master Panel to connect to my peripheral using the autoConnect = true, but this does not connect to the device. Connecting without the autoConnect however does make it connect, and I've managed to read and write data from and to my peripheral this way with success.
The general way in Bluetooth to have two devices paired. However, searching for my BLE device and using BluetoothDevice.createBond() does not seem to work. In my ACTION_BOND_STATE_CHANGED-callback, the EXTRA_BOND_STATE and EXTRA_PREVIOUS_BOND_STATE just go from BOND_BONDING to BOND_NONE and back. I don't read out an error or anything - so maybe I'm missing something here. Here's the callback:
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
final int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
final int prevState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.ERROR);
Log.e(TAG, "prevState " + prevState + ", state " + state);
}
}
};
So this type of bonding does not seem to work.
My question is: am I doing something wrong for pairing or the autoConnect? Or is how I currently have it working the only correct way? It seems like a real pain (and battery-drain) to have to scan for devices every time, see if the device is there, if so read data and check back tomorrow, otherwise check back in an hour or so. The point of Bluetooth is that it should pair directly whenever it is near, isn't it?
It does work without rescan. You do not need pairing at all. Just call BluetoothGatt.connect() again for gatt object you aquired from first connection.
You will receive onConnectionStateChange event in your BluetoothGattCallback as soon as ble device will be available again. If you use autoconnect option, you don't even need to call BluetoothGatt.connect() method. Just monitor your cllback, and don't forget to close BluetoothGatt with close() if you don't see any connection for too long.
And yes, to obtain first connection you should scan for ble devices with BluetoothAdapter.startLeScan, not the common bluetooth devices scan.

Android Bluetooth rescanning cause Bluetooth lost

I am working on Bluetooth related application where I provide user a list of nearby Bluetooth devices and also I provide a rescan button to restart scanning process. When user comes to this view application start discovery process and if application founds device it get display in a list. But if the user presses rescan button, first application clear list and then restart scanning process then application fails to list same device again.
I don't know why application fails to rescan same device again.
Check out code below :
Starting search
mBluetoothAdapter.startDiscovery();
mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Finding devices
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());
}
}
};
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
The Discovery procedure is in some sense a probabilistic, so if you can't get identical lists in two sequential calls it is ok. I'd rather wonder are you able to enumerate any other BT-devices during subsequent calls. And if answer is always 'yes', and you experience problems with that only device, check if it is operating correctly. If after first successful call you can't enumerate the devices - either your code is incorrect or your device you're using for debugging works not very well (that's happens quite often in the Android World).

How do I actually BOND a device?

Everywhere I look I find this method "getBondedDevices()" for my bluetooth adapter. However, I have my tablet and another bluetooth device sitting next to me, and I can't figure out how to actually get the device to show up on the list of bonded devices.
In Bluetooth terms, "bonded" and "paired" are basically synonyms (officially, the process of pairing leads to a bond, but most people use them interchangeable). In order for your device to be added to that list, you must go through the process of Discovery, which is how one device searches and finds another, and then Pair the two together.
You can actually do this from the device settings as a user, but if you are looking to so so within the context of an app, your process will likely look something like this:
Register a BroadcastReceiver for BluetoothDevice.ACTION_FOUND and BluetoothAdapter. ACTION_DISCOVERY_FINISHED
Start discovery by calling BluetoothAdapter.startDiscovery()
Your receiver will get called with the first action every time a new device is found in range, and you can inspect it to see if it's the one you want to connect with. You can call BluetoothAdapter.cancelDiscovery() once you've found it to not waste the battery any more than necessary.
When discovery is complete, if you haven't canceled it, your receiver will get called with the second action; so you know not to expect any more devices.
With a device instance in hand, open a BluetoothSocket and connect(). If the devices are not already bonded, this will initiate pairing and may show some system UI for a PIN code.
Once paired, your device will show up in the bonded devices list until the user goes into settings and removes it.
The connect() method also actually opens the socket link, and when it returns without throwing an exception the two devices are connected.
Now connected, you can call getInputStream() and getOutputStream() from the socket to read and write data.
Basically, you can inspect the list of bonded devices to quickly get access to an external device, but in most applications you will be doing a combination of this and true discovery to make sure you can always connect to the remote device regardless of what the user does. If a device is already bonded, you'd just be doing steps 5-7 to connect and communicate.
For more information and sample code, check out the "Discovering Devices" and "Connecting Devices" sections of the Android SDK Bluetooth Guide.
HTH
API level 19 and above you can call createBond() on BluetoothDevice instace to which you want to connect.
You will require some permissions to discover and list the visible devices
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Code to discover and list the devices:
bluetoothFilter.addAction(BluetoothDevice.ACTION_FOUND);
bluetoothFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
bluetoothFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(bluetoothReceiver, bluetoothFilter);
private BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
Log.e("bluetoothReceiver", "ACTION_FOUND");
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
devicesList.add((device.getName() != null ? device.getName() : device.getAddress()));
bluetoothDevicesAdapter.notifyDataSetChanged();
} else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Log.e("bluetoothReceiver", "ACTION_DISCOVERY_STARTED");
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.e("bluetoothReceiver", "ACTION_DISCOVERY_FINISHED");
getActivity().unregisterReceiver(bluetoothReceiver);
}
}
};
Just call createBond() on selected device.

Android Bluetooth - service to log nearby bluetooth devices

Is it possible to create a service that can listen for devices nearby and log device info to a file?
Yes, your service can listen for new Bluetooth devices, as described by Vipul Shah, but the real issue is how do you cause your device to find other Bluetooth devices in the first place.
ACTION_FOUND is sent when a remote device is found during discovery. You can call BluetoothAdapter.startDiscovery() to start the discovery process, but the problem is that very few devices are normally discoverable. A couple of years ago it was common for devices to remain discoverable all the time, but now the user is expected to make a device temporarily discoverable as needed to pair it.
So, it doesn't make sense to have a service that periodically does discovery (and listen for ACTION_FOUND) both because it consumes a lot of battery and because you won't find anything.
If you know the Bluetooth address of the devices that you are looking for then you could try to connect to them, but I assume that is not the case.
Yes it is very much possible
Step 1 You will need to create one service
Step 2 You will need BluetoothDevice.ACTION_FOUND Broadcast Receiver to look for nearby devices.
Step 3 Then you can query all found devices one by one.
Step 4 As you will fast enumerate over found devices dump their information inside file.
Below is broadcast Receiver
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
// You will log this information into file.
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
Register the broadcast receiver for intent action as follows
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
Hope this helps.

Categories

Resources