Сбой BluetoothSocket.connect () на Samsung S9 с Android 9 - PullRequest
0 голосов
/ 08 февраля 2019

Я работаю над собственным приложением для Android, которое необходимо подключить к устройству Bluetooth.

Пользователи с Samsung S9 с Android 9 сообщают, что их мобильные телефоны не соединяются с Bluetooth-устройствами, и после долгих исследований я попросил один из них протестировать его, и они правы, он работает на всех устройствах, кроме Samsung9 с Android 9.

Вот мой код

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;
     }
}

Полагаю, проблема в создании экземпляра сокета.

Я пробовал также с ...

sock = device.createRfcommSocketToServiceRecord(MY_UUID);

и с ...

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

Но что-то работает, вот некоторые журналы:

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

Есть идеи?

Большое спасибо.

Маурисио

1 Ответ

0 голосов
/ 13 февраля 2019

наконец-то нашел решение.Вероятно, у кого-то будет похожая проблема с похожим кодом (классическая копия вставки из примера Github ...), поэтому вот мое решение.

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;
}

Где isWorkAroundSamsungS9 () - это ...

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

initLocalConnectionStandard () использует старый код, а initLocalConnectionS9 () имеет несколько изменений ...

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);
}

Кажется, чтоВыполнение синхронизации initLocalConnectionS9 () и добавление большей части кода в поток localConnect решило проблему.

Ура!

Маурисио

...