只有一个特定的蓝牙SPP模块,.createRfcommSocketToServiceRecord()突然不再有效,但反射方法有效

时间:2012-01-29 10:26:31

标签: android bluetooth

我的应用程序通过制作和处理连接来连接蓝牙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如上所述。

谢谢 - 特雷夫

2 个答案:

答案 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)

Linvor 1.8在这里 我经常与这个设备斗争。您遇到的问题之一就是我遇到的问题之一 当器件完全上电时,可以通过向下拉复位引脚(用跳线将引脚跳到GND)来解决 复位引脚是器件左下角的第3个引脚 对我来说,这将允许我在没有反射的情况下连接到设备一次,但它可以再次回到不良行为 我的建议是你实现从android到设备的看门狗ping,并在计时器到达时用剩余的GPIO引脚触发复位命令。
至于为什么以及什么引发了这种行为。我仍然不知道,但希望有人会弄清楚。

我的怀疑是该设备陷入了未知状态 reset pin