Currently I am trying to deal with a strange Exception when opening a BluetoothSocket on my Nexus 7 (2012), with Android 4.3 (Build JWR66Y, I guess the second 4.3 update). I
Bluetooth devices can operate in both classic and LE mode at the same time. Sometimes they use a different MAC address depending on which way you are connecting. Calling socket.connect()
is using Bluetooth Classic, so you have to make sure the device you got when you scanned was really a classic device.
It's easy to filter for only Classic devices, however:
if(BluetoothDevice.DEVICE_TYPE_LE == device.getType()){
//socket.connect()
}
Without this check, it's a race condition as to whether a hybrid scan will give you the Classic device or the BLE device first. It may appear as intermittent inability to connect, or as certain devices being able to connect reliably while others seemingly never can.
Even i had the same problem ,finally understand my issue , i was trying to connect from (out of range) Bluetooth coverage range.
You put
registerReceiver(receiver, new IntentFilter("android.bleutooth.device.action.UUID"));
with "bluetooth" spelled "bleutooth".
Well, I have actually found the problem.
The most people who try to make a connection using socket.Connect();
get an exception called Java.IO.IOException: read failed, socket might closed, read ret: -1
.
In some cases it also depends on your Bluetooth device, because there are two different types of Bluetooth, namely BLE (low energy) and Classic.
If you want to check the type of your Bluetooth device is, here's the code:
String checkType;
var listDevices = BluetoothAdapter.BondedDevices;
if (listDevices.Count > 0)
{
foreach (var btDevice in listDevices)
{
if(btDevice.Name == "MOCUTE-032_B52-CA7E")
{
checkType = btDevice.Type.ToString();
Console.WriteLine(checkType);
}
}
}
I've been trying for days to solve the problem, but since today I have found the problem. The solution from @matthes has unfortunately still a few issues as he said already, but here's my solution.
At the moment I work in Xamarin Android, but this should also work for other platforms.
SOLUTION
If there is more than one paired device, then you should remove the other paired devices. So keep only the one that you want to connect (see the right image).
In the left image you see that I have two paired devices, namely "MOCUTE-032_B52-CA7E" and "Blue Easy". That's the issue, but I have no idea why that problem occurs. Maybe the Bluetooth protocol is trying to get some information from another Bluetooth device.
However, the socket.Connect();
works great right now, without any problems. So I just wanted to share this, because that error is really annoying.
Good luck!
I ran into this problem and fixed it by closing the input and output streams before closing the socket. Now I can disconnect and connect again with no issues.
https://stackoverflow.com/a/3039807/5688612
In Kotlin:
fun disconnect() {
bluetoothSocket.inputStream.close()
bluetoothSocket.outputStream.close()
bluetoothSocket.close()
}
In case somebody is having issues with Kotlin, I had to follow the accepted answer with some variations:
fun print(view: View, text: String) {
var adapter = BluetoothAdapter.getDefaultAdapter();
var pairedDevices = adapter.getBondedDevices()
var uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
if (pairedDevices.size > 0) {
for (device in pairedDevices) {
var s = device.name
if (device.getName().equals(printerName, ignoreCase = true)) {
Thread {
var socket = device.createInsecureRfcommSocketToServiceRecord(uuid)
var clazz = socket.remoteDevice.javaClass
var paramTypes = arrayOf<Class<*>>(Integer.TYPE)
var m = clazz.getMethod("createRfcommSocket", *paramTypes)
var fallbackSocket = m.invoke(socket.remoteDevice, Integer.valueOf(1)) as BluetoothSocket
try {
fallbackSocket.connect()
var stream = fallbackSocket.outputStream
stream.write(text.toByteArray(Charset.forName("UTF-8")))
} catch (e: Exception) {
e.printStackTrace()
Snackbar.make(view, "An error occurred", Snackbar.LENGTH_SHORT).show()
}
}.start()
}
}
}
}
Hope it helps