I have been strugling with a Bluetooth project on Android for weeks. Does anyone know where I can go to see the actual code that's used by Google to make their Bluetooth pairing and connection logic work?
I have been through all the documentaiton, the BluetoothChat application (which doesn't work as advertised ... tried it on 3 different handsets), as well as a bunch of other sites on the net, but still no luck. I need to get an app up and running on 2.1 or higher.
Any advice or help is greatly appreciated.
Yes the Bluetooth project didn't work for me also because the code for socket connection is not working
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
if (secure) {
tmp = device.createRfcommSocketToServiceRecord(
MY_UUID_SECURE);
} else {
tmp = device.createInsecureRfcommSocketToServiceRecord(
MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
}
this is not working ...
replace this by the following code
BluetoothDevice hxm = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(device.getAddress());
Method m;
m = hxm.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
socket = (BluetoothSocket)m.invoke(hxm, Integer.valueOf(1));
Ah, if you're having issues with application level code I'm not sure staring at the Bluetooth manager source will be much help, but here you go: https://android.googlesource.com/platform/packages/apps/Bluetooth the Bluetooth manager app code.
I'll re-iterate it: this is honestly probably not going to be helpful for what you want. You should be able to get a reasonably working Bluetooth app without having to look at this.
EDIT: if you want the code that implements the Bluetooth packages (android.bluetooth), see https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth for that.
You can browse all the android.bluetooth package around here:
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/bluetooth/BluetoothClass.java#BluetoothClass
Related
I'm trying to establish a bluetoothconnection to another phoner. Later on, it'll be a board with a HC5 module, but for debugging I'm just using a phone.
The problem is, that connect fails and throws an IO Exception:
" read failed, socket might closed or timeout, read ret: -1"
A quick google-search shows a lot having this problem. The only way I can see it solved, is by using a method not public in the API
Method m = mmDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
mmSocket = (BluetoothSocket) m.invoke(mmDevice, 1);
The problem just is, that createRfcommSocket has been removed, and the result from getMethod will be null.
My code is from the example: https://github.com/xamarin/monodroid-samples/tree/master/BluetoothChat which for connecting is:
public ConnectThread(BluetoothDevice device, BluetoothChatService service)
{
UUID MY_UUID = UUID.FromString("00001101-0000-1000-8000-00805f9b34fb");
mmDevice = device;
_service = service;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try
{
if ((int)Android.OS.Build.VERSION.SdkInt >= 10) // Gingerbread 2.3.3 2.3.4
tmp = device.CreateInsecureRfcommSocketToServiceRecord(MY_UUID);
else
tmp = device.CreateRfcommSocketToServiceRecord(MY_UUID);
}
catch (Java.IO.IOException e)
{
Log.Error(TAG, "create() failed", e);
}
mmSocket = tmp;
}
Since the 'original hack' doesn't work, and I haven't found any other solution, I'm hoping somebody here knows how to fix this.
Best regards!
This is the issue I and others in my company have come across when working with Bluetooth devices from Android phones. It is well described on SO here: Service Discovery Failed Exception Using Bluetooth On Android
The method you describe as being removed is, in fact, still operational. And it is the one we have successfully used. We attempt connection using the
tmp = device.CreateRfcommSocketToServiceRecord(MY_UUID);
method you show above.
Use a try...catch block around tmp.Connect() (your code does not show the Connect call)
In the catch block "re-create" the BluetoothSocket using the createRfcommSocket method. I used a small method to do this:
private BluetoothSocket CreateRfcommSocket(BluetoothDevice bTdevice)
{ // This is an "undocumented" call that is needed to (mostly) avoid a Bluetooth Connection error
// introduced in Android v4.2 and higher. It is used as a "fallback" connection.
// Full paths version of code!
//Java.Lang.Reflect.Method mi = device.Class.GetMethod("createRfcommSocket", new Java.Lang.Class[] { Java.Lang.Integer.Type });
//_bluetoothSocket = (BluetoothSocket)mi.Invoke(device, 1);
// Compact version of above
var mi = bTdevice.Class.GetMethod("createRfcommSocket", Integer.Type);
return (BluetoothSocket)mi.Invoke(bTdevice, 1);
}
This is the method indicated here: Xamarin Forum Post
I have tested this on Android 4.4.2 and Android 8.0 and it works on these systems. Another person in the company has tested the Java equivalent code on Android: 4.2.2, 4.4.2, 7.0 and 8.0 and it works in every case.
I am having an Android-App [1] which I partly want to port to google-glass - this app uses bluetooth rfcomm. Now I am facing the following problem: when I use my connection code I see a pairing dialog on glass - showing me a large number and asks for a tap to confirm. But this is strange - as I usually have to enter my 4 digit pin on the phone - also I am getting auth problems ( smells like it is caused by not letting me enter the PIN )
Anyone using bluetooth-rfcomm on google-glass?
[1] https://github.com/ligi/DUBwise
I was having the exact problem like this! In this post I put my complete solution to this problem.
But basically the pairing is done like this:
In the BroadcastReceiver
if(BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)){
BluetoothDevice device = ListDev.get(selectedDevice);
byte[] pinBytes = getStrFromName(device.getName(),7,11).getBytes(); // My devices had their own pin in their name, you can put a constant pin here or ask for one...
try {
Method m = device.getClass().getMethod("setPin", byte[].class);
m.invoke(device, pinBytes);
try {
device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
So the pin is set automatically in this example, but you can always ask for a pin to the user.
Hope it helps!
So im trying to get this little piece of code to run
public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("Server", MY_UUID);
} catch (IOException e) { }
mmServerSocket = tmp;
}
But when i continue from the line where tmp should be assigned it is still null. Bluetooth is activated and everything but it simply wont set tmp to anything when i get to it. Any ideas why not? And btw. does this method not work on a 2.2 android machine since it crashes at that line on my 2.2 machine but not on my 4.1.2 device.
If any more information is needed to be able to answer please just ask for it and ill give it to the best of my ability.
Found out i hadn't given permission to the app to use bluetooth so solved.
I am completely new to Android development and ran into the same problem. Here is more help if other people run into this:
Because this is happening on the server side, be sure discoverability is enabled before starting the accept-connection thread. This can by starting the thread in the onActivityResult() method when the proper resultCode is received.
I'm using the Android development sample project BluetoothChat.
http://developer.android.com/resources/samples/BluetoothChat/index.html
I'm running it on an Archos 43 and trying to communicate with a serial to bluetooth adapter.
To communicate with the adapter I need to use UUID 00001101-0000-1000-8000-00805F9B34FB.
However, when I do that, I get a Null Pointer Exception at this line:
socket = mmServerSocket.accept();
If I use a different UUID I do not have this problem, however I cannot connect to the serial adapter.
If I use a Motorola Droid instead of the Archos 43, I do not have this problem.
From some error messages, I think the Archos is using the bluez stack.
Any ideas why the combination of this UUID and stack would cause an exception when calling the accept() function?
Here's the surrounding code (you can get the whole source from the link above)
public void run() {
if (D) Log.d(TAG, "BEGIN mAcceptThread" + this);
setName("AcceptThread");
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "accept() failed", e);
break;
}
Some error messsages from the log:
04-25 21:05:33.278: ERROR/BluetoothChatService(3321): listen() failed
04-25 21:05:33.278: ERROR/BluetoothChatService(3321): java.io.IOException: Not able to register SDP record for BluetoothChat
04-25 21:05:33.278: ERROR/BluetoothChatService(3321): at android.bluetooth.BluetoothAdapter.listenUsingRfcommWithServiceRecord(BluetoothAdapter.java:778)
Did you change the constructor of "class AcceptThread" , where you use this function "listenUsingRfcommWithServiceRecord()" ?
I'm using the same UUID on archos 70 and i dont get any bluetooth connection errors.( Try restarting the archos if its intermittent.) I wanted to add this as comments for some reasons i dont see a comment !
It ends up the problem was solved with a firmware update from Archos.
Is there a way, using the Android SDK, to programmatically connect to an already-paired Bluetooth device?
In other words: I can go into Settings -> Wireless & networks -> Bluetooth settings, and tap the device (listed as "Paired but not connected"), at which point it will connect. I'd like to be able to do this programmatically, but don't see a way to do this.
I see the options to create an RFCOMM socket, and for a SPP device, I'm assuming that'll do the connection part as well, but for an A2DP device, where the actual data transfer will be handled by the OS rather than by my app, I think that's not applicable?
Okay, since this was driving me crazy, I did some digging into the source code and I've found a 100% reliable (at least on my Nexus 4, Android 4.3) solution to connect to a paired A2DP device (such as a headset or Bluetooth audio device). I've published a fully working sample project (easily built with Android Studio) that you can find here on Github.
Essentially, what you need to do is:
Get an instance of the BluetoothAdapter
Using this instance, get a profile proxy for A2DP:
adapter.getProfileProxy (context, listener, BluetoothProfile.A2DP);
where listener is a ServiceListener that will receive a BluetoothProfile in its onServiceConnected() callback (which can be cast to a BluetoothA2dp instance)
Use reflection to acquire the connect(BluetoothDevice) method on the proxy:
Method connect = BluetoothA2dp.class.getDeclaredMethod("connect", BluetoothDevice.class);
Find your BluetoothDevice:
String deviceName = "My_Device_Name";
BluetoothDevice result = null;
Set<BluetoothDevice> devices = adapter.getBondedDevices();
if (devices != null) {
for (BluetoothDevice device : devices) {
if (deviceName.equals(device.getName())) {
result = device;
break;
}
}
}
And invoke the connect() method:
connect.invoke(proxy, result);
Which, at least for me, caused an immediate connection of the device.
the best way I found to solve my problem was finding out that I can create a button that brings up the Bluetooth Settings screen. I didn't realize you could do this, or I would have from the beginning.
startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
if the device is already paired , then you can use
if(device.getBondState()==device.BOND_BONDED){
Log.d(TAG,device.getName());
//BluetoothSocket mSocket=null;
try {
mSocket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e1) {
// TODO Auto-generated catch block
Log.d(TAG,"socket not created");
e1.printStackTrace();
}
try{
mSocket.connect();
}
catch(IOException e){
try {
mSocket.close();
Log.d(TAG,"Cannot connect");
} catch (IOException e1) {
Log.d(TAG,"Socket not closed");
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
for the MY_UUID use
private static final UUID MY_UUID = UUID.fromString("0000110E-0000-1000-8000-00805F9B34FB");
the above code snippet is just to connect your device to an A2DP supported device.
I hope it will work.
I used the code here as a starting point for this functionality in my app: http://developer.android.com/guide/topics/wireless/bluetooth.html#ConnectingDevices
Once the device is paired, the app has no problem connecting the two devices together programmtically.