带有Android 9的Samsung S9上BluetoothSocket.connect()失败

时间:2019-02-08 15:39:39

标签: android bluetooth-socket

我正在处理需要与蓝牙设备配对的本机Android应用程序。

使用装有Android 9的Samsung S9的用户报告说,他们的手机无法与蓝牙设备配对,经过长时间的研究,我要求对它进行测试,他们是对的,它可以在除装有Android 9的Samsung 9之外的所有设备上使用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 :(得分:0)

终于找到了解决方案。也许有人会用类似的代码(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 中添加大多数代码已解决了该问题。

干杯!

毛里西奥