2

I am working on a native Android application that needs to be paired with a bluetooth device.

Users with Samsung S9 with Android 9 are reporting that their mobiles does not pair with out bluetooth devices and after doing a long research I requested one to test it, and they are right, it works on every device but Samsung 9 with Android 9.

Here is my code

try {
    if (sock == null) {
        final BluetoothDevice device = BT.getRemoteDevice(_btMac);
        if (device == null) {
            setBluetoothState(BT_DISCONNECTED, false);
            return;
        }

        UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
        sock = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);

        if (sock != null) {
            in = sock.getInputStream();
            out = sock.getOutputStream();
            mBtConnectCounter = 0;
            if (localConnect != null) {
                if (VersionUtils.isAtLeastNougat()) {
                    if (localConnect.isAlive()) {
                        localConnect.interrupt();
                    }
                }
            }
            localConnect = new Thread() {
            public void run() {
                try {
                    BluetoothAdapter bT = BluetoothAdapter.getDefaultAdapter();
                    if (bT != null) {
                        if (bT.isEnabled()) {
                            bT.cancelDiscovery();
                            Log.d(TAG, "localConnect() INI:sock.connect()");
                            if (sock != null) {
                                sock.connect();
                                Log.d(TAG, "localConnect() END: sock.connect()");
                                setBluetoothState(BT_CONNECTED, true);
                                startReadThread();
                                refreshMainActivity();
                            }
                        }
                    }
                } catch (IOException e) {
                    Log.e(TAG, "localConnect() EXCEPTION: sock.connect() " + e.getMessage());
                }
                if (!sockedConnected) {
                    int localCounter = mBtConnectCounter;
                    int dif = 0;
                    while ((mBtConnectCounter < 25) && (dif < 3)) {
                        if (mBtConnectCounter > localCounter)
                            dif = mBtConnectCounter - localCounter;
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        setBluetoothState(BT_DISCONNECTED, false);
                    }
                }
            };
            threadPoolDevelopers.submit(localConnect);
         } else
             setBluetoothState(BT_DISCONNECTED, false);
             return;
         }
    } catch (IOException e) {
        setBluetoothState(BT_DISCONNECTED, false);
        closeSocket();
        return;
     } catch (final Exception e) {
        setBluetoothState(BT_DISCONNECTED, false);
        return;
     }
}

I suppose that the problem is on the socket instance creation.

I tried also with...

sock = device.createRfcommSocketToServiceRecord(MY_UUID);

and with...

Method m = device.getClass().getMethod("createRfcommSocket", int.class);
sock = (BluetoothSocket) m.invoke(device, 1);

But anything is working, here are some logs:

D/BluetoothAdapter: cancelDiscovery
D/bt_ifac: localConnect() INI: sock.connect()
D/BluetoothUtils: isSocketAllowedBySecurityPolicy start : device null
W/BluetoothAdapter: getBluetoothService() called with no BluetoothManagerCallback
E/bt_ifac: cerrarSocketBluetooth()
D/BluetoothSocket: close() this: android.bluetooth.BluetoothSocket@befe2cd, channel: -1, mSocketIS: android.net.LocalSocketImpl$SocketInputStream@3cc3782, mSocketOS: android.net.LocalSocketImpl$SocketOutputStream@7696e93mSocket: android.net.LocalSocket@470ed0 impl:android.net.LocalSocketImpl@9a4dec9 fd:java.io.FileDescriptor@f8a49ce, mSocketState: INIT
D/BluetoothSocket: close() this: android.bluetooth.BluetoothSocket@befe2cd, channel: -1, mSocketIS: android.net.LocalSocketImpl$SocketInputStream@3cc3782, mSocketOS: android.net.LocalSocketImpl$SocketOutputStream@7696e93mSocket: null, mSocketState: CLOSED
E/bt_ifac: localConnect() EXCEPTION: sock.connect() read failed, socket might closed or timeout, read ret: -1

Any idea?

Thank you so much.

Mauricio

1 Answers1

0

finally found a solution. Probably someone will have a similar problem with similar code (classic copy paste from Github sample...) so here is my solution.

try {
    if (sock == null) {
        if (isWorkAroundSamsungS9()) {
            initLocalConnectionS9();
        } else {
            initLocalConnectionStandard();
        }
    } else
        setBluetoothState(BT_DISCONNECTED, false);
        return;
} catch (final IOException e) {
    setBluetoothState(BT_DISCONNECTED, false);
    closeSocket();
    return;
} catch (final Exception e) {
    setBluetoothState(BT_DISCONNECTED, false);
    return;
}

Where isWorkAroundSamsungS9() is...

private boolean isWorkAroundSamsungS9() {
    return Build.MANUFACTURER.toLowerCase().contains("samsung") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
}

initLocalConnectionStandard() uses the old code and initLocalConnectionS9() has a few changes...

private synchronized void initLocalConnectionS9() {
    localConnect = new Thread() {
        public void run() {
            final BluetoothDevice btDevice;
            BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
            int connectionRetries = 0;
            while (bluetoothState != BT_CONNECTED && connectionRetries < 3) {
                try {
                    bluetoothState = BT_CONNECTING;
                    sock = null;
                    final BluetoothAdapter BT = BluetoothAdapter.getDefaultAdapter();
                    btDevice = BT.getRemoteDevice(btMac);
                    final UUID MY_UUID = UUID
                            .fromString("00001101-0000-1000-8000-00805F9B34FB");
                    sock = btDevice
                            .createInsecureRfcommSocketToServiceRecord(MY_UUID);
                    in = sock.getInputStream();
                    out = sock.getOutputStream();
                    Log.d(TAG, "localConnect() INI: sock.connect()");
                    sock.connect();
                    Log.d(TAG, "localConnect() END: sock.connect()");
                    setBluetoothState(BT_CONNECTED, true);
                    startReadThread();
                    refreshMainActivity();
                } catch (final Exception e) {
                    connectionRetries++;
                    closeSocket();
                    bluetoothState = BT_DISCONNECTED;
                    Log.e(TAG, "localConnect() EXCEPTION: sock.connect()" + e);
                    if (connectionRetries >= 3) {
                        setBluetoothState(BT_DISCONNECTED, false);
                    } else {
                        Log.d(TAG, "Bluetooth connection retries: " + connectionRetries);
                        delay(500);
                    }
                }
            }
        }
    };
    threadPoolDevelopers.submit(localConnect);
}

Seems that making initLocalConnectionS9() synchronized and adding most of the code in the thread localConnect has solved the problem.

Cheers!

Mauricio