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.
Related
For weeks I was struggling to create an app that connected to an arduino device over Bluetooth Low Energy (Bluetooth LE) and I finally got it working today. I am sharing the resources I found so that if someone else is struggling they can learn from my experience. The information I am sharing is for bluetooth LE only. If your device is using bluetooth classic this will not work as they are not compatible.
For anyone who is new to this here is some terms you will need to know. You need to use them in your program to communicate with bluetooth LE.
UART: universal asynchronous receiver-transmitter. This is the protocol that is used to send data to a device via bluetooth LE and to receive data.
GATT: Generic Attribute Profile. This defines how data will be transferred back and forth using Services and Characteristics.
This was an excellent tutorial on how to create the app:
https://www.jenx.si/2020/08/13/bluetooth-low-energy-uart-service-with-xamarin-forms/
This app will scan for BLE devices, connect to them, send data to the device, and receive data from the device. My app is for android, but it looks like the app from this tutorial will work for IOS as well.
Once I created the app I searched for the UART UUID's of my device (an Adafruit Feather Bluefruit LE). Here is the page where I found the codes for my device:
https://learn.adafruit.com/adafruit-feather-m0-bluefruit-le/uart-service
I found the Send and Receive UUID's from the Nordic Semiconductor website:
https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v14.0.0%2Fble_sdk_app_nus_eval.html
Then in the GattIdentifiers page I replaced the generic UUID's that were entered with the UUID's for my device. Here is what my GattIdentifiers page looks like with my UUID's.
public class GattIdentifiers
{
public static Guid UartGattServiceId = Guid.Parse("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
public static Guid UartGattCharacteristicReceiveId = Guid.Parse("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
public static Guid UartGattCharacteristicSendId = Guid.Parse("6E400002-B5A3-F393-E0A9-E50E24DCCA9E");
public static Guid SpecialNotificationDescriptorId = Guid.Parse("00002902-0000-1000-8000-00805f9b34fb");
}
A note on this is to make sure you put the right UUID's with the send and receive characteristics defined in the file. I had them reversed at first which was giving me "null" results. So if they are not working try reversing them.
I hope this helps!
I am having a Arduino with BLE which has to send some data to any/all android phones over Bluetooth in it's range. My android phone should have a app which i intend to make will notify about data received.
How can i make such android app which auto-connects to any nearby BLE , if found without pairing even for first time and exchange data. I mean how in any application i can implement auto-connect without key pairing.I found that setting autoconnect=true will do this task , but i am not sure.
Any help, even some resource i will refer and clear my doubts.
The pre-requisites and steps are (code snippets in Java):
HC-XX module or similar BLE-device on the Arduino-side set to security mode 1 and security level 1 (no security AND no pairing)
Android 4.3 (API level 18) with built-in platform support for Bluetooth Low Energy (BLE)
Check on the device (mobile) that BLE is enabled
// Ensures Bluetooth is available on the device and it is enabled. If not,
// displays a dialog requesting user permission to enable Bluetooth.
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
Find the BLE device(s). You use the startLeScan() method. This method takes a BluetoothAdapter.LeScanCallback as a parameter. You must implement this callback, because that is how scan results are returned. Because scanning is battery-intensive, you should observe the following guidelines:
As soon as you find the desired device, stop scanning.
Never scan on a loop, and set a time limit on your scan. A device that was previously available may have moved out of range, and continuing to scan drains the battery.
If you want to scan for only specific types of peripherals, you can instead call startLeScan(UUID[], BluetoothAdapter.LeScanCallback), providing an array of UUID objects that specify the GATT services your app supports.
The first step in interacting with a BLE device is connecting to it— more specifically, connecting to the GATT server on the device. To connect to a GATT server on a BLE device, you use the connectGatt() method. This method takes three parameters: a Context object, autoConnect (boolean indicating whether to automatically connect to the BLE device as soon as it becomes available), and a reference to a BluetoothGattCallback.
// Here we set autoconnect to true
bluetoothGatt = device.connectGatt(this, true, gattCallback);
To sum up auto connect alone will not do the job as you want no pairing. So security mode 1 and security level 1 (no security at all) has to be set. So make sure by using software sided encryption/auto sign-in that no unauthorized persons use your device
Read more about BLE in Android in detail here
Read more about BLE security in detail here
Have you ever seen the apple watch unlock a Mac? The idea is amazing, but I don't want a smart watch because I already have a phone which has similar capabilities AFAIK.
Also, I moved from OSX to Linux recently :)
I don't know how the Apple watch manages to unlock the Mac. But I know what would be desirable from a user experience point of view:
Needs to unlock quicker than I type my password
Should work in absence of wifi/4G
Should be power efficient
RFID
RFID would be nice, but no laptops that I know embed RFID readers.
Bluetooth based proximity detection
The challenge with classic Bluetooth is the requirement to constantly scan for near devices to measure the signal strenght (RSSI) from which we can infer the proximity.
Unfortunately discovery hops and listens 40 channels. And anyway the phones stop broadcasting when screen is off for a while. This is not good enough. I know because I tried:
import collection.JavaConverters._
import tinyb._
object Listener extends App {
var running = true
val BT_ADDR = sys.env.getOrElse("BT_ADDR", "XX:XX:XX:XX:XX:XX")
val BT_RSSI_DBM_THRESHOLD = Integer.parseInt(sys.env.getOrElse("BT_RSSI_DBM_THRESHOLD", "-65")).toShort
val manager = BluetoothManager.getBluetoothManager
val lock = new Object
while (true) {
manager.getAdapters.forEach(a => {
a.setRssiDiscoveryFilter(BT_RSSI_DBM_THRESHOLD)
a.removeDevices()
})
System.err.println("scanning for " + BT_ADDR + " at minimum " + BT_RSSI_DBM_THRESHOLD + " dBm RSSI...")
manager.startNearbyDiscovery(
(device: BluetoothDevice) => {
if (BT_ADDR.equals(device.getAddress)) {
onProximity(device)
manager.stopNearbyDiscovery()
lock.synchronized(lock.notify())
}
else println(device.getName)
}
, 1000
, false
)
lock.synchronized(lock.wait())
}
}
I was looking at BTLE (Bluetooth Low Energy), and I'm having difficulty to understand the following:
Is there a way to establish from Linux a single low energy bluetooth connection to the Android phone which we can leave dormant all the time, and use it to wake the phone up and make it transmit some packets (so we can measure its RSSI power and infer proximity) on demand, only when strictly needed.
I.e. we'd limit transmissions to only these rare occasions:
Check when the user is away if we detect inactive mouse & keyboard for 1 minute,
Check if the user is near enough when GDM is active
No BT activity whatsoever otherwise
This approach is quick, energy efficient, and does not require network protocol, only some rare BT transmission.
But is this possible with Bluetooth LE? Any pointers to examples?
Yes this should be possible with Bluetooth Low Energy (with some caveats) as follows:-
You need a BlueZ script/C program to constantly scan for your Android device.
You need your phone's Bluetooth to always be turned on.
You will need to pair at least once so that your Linux machine recognizes the changeable Bluetooth address of your Android device (see referenced links).
The BlueZ script program should be written so that as soon as your Linux system goes to standby, the program is launched as a daemon or background process that just starts scanning for Android devices and read their RSSI values. If your device is found and the RSSI value indicates that it is within range, this process will signal the Linux OS to wake up.
The caveats:-
BLE is not ideal for positioning/locationing; you can probably detect
if you're a few metres away but it would be challenging to get an
accuracy of a few centimeters.
Your BlueZ script needs to be
constantly running as a daemon or background process, so if it is
somehow killed or is inactive when the device goes to sleep, this
will not work.
Bluetooth on your phone should be always on, which
shouldn't have a big impact on the battery life but is also not
recommended.
Some resources for you:-
Running Bluetooth applications in the background in Linux
Bluetooth Low Energy: A Primer
Getting Started with Bluetooth Low Energy
Introduction to BLE
Bluetooth LE Signal Strength in Linux
Should One Create a Bond with a Bluetooth LE Device
How to Detect Whether System is Going to Standby in Linux
Android Bluetooth Low Energy Overview
Using Bluetooth Low Energy in Linux Command Line
It will not be a straight forward process and you'll probably have to try and fail along the way, but it will be a learning experience and you should be able to achieve what you want in the end.
I hope this helps.
I'm trying to connect to a specific device using my Android APP, until now what I was able to do is get the paired items doing this :
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Set < BluetoothDevice > pairedDevices = bluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device: pairedDevices) {
mDeviceName.add(device.getName());
mDeviceMAC.add(device.getAddress());
}
}
bluetoothClass.setDeviceName(mDeviceName);
bluetoothClass.setDeviceMac(mDeviceMAC);
Where I get the MAC and the Device name of all of my paired devices. The thing that I would like to do is when I select one it connects to the Bluetooth device.
EXAMPLE
On a Samsung S4 when I turn on the Bluetooth it popups a Dialog whitch contains all of my paired devices and when I click on anyone it connects (I've i'm able to ...) so basically I want to do this, since now I've been getting the paired devices (I don't know if it's the best way to get that but it does) and then when user click on anyone it connects to the device.
It's something like this question but it's unfortunately unanswered.
It's impossible to give you an example within this format, so I have provided you
with a good sample and helpful links to help you understand the sample.
I recommend you follow the steps I have provided and then, when you have
specific problems, you can bring it here, with the code snippet you are having
difficulty with.
I recommend you use download this sample code:
http://developer.android.com/samples/BluetoothChat/index.html
If you haven't already, it's good to study this:
http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html
This is a good tutorial and they have many tutorials:
http://www.tutorialspoint.com/android/android_bluetooth.htm
You will need the following permissions in your manifest:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
This is one intent that is advisable to use, to check to see if BT is enabled:
if (!mBluetoothAdapter.isEnabled()) {
android.content.Intent enableIntent = new android.content.Intent(
android.bluetooth.BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
and to make your device discoverable to other devices:
if (mBluetoothAdapter.getScanMode() !=
android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
android.content.Intent discoverableIntent =
new android.content.Intent(
android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(
android.bluetooth.BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
300); // You are able to set how long it is discoverable.
startActivity(discoverableIntent);
}
As I mentioned in my answer here:
You can avoid using an intent to search for paired devices. When
connecting to a device that is not paired, a notification will pop up
asking to pair the devices. Once paired this message should not show
again for these devices, the connection should be automatic (according
to how you have written your program).
I use an intent to enable bluetooth, and to make my device
discoverable, I then set up my code to connect, and press a button to
connect. In your case, you will need to ensure your accessories are
discoverable also. In my case I use a unique UUID, and both devices
must recognise this to connect. This can only be used if you are
programming both devices, whether both are android or one android and
one other device type.
You will need to understand how to use sockets, this is how the devices communicate.
I recommend studying these two links:
http://developer.android.com/reference/android/bluetooth/BluetoothSocket.html
http://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html
Sockets are used to set up connections between devices. There will be a server socket and device sockets (determined by many factors, the programmer, the actual devices). The server socket listens for incoming connections, when a connection is accepted the devices connect, each with a simple socket.
I am not sure how much you know about threading.
The connection needs to be managed with threads:
http://developer.android.com/guide/components/processes-and-threads.html
http://android-developers.blogspot.com.au/2009/05/painless-threading.html
The connection between the devices is managed on threads separate from the User
Interface thread. This is to prevent the phone from locking up while it is
setting up, seeking and making a BT connection.
For instance:
AcceptThread - the thread that listens for a connection and accepts the connection (via the serversocket). This thread can run for an extended time waiting for a device to connect with.
ConnectThread - the thread that the device connecting to the server uses to connect to the serversocket.
ConnectedThread - this is the thread that manages the connection between both sockets.
Let me know if this helps you.
There are similar questions to this here already, but the answers and suggestions relate to older versions of Android. I understand that the bluetooth stack has been completely revised from 4.2 onwards and older solutions do not work anymore.
I have tried all the older solutions to no avail. the use of the private APIs no longer works because they have changed. I dont mind using private APIs but it must work on the newest versions and later (ie API 17+)
I am trying to do the following:
set up a bluetooth pairing between an Android device and an embedded device using legacy PIN pairing without the embedded device being discoverable nor the user having to manually enter the PIN. In fact I want no PIN entry dialog box at all.
The plan is that the two devices have a predefined shared secret PIN, so that I can perform the pairing programmatically and then open an RFCOMM connection between them. All of this without UI. The hardware address of the embedded device is known to the Android program.
There is no security issue here. the project involves just talking to a nearyby, small embedded device through BT as simple as possible.
Ideas that might work on Android 4.2 (Jelly Bean) most welcome, thanks.
turns out some of the problem was inside the embedded device. on the Android side, the following works:
BluetoothSocket s = null;
try
{
s = device.createInsecureRfcommSocketToServiceRecord(SerialPortServiceClass_UUID);
}
catch (IOException e)
{
Log.e(TAG, "BT connect failed", e);
return false;
}
where
private static final UUID SerialPortServiceClass_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");