Android:蓝牙无法获取端口号

Android:蓝牙无法获取端口号,android,bluetooth,Android,Bluetooth,我在应用程序中使用蓝牙时遇到问题。似乎在创建了28个BluetoothSocket/BluetoothServerSocket之后,所有端口都被占用了。这些插座不需要同时打开,自从启用蓝牙以来,只有28个插座 这可以使用中提供的BluetoothChat示例进行复制。只需打开和关闭应用程序15次(应用程序每次创建2个套接字)。在第15次,它将崩溃,并将继续崩溃,直到您禁用蓝牙,然后重新启用: 12-06 18:43:58.177: E/BluetoothSocket(18530): bindLi

我在应用程序中使用蓝牙时遇到问题。似乎在创建了28个
BluetoothSocket
/
BluetoothServerSocket
之后,所有端口都被占用了。这些插座不需要同时打开,自从启用蓝牙以来,只有28个插座

这可以使用中提供的BluetoothChat示例进行复制。只需打开和关闭应用程序15次(应用程序每次创建2个套接字)。在第15次,它将崩溃,并将继续崩溃,直到您禁用蓝牙,然后重新启用:

12-06 18:43:58.177: E/BluetoothSocket(18530): bindListen, fail to get port number, exception: java.io.IOException: read failed, socket might closed, read ret: -1
12-06 18:43:58.193: E/BluetoothChatService(18530): Socket Type: Insecurelisten() failed
12-06 18:43:58.193: E/BluetoothChatService(18530): java.io.IOException: Error: -1
12-06 18:43:58.193: E/BluetoothChatService(18530):  at android.bluetooth.BluetoothAdapter.createNewRfcommSocketAndRecord(BluetoothAdapter.java:1035)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at android.bluetooth.BluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(BluetoothAdapter.java:982)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at com.example.android.BluetoothChat.BluetoothChatService$AcceptThread.<init>(BluetoothChatService.java:280)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at com.example.android.BluetoothChat.BluetoothChatService.start(BluetoothChatService.java:119)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at com.example.android.BluetoothChat.BluetoothChat.onResume(BluetoothChat.java:131)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at android.app.Activity.performResume(Activity.java:5182)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at android.app.ActivityThread.access$600(ActivityThread.java:141)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at android.os.Handler.dispatchMessage(Handler.java:99)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at android.os.Looper.loop(Looper.java:137)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at android.app.ActivityThread.main(ActivityThread.java:5039)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at java.lang.reflect.Method.invokeNative(Native Method)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at java.lang.reflect.Method.invoke(Method.java:511)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
12-06 18:43:58.193: E/BluetoothChatService(18530):  at dalvik.system.NativeStart.main(Native Method)
12-06 18:43:58.177:E/BluetoothSocket(18530):bindListen,无法获取端口号,异常:java.io.IOException:读取失败,套接字可能已关闭,读取ret:-1
12-06 18:43:58.193:E/BluetoothChatService(18530):套接字类型:unsecureListen()失败
12-06 18:43:58.193:E/BluetoothChatService(18530):java.io.IOException:错误:-1
12-06 18:43:58.193:E/BluetoothChatService(18530):在android.bluetooth.BluetoothAdapter.createNewRfcommSocketAndRecord(BluetoothAdapter.java:1035)
12-06 18:43:58.193:E/BluetoothChatService(18530):在android上。bluetooth.BluetoothAdapter.ListenusingSecureRFCommwithServiceRecord(BluetoothAdapter.java:982)
12-06 18:43:58.193:E/BluetoothChatService(18530):在com.example.android.BluetoothChat.BluetoothChatService$AcceptThread。(BluetoothChatService.java:280)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于com.example.android.BluetoothChat.BluetoothChatService.start(BluetoothChatService.java:119)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于com.example.android.BluetoothChat.BluetoothChat.onResume(BluetoothChat.java:131)
12-06 18:43:58.193:E/BluetoothChatService(18530):在android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
12-06 18:43:58.193:E/BluetoothChatService(18530):在android.app.Activity.performResume(Activity.java:5182)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235)
12-06 18:43:58.193:E/BluetoothChatService(18530):在android.app.ActivityThread.access$600(ActivityThread.java:141)
12-06 18:43:58.193:E/BluetoothChatService(18530):在android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于android.os.Handler.dispatchMessage(Handler.java:99)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于android.os.Looper.loop(Looper.java:137)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于android.app.ActivityThread.main(ActivityThread.java:5039)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于java.lang.reflect.Method.Invokenactive(本机方法)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于java.lang.reflect.Method.invoke(Method.java:511)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
12-06 18:43:58.193:E/BluetoothChatService(18530):位于dalvik.system.NativeStart.main(本机方法)

有没有办法在套接字关闭后释放端口?

我可以在这里的设备上验证此行为;虽然以相同方式崩溃所需的次数因设备而异(我认为运行4.2的Galaxy Nexus需要20-25次),但可用的端口句柄数量似乎有所不同。我还可以在示例应用程序(或您的应用程序)中提供信息,说明问题不是内存泄漏,因为
BluetoothSocket
的所有实例都已由Dalvik发布并关闭。这里列出的步骤只测试了
BluetoothServerSocket
上的问题,因此不清楚问题是否与此相关,尽管看起来不太可能

至少在我的设备上,在切换蓝牙适配器的状态之前,你甚至无法再次启动应用程序,因此问题肯定出在堆栈上连接的底层管理中


我会在这里提交一个bug,并给出复制的步骤,我很乐意对它进行更新。

最近,我不得不深入研究如何解决这个问题。升级Android不是一个选项

事实证明,如果不是每次建立/断开连接时都销毁和重新创建mAcceptThread,而是保留原始实例并重新使用它。这将最大限度地减少错误对应用程序的影响

在BluetoothChatService文件的connected()函数中,不要取消mAcceptThread:

public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
...
...
...
// Cancel the accept thread because we only want to connect to one device 
//(Rather stay listening so comment out the cancel line!!) 
//If necessary, use some other state to prevent a second connection.
//DONT CANCEL: if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;}
...
...
在AcceptThread类中,修改run()函数中的循环:

            // Listen to the server socket if we're not connected
//OLD LOOP:            while (mState != STATE_CONNECTED)
//(Rather use STATE_NONE so the loop will only stop when the service does)
            while (mState != STATE_NONE) 

您的代码中可能还有其他事情要做,以正确实现该想法。

要重新连接,我在片段中的定时处理程序中使用:

BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(MainActivity.mac);
                    // Attempt to connect to the device
                    mChatService.connect(device, true);
为了解决“重新连接超过28次时失败”的问题,每次断开连接时服务重新启动时,我都会发表评论:

//BluetoothChatService.this.start();
我还注释掉了插座关闭的所有部分:

//socket.close();

//mmServerSocket.close();

//mmSocket.close();

//mSecureAcceptThread.cancel();
并为accept线程添加了一个NOTNULL检测,并连接了一个and not fail:

if(mAdapter != null) {
                        tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
                                MY_UUID_SECURE);
                    }else{
                        mAdapter = BluetoothAdapter.getDefaultAdapter();
                        //mState = STATE_NONE;
                    }


我仍然会随机断开连接,但服务会重新连接,一切正常。

感谢您的关注!我在这里提交了一个bug:。在运行4.2.1的Galaxy Nexus和Nexus 7上,应用程序崩溃了15次。我的NexusOne从未崩溃,所以希望这只是JB的问题。
if(mmServerSocket != null) {
                        socket = mmServerSocket.accept();
                    }