蓝牙射频通信无法在安卓 4.2 上连续建立



我有一个应用程序,它通过蓝牙通过RFCOMM与自定义设备进行通信。通信代码基于BluetoothTalk示例项目。它以前在Galaxy S3、Galaxy S2、Galaxy Note和Nexus 7上运行时没有任何问题。

最近,Nexus 7升级到了Android 4.2,从那时起,问题发生如下:

  1. 当你第一次使用应用程序建立连接时,意味着设备刚刚打开,应用程序刚刚启动,没问题,你可以正常获取数据。

  2. 然后,如果您停止通信并尝试重新启动,则通信失败,并出现错误"java.io.IOException:bt socket closed,read return:-1"。从那时起,无论你尝试重新连接多少次,它总是失败的。

  3. 让它再次工作的唯一方法是,如果你重新启动自定义设备和应用程序,然后尝试连接,通信就会正常。但是,一旦你停止并重新启动通信,它就会不断失败。

我借用了一个带有Android 4.2的Nexus 4,问题仍然存在。

这真的很烦人,因为我们设备的主要价值在于依赖蓝牙RFCOMM应用程序。我仔细查看了安卓4.2中BT的文档,没有看到任何重大变化。我对我这边的代码相当有信心,因为它适用于任何不运行4.2 的Android设备

任何提示或建议都将不胜感激。该设备需要在12月初进行演示,我们真的希望尽快解决这个问题。

编辑:现在4.2.1已经发布,问题仍然没有解决。我们至少能得到一些关于它是否正在工作并将很快修复的确认吗?

这对你没有多大帮助,但请注意,谷歌推出了一个全新的蓝牙堆栈,带有4.2。

这应该是一件好事——根据我作为用户和开发人员的经验,带有Bluez(旧组合)的Android从未可靠运行,所以我很高兴听到他们进行了全面重写。

我想我只能说,听起来你在新堆栈中遇到了一个bug或怪癖。很遗憾听到新堆栈也有问题。

关于您的演示,请注意,谷歌发布了所有Nexus设备的固件映像(https://developers.google.com/android/nexus/images),并且将它们闪烁到您的设备上相当容易。

因此,我建议您提交一份错误报告,然后将您的设备闪存到4.1.2。

在我的测试中也发生过这种情况。我的BluetoothChat示例代码你应该看看connectionLost方法。我不记得是否有任何变量可以保持丢失连接的数量,但你可以自己添加。在connectionLost方法中,测试丢失连接的数量是否小于预定义的数量(在我的案例中为3)。如果这是真的,那么用mHandler(toast)向UI发送一条消息,然后再次调用connect(device)。如果不是这样(您丢失连接超过3次),请调用stop()方法。

还要确保像这样打开ConnectThread中的套接字:

public ConnectThread(BluetoothDevice device, boolean isSecure) {
mmDevice = device;
BluetoothSocket tmp = null;
mSocketType = isSecure ? "Secure" : "Insecure";
// Get a BluetoothSocket for a connection with the given BluetoothDevice
if (isSecure) {
// reflection is better to use
Method m = null;
try {
Log.d(TAG, "create reflection");
m = device.getClass().getMethod("createRfcommSocket",new Class[] { int.class });
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
}
try {
tmp = (BluetoothSocket) m.invoke(device, 1);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
mmSocketFallBack = tmp;
} else {
Log.d(TAG, "create insecure");
try {
tmp = device
.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
e.printStackTrace();
}
}
mmSocket = mmSocketFallBack;
}

你的connectionLost应该看起来像:

public void connectionLost() {
init = false;
Log.d(TAG, "connectionLost -> " + mConnectionLostCount);
mConnectionLostCount++;
if (mConnectionLostCount < 3) {
// Send a reconnect message back to the Activity
Message msg = mHandler.obtainMessage(cBluetooth.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(WebAppInterface.TOAST, "Connection lost. Reconnecting...");
msg.setData(bundle);
mHandler.sendMessage(msg);
connect(mSavedDevice,true);     
} else {
mConnectionLostCount = 0;
Message msg = mHandler.obtainMessage(cBluetooth.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(WebAppInterface.TOAST,"Device connection was lost!");
msg.setData(bundle);
mHandler.sendMessage(msg);
cBluetooth.this.stop();
}
}

我希望你能根据你的情况调整一下。你也可以查看这些链接,它们对我帮助很大:

  1. 远程控制示例
  2. 连接染色解决方案
  3. 蓝牙服务示例,灵感来自

我也遇到了类似的问题,并花了一些时间调试这个问题。我正在运行Android 4.3,发现BluetoothChat示例代码唯一需要的基本修改是设置:

MY_UUID_SECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

我正在尝试连接到HC-05蓝牙模块,我相信它使用了该UUID指示的SPP配置文件。您可以使用以下代码行查询设备的UUID:

UUID uuid = device.getUuids()[0].getUuid();

根据您连接的设备类型,验证UUID,看看它是否与有意义的配置文件匹配。

MY_UUID_SECURE = uuid;

UUID可能指示不同类型的设备配置文件,这取决于您要连接的设备。有了正确的UUID,我仍然能够运行AcceptThread代码并作为BluetoothServerSocket进行侦听,没有任何问题。我希望这能有所帮助,然而,我对Android和蓝牙的开发相对陌生,所以如果我的假设是错误的,请纠正我。

遇到了类似的问题。通过以17为构建目标的4.2 SDK构建,修复了其中一些问题。

我终于找到了解决方案。

事实证明,这不是新的蓝牙驱动程序中的错误。这是蓝牙示例应用程序中没有考虑的一个角落案例,更具体地说,是由Android SDK提供的BluetoothChat项目。

在BluetoothChat示例项目中的蓝牙服务代码中,当连接失败或丢失时,它总是重新启动服务以重新启动侦听模式。当手机用作服务器时没有问题,但是,在某些情况下,当手机用作客户端时,一旦进入监听模式,您就无法连接到其他服务器。因为在"connect"函数中,它不会取消(in)SecureAcceptThread。所以,本质上,您是在以服务器的身份侦听其他连接,同时尝试以客户端的身份连接到其他服务器。这是矛盾的。

解决这个问题的方法是,如果你确定你的手机不会被用作监听传入连接的服务器,那么只要删除代码,在连接失败或停止后重新启动监听模式。

我的Nexus 4遇到了同样的问题。

在我的案例中,我认为问题在于SDP服务发现协议。设备和服务器必须对某个服务使用相同的UUID。

我在我的应用程序中使用SPP(串行端口协议)。因此,我将蓝牙聊天示例代码中的UUID从"fa87c0d0-afac-11de-8a39-080020c9a66"更改为SPP"00001101-0000-1000-8000-00805F9B34FB"。现在一切都好了。

我在BluetoothChatService.start()中禁用了acceptThread的侦听代码。现在更简洁了。希望它能有所帮助。

我在4.2.2上也有同样的经验。

但我发现,只有在我的应用程序失败或在没有正确清理资源(套接字和/或流)的情况下被杀死后,蓝牙堆栈才会开始出现错误。在此之前,当我正确关闭我的应用程序时,它运行良好。

例如,当我关闭套接字然后关闭应用程序时,我可以启动它并再次正常连接。如果我在没有关闭套接字的情况下杀死了我的应用程序,那就太糟糕了,我必须重新启动设备才能让它重新工作。

所以,新的安卓蓝牙堆栈似乎在隐式清理机制中存在一些缺陷。当一个应用程序失败时,安卓应该清理打开的蓝牙资源,但这并没有发生。

我的蓝牙管理代码在应用程序子类中。没有办法——或者我看不到——如何挂接应用程序销毁并进行清理。

任何建议都感谢

编辑:

我做了一个相当混乱的变通办法。

我创建了包含单个远程服务的单独应用程序。我把所有的通信代码(套接字和流打开、读取、写入、关闭)都移到了这个远程服务中。然后,如果主应用程序崩溃或被终止,则服务仍在运行。当我再次启动应用程序时,连接仍然处于打开状态。从蓝牙输入流读取的字节通过标准服务消息传输到主应用程序。就我的情况而言,这是可以的,因为我传输的数据量非常小。

当包含服务的应用程序被终止时,同样的混乱也会发生。

我也面临同样的问题。这对我有效:

try {
Thread.sleep(1000); 
}
catch(Exception e3)
{
Toast.makeText(getApplicationContext(), "wa ni sud sa thread sleep!", Toast.LENGTH_SHORT).show();
}
btSocket.close();

相关内容

  • 没有找到相关文章

最新更新