Detecting another nearby android device via Bluetooth - android

Alright, I've got a bit of a weird question here. I'm working on an Android game where I'd like to be able to have Android phones detect the presence of each other.
The device searching for other players will know the bluetooth mac addresses of the other players' devices (from a game DB), however the devices will not be paired and the devices will not be in discoverable mode. Also, there will only be a handful of devices that could possibly be found - so it's not a big deal to scan through mac addresses.
I don't need to connect to the devices, I just need to be able to answer one simple question: is this device with this mac address nearby?
It is permissible to have a pairing dialog appear on the other user's screen...I don't care what the outcome of their choice is...I just need to know if their device is there.
Any help would be greatly appreciated!

This use-case may be a good fit for the recently released Nearby API. See the Nearby Messages developer overview
Nearby has its own runtime permission saving you from adding BLUETOOTH_ADMIN or similar to your manifest. It works across iOS and Android by utilizing multiple technologies (Classic Bluetooth, BLE, ultrasound). There's an option to use only the ultrasonic modem which reduces the range to about 5 feet.
I've included a partial example below, you can find a more complete sample on github
// Call this when the user clicks "find players" or similar
// In the ResultCallback you'll want to trigger the permission
// dialog
Nearby.Messages.getPermissionStatus(client)
.setResultCallback(new ResultCallback<Status>() {
public void onResult(Status status) {
// Request Nearby runtime permission if missing
// ... see github sample for details
// If you already have the Nearby permission,
// call publishAndSubscribe()
}
});
void publishAndSubscribe() {
// You can put whatever you want in the message up to a modest
// size limit (currently 100KB). Smaller will be faster, though.
Message msg = "your device identifier/MAC/etc.".getBytes();
Nearby.Messages.publish(googleApiClient, msg)
.setResultCallback(...);
MessageListener listener = new MessageListener() {
public void onFound(Message msg) {
Log.i(TAG, "You found another device " + new String(msg));
}
});
Nearby.Messages.subscribe(googleApiClient, listener)
.setResultCallback(...);
}
Disclaimer I work on the Nearby API

Related

How to "connect" the android watch programmatically if disconnected in the Android Wear app?

On the top of the action bar menu, top right, in Android Wear app, I see the following item: "Disconnect HUAWEI WATCH" (this is the watch I use for testing).
If I select this item, indeed, the watch is kind of "disconnected" - there is no Bluetooth communication with it, even if the Bluetooth is in general on on and the device is still seen as paired in general Bluetooth settings. Worst, sometimes the watch gets disconnected without the user input, if it has been physically far away form the phone for longer time.
My app heavily relies on Bluetooth connectivity, and the end user most likely will not notice the fact of watch being "disconnected". They will just assume the app is buggy.
Hence it is vital for my app to detect the "disconnected watch" state. Best would be to connect the watch again, automatically or after the user confirmation. In the worse case, may be ok to detect the case and ask the user to go and fix the problem in Android Wear.
How to detect programmatically that the watch has been disconnected via Android Wear menu.
How to connect it back.
This is not about how to detect if Bluetooth in general is enabled or disabled, also now about how to pair the Bluetooth device.
I am using the Data API with setUrgent().
I would suggest to use
#Override
public void onConnectionSuspended(int cause) {
}
to detect whether your nodes were disconnected.
there were
#Override
public void onPeerConnected(Node node) {
Log.d(TAG, "CONNECTED");
}
#Override
public void onPeerDisconnected(Node node) {
Log.d(TAG, "PEER DISCONNECTED");
}
but now they are deprecated.
Use CapabilityApi instead
Do not forget that you can use
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).setResultCallback(
new ResultCallback<NodeApi.GetConnectedNodesResult>() {
#Override
public void onResult(NodeApi.GetConnectedNodesResult nodes) {
for (Node node : nodes.getNodes()) {
mNode = node;
}
}
}
);
to retrieve nearby nodes
I do not know your code. That is why I just can say such broad advice.

Bond a BLE device without createBond()

I am creating an Android app - one feature of this app is that if the user connects to a BLE device and clicks a button, the app will remember the device and automatically connect in future. From what I understand, this means I need bonding.
I came across the createBond() method, but realised that it is only usable in API 19 (Android 4.4) and onwards. The person I am making this for would much prefer it be available in API 18 (Android 4.3) as the product has already been advertised as such.
Assuming that I am correct in my approach (meaning, through active use of Bonding - I'm self-teaching Bluetooth, so please correct me if this isn't the way to go or if I am misunderstanding), is there any way that I can achieve what I want to without createBond()? If so, how? Or is API19 something we will have to live with?
One option is to use a preference in conjunction with your callback for device scanning.
Assuming you're using an LeScanCallback somewhere in your app:
BluetoothAdapter.LeScanCallback mCallBack =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
// You can place this elsewhere so this isn't called for every device
String storedAddr = myContext.getSharedPreferences("global", Context.MODE_PRIVATE).getString("storedAddr","");
if(storedAddr.equals("")) {
// Do your normal process to list / connect to devices.
// Store device.getAddress() in preferences once connected.
} else if(device.getAddress().equals(storedAddr) {
// Do whatever you want with the matching device
}
}
}
Of course, you'll have to deal with an option to remove that stored address so that they can choose a new device to save, if needed.

How to get changing RSSI of BLE in Android

I am using Kontakt beacon device & testing ble on nexus 5. When I tested iPad as a beacon device I am able to find out the services & characteristics with the help of the code given on android developer site. But now I want to do some actions depending on the distance of the mobile from the beacon device. So I tried to detect how far is the mobile from the beacon device like iOS CLBeacon.Proximity (CLProximityFar, CLProximityNear, CLProximityImmideate & CLProximityUnknown). I searched but not able to find out like this in android. So decided to do some actions depending on the rssi. But problem is whatever rssi I am getting first time i.e at the time of mobile detect beacon device is not changing even if I move near to beacon device or went far away from it.
If any one had idea how to get the changing rssi in the android then please share.
Thanks.
I'm not sure how you checked the never changed rssi as you described, via a existed APP or writing codes by yourself?
but from the code, it's quite straight forward, I put a core code in Android 5.0,
//get your device's BT adapter
mBluetoothAdapter = ((BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
mLescanner = mBluetoothAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder().setScanMode(scanSettings.SCAN_MODE_LOW_LATENCY).build();
mLescanner.startScan(this.mLeScanCallback);
And the callback is like this, and you can get the real time rssi in the function:
this.mLeScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
int realTimeRssiYouWant = result.getRssi();
}
}

Discovering vendor-specific bluetooth devices only

Need to discover or search for Bluetooth devices of certain "vendor-specific" devices.
"vendor-specific" means all devices will have similar starting bits in their "MAC" address
For example, I want to search only for devices whose MAC address starts with 12:34:56:
It should search only for specific series of MAC addresses and list them.
Perform a full discovery, then filter using BluetoothDevice.getAddress()
// Define Vendor ID Prefix
public static final String VENDOR_ID = "12:34:56:"
// First, do a full discovery...
BluetoothAdapter.getDefaultAdapter().startDiscovery()
//...
// Then, for each device returned from discovery...
if ( device.getAddress().startsWith(VENDOR_ID) ) {
// Do Something
}
My Explanation will be based on the BluetoothChat example from the Android SDK, hopefully this is ok, otherwise I would need to write a lot more. If you haven't seen the BluetoothChat example, go take a look, it's really nice!
If you want to use a device where you don't know the complete adress, you'll have to do a complete discovery with BluetoothAdapter.startDiscovery() and search the received addresses for the ones you want to.
If you know the complete address of the device you want to connect to you can directly connect to this device with BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address)

Android Bluetooth Low Energy Motorola API pairing

I am working on using the BT 4.0 API that Motorola has provided with the RAZR. In one of their documents it states to use the Android API to pair before connecting and using their framework. Per their instructions I have been pairing with OS Bluetooth settings application, but it never prompts me for a key. It will pair but doesn't appear to bond, and this is critical for me.
My question is, when they say "using the Android API" is this referring to simply using the OS Bluetooth utility to pair before hand (like I have been doing), or is there some way to do it with code in my application. They reference the "createBond()" function which, to my knowledge, is not an accessible function (at least not without some squirrely libraries or reflection).
Any advice is greatly appreciated, especially anyone who has used the API successfully, if they could give an account of their process. I'm just looking for some clarity at this point :)
Lloyd,
You are correct, follow the instructions in the link you posted.
Outside of coding, when they say use the standard android api for "non-le" operations, they mean go ahead and pair the ble device the same way you would any bluetooth classic devices inside android settings -> wireless & network -> bluetooth -> scan for devices.
If the device you are using is a motorola le compatible device the ble device will be paired but not connected.
Now, in the code, you can detect this paired device through the same method of
BluetoothAdapter.getDefaultAdapter().getBondedDevices()
To double check if your Android Phone is LE compatible, run this code:
public static boolean checkBLESupport() {
boolean deviceSupportsLE;
try {
#SuppressWarnings({ "unused", "rawtypes" })
Class object = Class.forName("android.server.BluetoothGattService");
deviceSupportsLE = true;
} catch (Exception e) {
deviceSupportsLE = false;
}
return deviceSupportsLE;
}
And to double check if the bluetooth device you paired is LE, when you are looping through the bonded devices.
Check the device with this code.
if (device.getBluetoothClass() == null) {
Log.i(TAG, "This device is BLE compatible");
b = true;
} else {
Log.i(TAG, "This device is not BLE");
b = false;
}
Now for establishing connection from your LE compatible phone to your LE compatible bluetooth device, follow the Gatt service instructions under the link you posted. http://developer.motorola.com/docs/bluetooth-low-energy-api/
Take note that under this example it is connecting to a bluetooth low energy heart rate monitor.
If you are not trying to connect to the heart rate monitor with LE heart rate profile, here is a link to another Motorola document that details creating your own LE Profile to use with the GATT framework. http://developer.motorola.com/docs/bluetooth-low-energy-gatt-framework-api/
If the instructions are not clear enough at any point in either of these documents, motorola offers sample android applications using the frameworks in those documents.
I guess motorola stack has BLE support. But what i feel is that it does not pair with the devices that require bonding though It does work some sensors. I have tried with a proximity sensor that require bonding. It never gets paired though the devices is discovered with Razr which even does not with S3.
There's a helpful video here.
Late to the game, but can confirm -
If your BLE Peripheral requires bonding, Moto X - and some other older Motorola devices - MUST be paired via Bluetooth Settings prior to programmatic connection via the Android GATT interface.
If you bond via the createBond method, or reading of an encrypted characteristic, your connection will be dropped typically in under 60 seconds, despite DDMS logs that show a good bond may be established.

Categories

Resources