我的应用程序通过制作和处理连接来连接到蓝牙SPP模块,就像在
the Android Bluetooth documentation中所描述的那样.也就是说,在我的连接线程中,我习惯于使用以下连接建立连接:
socket = device.createRfcommSocketToServiceRecord(MY_UUID)
其中UUID是“众所周知的”SPP UUID,00001101-0000-1000-8000-00805F9B34FB.
我连接的蓝牙设备是小型蓝牙/串行适配器.我有三个我一直用于测试.其中两个是“Linvor”蓝牙到TTL级别的串行PCB,目前全部都在eBay上,它们完全相同;第三个是制造商未知的完全封闭的适配器.
在我开发此应用程序的过程中,我经常在各种设备上进行测试,这些设备的范围从Android 2.2.1版(我的旧Archos 101)到Archos Honeycomb设备.我一直在测试的设备主要是我的Desire HD,目前有Android版本2.3.5.在过去一年左右的时间里,我一直在研究这个问题,我可以自信地说我从来没有遇到任何连接问题.
昨天在使用我的Desire HD(2.3.5)测试期间,我发现该应用程序将不再连接到我最近一直在使用的Linvor蓝牙PCB.在使用上面引用的代码行获取套接字后,在尝试socket.connect()时,我会立即得到一个无法启动发现的IOException.
我做的下一件事是交换到我的其他备用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()一直对我有用.因此,我使用迈克尔对该问题的回答中给出的代码来创建我的套接字,令我惊讶的是,我的Desire HD连接到’错误的’Linvor模块.
所以回顾一下,情况似乎是这样的:
在过去的一年里,我已经能够在我的2.2.1和2.3.5设备上定期使用.createRfcommSocketToServiceRecord()连接到我的三个蓝牙SPP适配器.
然后,在某一天,在手机或蓝牙适配器上的软件没有任何变化的情况下,第一个适配器突然需要反射方法来连接工作;另外两个适配器(其中一个与第一个类型相同)继续使用.createRfcommSocketToServiceRecord()连接我的应用程序.请注意,在此行为突然发生变化之前,我的蓝牙代码绝对没有任何变化.
这到底是怎么回事?
任何人都可以建议我在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, mViews07002: 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()方法立即失败,并且“无法启动发现”异常,那么回到重选方法,直到今天,我从来没有用过.
其他信息:我的应用程序针对API级别8.怀疑RFCOMM连接错误会影响Android 2.2及更低版本,我尝试切换到API级别10只是为了查看它是否会对.createRfcommSocketToServiceRecord()的行为产生任何影响,但问题是持久化:尝试连接到一个Linvor模块导致立即IOException,如上所述.
谢谢 – 特雷夫
最佳答案 苦苦挣扎同样的问题.在2部手机上使用API 10.两者都使用Android 4.0.4.
一部手机经常失败,“无法启动发现”,但使用反射.
第二部手机使用反射提供“权限被拒绝”,但与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,只是立即获得异常.