jjzjj

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

coder 2023-12-22 原文

我的应用程序通过建立和处理连接(如the Android Bluetooth documentation中所述)连接到蓝牙spp模块。也就是说,在我的连接线程中,我习惯于使用以下方法进行连接:

socket = device.createRfcommSocketToServiceRecord(MY_UUID)

其中uuid是“众所周知”的spp uuid,00001101-0000-1000-8000-00805F9B34FB。
我正在连接的蓝牙设备是小型蓝牙/串行适配器。我用了三个来做测试。其中两个是“linvor”蓝牙到ttl级别的串行pcb,目前ebay上到处都是,它们是相同的;第三个是制造商未知的完全封闭的适配器。
在开发这个应用程序的过程中,我经常在各种设备上进行测试,从android版本2.2.1(我以前的archos 101)到archos蜂窝设备。我一直在测试的设备主要是我的Desire HD,它目前有Android版本2.3.5。在这一年多的时间里,我一直在努力解决这个问题,我可以自信地说,我从来没有遇到过任何连接问题。
昨天在使用Desire HD(2.3.5)进行测试时,我发现应用程序将不再连接到我最近一直使用的Linvor Bluetooth PCB。在使用上面引用的代码行获得套接字之后,当尝试socket.connect()时,我将立即得到IOExceptionUnable 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()一直在为我工作。因此,我使用michael对这个问题的回答中给出的代码来创建我的socket,令我惊讶的是,我的desire hd连接到了“有问题”的linvor模块。
总而言之,情况似乎是这样的:
在过去的一年里,我已经能够在我的2.2.1和2.3.5设备上常规使用.createRfcommSocketToServiceRecord()来连接我的三个蓝牙spp适配器。
然后,有一天,在没有对手机或蓝牙适配器上的软件进行任何更改的情况下,第一个适配器突然需要反射方法才能使连接正常工作;另外两个适配器(其中一个适配器的类型与第一个适配器的类型相同)继续与我的应用程序JU连接使用.createRfcommSocketToServiceRecord()进行微调。请注意,在行为发生这种突然变化之前,我的蓝牙代码绝对没有任何变化。
这到底是怎么回事?
有人能告诉我什么Android版本的反射“黑客”不应该是必需的吗?在我的印象中,2.3.5(我的欲望高清)不应该再需要它了。是这样吗?
这个缺陷的本质是这样的吗?.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 connect bug会影响android 2.2及以下版本,于是尝试切换到api级别10,以查看它是否会对.createRfcommSocketToServiceRecord()的行为产生任何影响,但问题仍然存在:尝试连接一个linvor模块会导致上述即时ioexception。
谢谢-特雷夫

最佳答案

同样的问题。在两部手机上使用API 10。都是安卓4.0.4。
一部手机不断出现故障,出现“无法启动发现”的情况,但仍能进行反射。
第二个电话通过反射提供“权限被拒绝”,但与createrFCommSocketToServiceRecord()一起工作。
为了研究,我查阅了安卓的资料。
所以它在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。
蓝牙服务.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的尝试,只是立即出现异常。

关于android - 只有一个特定的蓝牙SPP模块,.createRfcommSocketToServiceRecord()突然不再有效,但反射方法有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9052460/

有关android - 只有一个特定的蓝牙SPP模块,.createRfcommSocketToServiceRecord()突然不再有效,但反射方法有效的更多相关文章

  1. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  4. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  5. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  6. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  7. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  8. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  9. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  10. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

随机推荐