BluetoothSocket.connect() 在 Android 9 的三星 S9 上失败
BluetoothSocket.connect() fails on Samsung S9 with Android 9
我正在开发需要与蓝牙设备配对的本机 Android 应用程序。
使用 Android 9 的三星 S9 用户报告说他们的手机无法与蓝牙设备配对,经过长时间的研究后,我请人进行测试,他们是对的,它适用于所有蓝牙设备设备但三星 9 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
有什么想法吗?
非常感谢。
毛里西奥
终于找到解决办法了。可能有人会遇到类似代码的类似问题(来自 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 中添加大部分代码已经解决了问题。
干杯!
毛里西奥
我正在开发需要与蓝牙设备配对的本机 Android 应用程序。
使用 Android 9 的三星 S9 用户报告说他们的手机无法与蓝牙设备配对,经过长时间的研究后,我请人进行测试,他们是对的,它适用于所有蓝牙设备设备但三星 9 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
有什么想法吗?
非常感谢。
毛里西奥
终于找到解决办法了。可能有人会遇到类似代码的类似问题(来自 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 中添加大部分代码已经解决了问题。
干杯!
毛里西奥