我的应用程序通过制作和处理连接来连接蓝牙SPP模块,就像the Android Bluetooth documentation中所述。也就是说,在我的连接线程中,我习惯于使用:
进行连接socket = device.createRfcommSocketToServiceRecord(MY_UUID)
其中UUID是众所周知的' SPP UUID,00001101-0000-1000-8000-00805F9B34FB。
我连接的蓝牙设备是小型蓝牙/串行适配器。我有三个用于测试的。其中两个是" Linvor"目前在eBay上的蓝牙到TTL级串行PCB是完全相同的;第三个是制造商未知的完全封闭的适配器。
在我开发此应用程序的过程中,我经常在各种设备上进行测试,这些设备包括Android 2.2.1版(我的旧Archos 101)到Archos Honeycomb设备。我一直在测试的设备主要是我的Desire HD,目前有Android版本2.3.5。大约在一年左右的时间里,我一直在研究这个问题,我可以自信地说,我从来没有遇到任何连接问题。
昨天在使用我的Desire HD(2.3.5)测试期间,我发现该应用程序将不再连接到我最近一直在使用的Linvor蓝牙PCB。在使用上面引用的代码行获取套接字后,在尝试socket.connect()
时,我会立即获得IOException
Unable to start discovery
。
我接下来要做的是交换到我的其他备用Linvor模块并尝试配对和连接。应用程序连接得很好。然后我也交换了我的第三个打包蓝牙适配器,连接到那个应用程序也很好。回到我的第一个Linvor模块,该应用程序仍然拒绝连接。我确保我解开了“错误”的错误。我的Desire HD上的Linvor设备,关闭蓝牙,关闭手机,取出并重新插入电池,开机,重新配对等,然后再试一次。该应用程序仍拒绝连接到第一个Linvor模块,但可以很好地连接到第二个Linvor模块和其他适配器模块。
然后我抓住我的Archos 101(2.2.1)并启动一个仍然安装在其上的应用程序的较旧版本。 Archos 101立即连接到“故障”状态。 Linvor模块就好了。
此时我开始怀疑这两种设备 - 即我的Desire HD,或者更可能是Linvor模块 - 是否会在配对设备的闪存表中有一些损坏的条目。换句话说,在第一个Linvor模块中某些东西意味着它不再接受来自我的Desire HD的连接(虽然它确实接受配对),但它仍将接受来自其他设备的连接;同时,我的Desire HD可以像往常一样愉快地连接到其他设备,包括其他备用的Linvor模块。
经过几个小时的搔痒和绝望,我决定尝试reflection connection method as described in Michael's answer here。这是我听过很多的东西,我觉得它适用于Android 2.2及以下版本。但是,在我使用各种Android设备的蓝牙SPP的整个一年中,我从不需要使用它,因为.createRfcommSocketToServiceRecord()
一直对我有效。因此,我使用迈克尔对该问题的答案中给出的代码来创建我的socket
,令我惊讶的是,我的Desire HD连接到了“错误的”#39; Linvor模块。
所以回顾一下,情况似乎是这样的:
在过去的一年中,我已经能够在我的2.2.1和2.3.5设备上定期使用.createRfcommSocketToServiceRecord()
连接到我的三个蓝牙SPP适配器。
然后,在某一天,没有对手机或蓝牙适配器上的软件进行任何更改,第一个适配器突然需要使用反射方法来连接工作;另外两个适配器(其中一个与第一个类型相同)继续使用.createRfcommSocketToServiceRecord()
连接我的应用程序。请注意,在此行为突然发生变化之前,我的蓝牙代码绝对没有任何变化。
earth 上发生了什么?
任何人都可以告诉我Android版本的反映' hack'应该不吗?我的印象是,在2.3.5(我的Desire HD)上不应再需要了。这是对的吗?
与.createRfcommSocketToServiceRecord()
的错误的性质是什么,以便连接通常可以工作,但有时根据月亮的相位不起作用?
以下是使用.createRfcommSocketToServiceRecord()
时与特定Linvor模块连接失败时的Logcat输出:
01-29 10:22:00.004: D/View(8165): onTouchEvent: viewFlags: 0x18005001
01-29 10:22:00.014: D/View(8165): onTouchEvent: isFocusable: true, isFocusableInTouchMode: false, isFocused: false; focusTaken: false
01-29 10:22:00.034: D/WindowManagerImpl(8165): finishRemoveViewLocked, mViews2: com.android.internal.policy.impl.PhoneWindow$DecorView@406215d8
01-29 10:22:00.074: I/BLZ20_WRAPPER(8165): blz20_wrp_socket: fam 31, type 1, prot BTPROTO_RFCOMM
01-29 10:22:00.084: D/BLZ20_WRAPPER(8165): blz20_init: initializing...
01-29 10:22:00.084: D/BTL_IFC_WRP(8165): wsactive_init: init active list
01-29 10:22:00.084: I/BTL_IFC(8165): main_client_thread: Client main thread starting
01-29 10:22:00.194: D/BLZ20_WRAPPER(8165): blz20_init: success
01-29 10:22:00.194: I/BTL_IFC(8165): BTL_IFC_RegisterSubSystem: Register subsystem [BTS]
01-29 10:22:00.194: I/BTL_IFC(8165): btl_ifc_ctrl_connect: Connect control channel for subsystem [BTS]
01-29 10:22:00.194: D/BTL_IFC_WRP(8165): wrp_sock_create: CTRL
01-29 10:22:00.194: D/BTL_IFC_WRP(8165): wrp_alloc_new_sock: wrp_alloc_new_sock sub 1
01-29 10:22:00.194: D/BTL_IFC_WRP(8165): wrp_sock_create: 66
01-29 10:22:00.194: D/BTL_IFC_WRP(8165): wrp_sock_connect: wrp_sock_connect brcm.bt.btlif:9000 (66)
01-29 10:22:00.194: D/BTL_IFC_WRP(8165): wrp_sock_connect: BTLIF_MAKE_LOCAL_SERVER_NAME return name: brcm.bt.btlif.9000
01-29 10:22:00.194: D/BTL_IFC_WRP(8165): wrp_sock_connect: wrp_sock_connect ret:0 server name:brcm.bt.btlif.9000
01-29 10:22:00.194: I/BTL_IFC_WRP(8165): wrp_sock_connect: Connected. (66)
01-29 10:22:00.194: I/BTL_IFC(8165): send_ctrl_msg: [BTL_IFC CTRL] send BTLIF_REGISTER_SUBSYS_REQ (BTS) 0 pbytes (hdl 66)
01-29 10:22:00.194: D/BTL_IFC(8165): BTL_IFC_RegisterSubSystem: add new ctrl fd to active set
01-29 10:22:00.194: D/BTL_IFC_WRP(8165): wrp_wsock_create: BTS
01-29 10:22:00.194: D/BTL_IFC_WRP(8165): wrp_alloc_new_sock: wrp_alloc_new_sock sub 16
01-29 10:22:00.194: D/BTL_IFC_WRP(8165): wrp_wsock_create: 67
01-29 10:22:00.194: D/BLZ20_WRAPPER(8165): btsk_alloc_add: success
01-29 10:22:00.194: D/BLZ20_WRAPPER(8165): btsk_dump_list: fd (-1:67), bta -1, rc 0, wflags 0x0, cflags 0x0, port 0
01-29 10:22:00.194: I/BLZ20_WRAPPER(8165): blz20_wrp_socket: return 67
01-29 10:22:00.194: D/BLZ20_WRAPPER(8165): blz20_wrp_setsockopt: fd (-1:67), bta -1, rc 0, wflags 0x0, cflags 0x0, port 0
01-29 10:22:00.194: I/BLZ20_WRAPPER(8165): blz20_wrp_setsockopt: configure rfcomm lm mode 0x26, (master:0, auth 1, enc 1)
01-29 10:22:00.194: I/BLZ20_WRAPPER(8165): blz20_wrp_setsockopt: success
01-29 10:22:00.194: D/BLZ20_WRAPPER(8165): blz20_wrp_setsockopt: fd (-1:67), bta -1, rc 0, wflags 0x0, cflags 0x0, port 0
01-29 10:22:00.194: I/BLZ20_WRAPPER(8165): blz20_wrp_setsockopt: configure rfcomm sndbuf len 71680 bytes
01-29 10:22:00.194: I/BLZ20_WRAPPER(8165): blz20_wrp_setsockopt: success
01-29 10:22:00.194: D/BLZ20_ASOCKWRP(8165): asocket_init
01-29 10:22:00.194: I/BLZ20_WRAPPER(8165): blz20_wrp_fcntl: s 67, cmd 3
01-29 10:22:00.194: D/BLZ20_WRAPPER(8165): blz20_wrp_fcntl: fd (-1:67), bta -1, rc 0, wflags 0x0, cflags 0x0, port 0
01-29 10:22:00.194: I/BLZ20_WRAPPER(8165): blz20_wrp_fcntl: s 67, cmd 4
01-29 10:22:00.194: D/BLZ20_WRAPPER(8165): blz20_wrp_fcntl: fd (-1:67), bta -1, rc 0, wflags 0x0, cflags 0x0, port 0
01-29 10:22:00.194: D/BLZ20_WRAPPER(8165): blz20_wrp_fcntl: transparant fcntl
01-29 10:22:00.194: I/BLZ20_WRAPPER(8165): blz20_wrp_fcntl: s 69, cmd 3
01-29 10:22:00.194: I/BLZ20_WRAPPER(8165): blz20_wrp_fcntl: wsock not found, pass through transparantly
01-29 10:22:00.194: I/BLZ20_WRAPPER(8165): blz20_wrp_fcntl: s 69, cmd 4
01-29 10:22:00.194: I/BLZ20_WRAPPER(8165): blz20_wrp_fcntl: wsock not found, pass through transparantly
01-29 10:22:00.194: I/BLZ20_WRAPPER(8165): blz20_set_asocket: success (67,68,69)
01-29 10:22:00.214: I/BluetoothIF(8165): BEGIN mConnectThread
01-29 10:22:00.234: E/BluetoothIF(8165): TP: IOException error: java.io.IOException: Unable to start Service Discovery
01-29 10:22:00.234: E/BluetoothIF(8165): Unable to start Service Discovery
01-29 10:22:00.234: E/BluetoothIF(8165): Unable to start Service Discovery
01-29 10:22:00.234: D/BluetoothSocket(8165): close(): android.bluetooth.BluetoothSocket@405c8f78
01-29 10:22:00.234: D/BLZ20_ASOCKWRP(8165): asocket_abort [67,68,69]
01-29 10:22:00.234: I/BLZ20_WRAPPER(8165): blz20_wrp_shutdown: s 67, how 2
01-29 10:22:00.234: D/BLZ20_WRAPPER(8165): blz20_wrp_shutdown: fd (-1:67), bta -1, rc 0, wflags 0x0, cflags 0x0, port 0
01-29 10:22:00.234: I/BLZ20_WRAPPER(8165): blz20_wrp_shutdown: shutdown socket
01-29 10:22:00.234: D/BLZ20_WRAPPER(8165): blz20_wrp_write: wrote 1 bytes out of 1 on fd 69
01-29 10:22:00.234: D/BLZ20_ASOCKWRP(8165): asocket_destroy
01-29 10:22:00.234: D/BLZ20_ASOCKWRP(8165): asocket_abort [67,68,69]
01-29 10:22:00.234: I/BLZ20_WRAPPER(8165): blz20_wrp_shutdown: s 67, how 2
01-29 10:22:00.234: D/BLZ20_WRAPPER(8165): blz20_wrp_shutdown: fd (-1:67), bta -1, rc 0, wflags 0x0, cflags 0x0, port 0
01-29 10:22:00.234: I/BLZ20_WRAPPER(8165): blz20_wrp_shutdown: shutdown socket
01-29 10:22:00.234: D/BLZ20_WRAPPER(8165): blz20_wrp_write: wrote 1 bytes out of 1 on fd 69
01-29 10:22:00.234: I/BLZ20_WRAPPER(8165): blz20_wrp_close: s 69
01-29 10:22:00.234: D/BLZ20_WRAPPER(8165): blz20_wrp_close: std close (69)
01-29 10:22:00.244: I/BLZ20_WRAPPER(8165): blz20_wrp_close: s 68
01-29 10:22:00.244: D/BLZ20_WRAPPER(8165): blz20_wrp_close: std close (68)
01-29 10:22:00.244: I/BLZ20_WRAPPER(8165): blz20_wrp_close: s 67
01-29 10:22:00.244: D/BLZ20_WRAPPER(8165): blz20_wrp_close: fd (-1:67), bta -1, rc 0, wflags 0x0, cflags 0x0, port 0
01-29 10:22:00.244: I/BLZ20_WRAPPER(8165): __close_prot_rfcomm: fd 67
01-29 10:22:00.244: I/BTL_IFC(8165): send_ctrl_msg: [BTL_IFC CTRL] send BTLIF_BTS_RFC_CLOSE (BTS) 8 pbytes (hdl 66)
01-29 10:22:00.244: D/BTL_IFC_WRP(8165): wrp_close_s_only: wrp_close_s_only [67] (67:-1) []
01-29 10:22:00.244: D/BTL_IFC_WRP(8165): wrp_close_s_only: data socket closed
01-29 10:22:00.244: D/BTL_IFC_WRP(8165): wsactive_del: delete wsock 67 from active list [ad40f904]
01-29 10:22:00.244: D/BTL_IFC_WRP(8165): wrp_close_s_only: wsock fully closed, return to pool
01-29 10:22:00.244: D/BLZ20_WRAPPER(8165): btsk_free: success
目前,我看到的最佳行动方案是设计我的代码,以便.createRfcommSocketToServiceRecord()
方法立即失败并且"无法启动发现"异常然后回到relection方法,直到今天,我从来没有需要使用。
其他信息:我的应用程序针对API级别8.怀疑RFCOMM连接错误会影响Android 2.2及更低版本,我尝试切换到API级别10,看看它是否会对.createRfcommSocketToServiceRecord()
的行为产生任何影响,但问题仍然存在:尝试连接到一个Linvor模块导致立即IOException如上所述。
谢谢 - 特雷夫
答案 0 :(得分:1)
苦苦挣扎同样的问题。在2部手机上使用API 10。两者都使用Android 4.0.4。 一部手机经常失败,“无法启动发现”,但使用反射。 第二部手机使用反射提供“Permission denied”但使用createRfcommSocketToServiceRecord()。
对于研究我检查了android的来源。 所以它在BluetoothSocket.java中失败了:
boolean inProgress = false;
try {
inProgress = service.fetchRemoteUuids(device.getAddress(), uuid, this);
} catch (RemoteException e) {Log.e(TAG, "", e);}
if (!inProgress) throw new IOException("Unable to start Service Discovery");
但是fetchRemoteUuids()有很多失败点而且没有,它们不会抛出异常而只返回false。 BluetoothService.java:
public synchronized boolean fetchRemoteUuids(String address, ParcelUuid uuid,
IBluetoothCallback callback) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
return false;
}
RemoteService service = new RemoteService(address, uuid);
if (uuid != null && mUuidCallbackTracker.get(service) != null) {
// An SDP query for this address & uuid is already in progress
// Do not add this callback for the uuid
return false;
}
if (mUuidIntentTracker.contains(address)) {
// An SDP query for this address is already in progress
// Add this uuid onto the in-progress SDP query
if (uuid != null) {
mUuidCallbackTracker.put(new RemoteService(address, uuid), callback);
}
return true;
}
boolean ret;
if (getBondState(address) == BluetoothDevice.BOND_BONDED) {
String path = getObjectPathFromAddress(address);
if (path == null) return false;
// Use an empty string for the UUID pattern
ret = discoverServicesNative(path, "");
} else {
ret = createDeviceNative(address);
}
mUuidIntentTracker.add(address);
if (uuid != null) {
mUuidCallbackTracker.put(new RemoteService(address, uuid), callback);
}
Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT);
message.obj = address;
mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY);
return ret;
}
本机方法是否失败导致我们成为司机?或者“uuid已经在进行中”部分失败,因为我甚至没有看到尝试连接/扫描uuid,只是立即获得异常。
答案 1 :(得分:1)