When I call BluetoothServerSocket.accept(...) with some timeout value, my Alcatel A30 running Android 7.0 just ignores the timeout and blocks forever. Is this a new bug in Android or some stupidity with this particular phone?
Here's a simple code-section to demonstrate the problem (just paste this into any activity and add <uses-permission android:name="android.permission.BLUETOOTH" /> to your manifest):
Thread test = new Thread() {
@Override
public void run() {
try {
System.out.println("Getting Bluetooth adapter...");
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
System.out.println("Registering service profile...");
BluetoothServerSocket server = bt.listenUsingRfcommWithServiceRecord
("Test", UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
System.out.println("Accepting connection with timeout...");
server.accept(1000); // Android 7.0 gets stuck here rather than timing out
System.out.println("Accepted!");
} catch (Exception e) {
System.err.println("Got an error:");
e.printStackTrace();
}
}
};
test.setDaemon(true);
test.start();
Expected output (from any of my older Android devices; exception shows up after 1s):
Getting Bluetooth adapter...
Registering service profile...
Accepting connection with timeout...
Got an error:
java.io.IOException: Connection timed out
at android.bluetooth.BluetoothSocket.acceptNative(Native Method)
at android.bluetooth.BluetoothSocket.accept(BluetoothSocket.java:364)
at android.bluetooth.BluetoothServerSocket.accept(BluetoothServerSocket.java:113)
at line containing server.accept(1000);
Output from my Android 7.0 Alcatel A30:
Getting Bluetooth adapter...
Registering service profile...
Accepting connection with timeout...
And then it sits there until I kill the app or until I actually connect to the service, in which case I get
`Accepted!`
even after many minutes of waiting before I connect.
Update:
It seems like the code-sample is maybe creating some confusion (Re: deleted answer). Usually when someone posts an exception on SO, they are looking for help how to fix it. This is not what I'm after. By setting the timeout and then not connecting, I am explicitly asking for the exception. The problem is that I am not getting the exception on my Android 7.0 device.
I have the same problem with a device that's running with Android 7.0. Other devices (Android 8 and 9) have the expected behavior : a IOException is raised when the accept did not get an incoming connection within its configured timeout.
What I ended up doing (and it's not very pretty) is using a Timer to close the BluetoothServerSocket from another thread, this caused accept to raise the IOException as though it was a timeout.
BluetoothServerSocket mBssOutCom = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("blabla", uuid);
Timer securityTimer = new Timer();
try {
//! there seems to be a bug in android 7.0
//! that makes the connect timeout never fire. This timer will do the dirty trick
//! Should only have an effect if the bug is active
securityTimer.schedule(new TimerTask() {
@Override
public void run() {
// this code will be executed after 2 seconds
if (mBssOutCom != null) {
try {
mBssOutCom.close();
} catch (IOException e) {
e.printStackTrace();
}
mBssOutCom = null;
}
}
}, 1500);
socketCom = mBssOutCom.accept(1000);
} catch (IOException e) {
Log.d(TAG, "tryToConnect: accept timedOut");
}
securityTimer.cancel();
if (mBssOutCom != null) {
mBssOutCom.close();
mBssOutCom = null;
}
If anyone is aware of a better solution, I'd love to hear it!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With