![](/img/trans.png)
[英]Could not create connection to database server after multiple successful connections
[英]android bluetooth connection fails after 489 successful connections
不幸的是,我的android蓝牙有一些问题。 对于我的测试环境,我使用的是带有Android 4.4.2的Nexus 4。
我的PC上有一个Java应用程序,它使用bluecove作为客户端进行SPP连接。 该程序正在寻找一个特殊的服务名称,并与我的Android手机连接。 然后它发送72个字节到我的Android手机,并等待答案。 得到答案时,程序会睡3秒钟而不是重新开始。
在我的Android手机上,我有一个带有后台蓝牙监听器的应用程序,它在启动时启动。 此应用程序基于BluetoothChat示例演示。 当接收蓝牙数据时,我检查传入的数据并发回答案。
一切正常。 但是在489蓝牙连接之后,Android应用程序在PC-java-app正在进行时失败并显示以下错误代码:
getBluetoothService() called with no BluetoothManagerCallback
Shutting down VM
threadid=1: thread exiting with uncaught exception (group=0x41b34ba8)
FATAL EXCEPTION: main
Process: de.tum.lme.diamantum:remote_blue, PID: 21567
java.lang.NullPointerException: FileDescriptor must not be null
at android.os.ParcelFileDescriptor.<init>(ParcelFileDescriptor.java:174)
at android.os.ParcelFileDescriptor$1.createFromParcel(ParcelFileDescriptor.java:905)
at android.os.ParcelFileDescriptor$1.createFromParcel(ParcelFileDescriptor.java:897)
at android.bluetooth.IBluetooth$Stub$Proxy.createSocketChannel(IBluetooth.java:1355)
at android.bluetooth.BluetoothSocket.bindListen(BluetoothSocket.java:349)
at android.bluetooth.BluetoothAdapter.createNewRfcommSocketAndRecord(BluetoothAdapter.java:1055)
at android.bluetooth.BluetoothAdapter.listenUsingRfcommWithServiceRecord(BluetoothAdapter.java:976)
at com.test.btconn.BluetoothHandling$AcceptThread.<init>(BluetoothHandling.java:449)
at com.test.btconn.BluetoothHandling.start(BluetoothHandling.java:216)
at com.test.btconn.BluetoothListenerService.setupBtSockets(BluetoothListenerService.java:330)
at com.test.btconn.BluetoothListenerService.manageBtState(BluetoothListenerService.java:249)
at com.test.btconn.BluetoothListenerService.setBtStateDisconnected(BluetoothListenerService.java:383)
at com.test.btconn.BluetoothListenerService.access$5(BluetoothListenerService.java:378)
at com.test.btconn.BluetoothListenerService$2.handleMessage(BluetoothListenerService.java:421)
因此,应用程序的ParcelFileDescriptor存在问题,该问题突然变为空。 但为什么?
当改变PC-java-app上的暂停时间时,使用各种数据大小来传输和使用不同的智能手机时,也会发生上述所有情况。 当使用反射“listenUsingRfcommWithServiceRecord”时,505传输后也会发生相同的情况。 使用唤醒锁也没有任何改变。
顺便说一下,使用BluetoothChat样本时我也有同样的行为。
所以,有人提示,会发生什么?
更新:
如果蓝牙状态为3,则每次连接后BluetoothServerSocket都会关闭,BluetoothSocket会关闭。
问题似乎与您设备上的文件描述符限制有关。 没有为这个问题的报告在这里
在创建蓝牙套接字期间, 新的fd是从系统获取的两个新FD 。 您似乎没有正确关闭以前的BT连接,因此在您达到限制之前,已使用的FD数量会稳步增加。
为了避免这种情况,你会至少要调用close()
在你从收到BluetoothServerSocket listenUsingRfcommWithServiceRecord()
完成操作它后调用。 您还应该检查是否要保留连接到BT连接的其他资源,并在可能的情况下释放它们。
这里要求的是如何强制关闭BluetoothServerSocket的ParcelFileDescriptor。 小心:它可能会破坏事情!
您必须访问BluetoothServerSocket的mSocket字段才能访问底层的BluetoothSocket 。 此BluetoothSocket在字段mPfd中保存ParcelFileDescriptor。 在那你可以调用close()
。 由于两个字段都不可见,您将不得不使用Reflections :
public void closePFD(BluetoothServerSocket closeMe) throws AllKindOfExceptionsThatYouHaveToHandle
{
Field mSocketFld = closeMe.getClass().getDeclaredField("mSocket");
mSocketFld.setAccessible(true);
BluetoothSocket btsock = (BluetoothSocket)mSocketFld.get(closeMe);
Field mPfdFld = btsock.getClass().getDeclaredField("mPfd");
mPfdFld.setAccessible(true);
ParcelFileDescriptor pfd = (ParcelFileDescriptor)mPfdFld.get(btsock);
pfd.close();
}
这将关闭BluetoothServerSocket 。 如果你想从BTServerSockets接受方法中只关闭BluetoothSocket ,你可以省略获得mSocket的部分,如jitain sharmas answer所示 。
我对我提出的问题的解决方法是:
private synchronized void clearFileDescriptor(){
try{
Field field = BluetoothSocket.class.getDeclaredField("mPfd");
field.setAccessible(true);
ParcelFileDescriptor mPfd = (ParcelFileDescriptor)field.get(socket);
if(null == mPfd){
return;
}
mPfd.close();
}catch(Exception e){
Log.w(SensorTicker.TAG, "ParcelFileDescriptor could not be cleanly closed.");
}
}
所以上面是我编写的关闭filedescriptor的方法,以及下面我使用此代码的方法:每当socket必须关闭时:
private synchronized void cleanClose() {
if (socket != null) {
try {
clearFileDescriptor();
//clearLocalSocket();
socket.close();
}
catch (IOException e) {
Log.w(SensorTicker.TAG, "Socket could not be cleanly closed.");
}
}
}
我也试过我编写的clearLocalSocket()方法,但没有用于我的问题。 所以我试图关闭FileDescriptor。 希望它能帮助你和其他人面对同样的问题。
这是Android 4.2 - 4.4.4(和4.4w&L预览版)中的BluetoothSocket.close()错误......在内部,它调用mPfd.detachFd(),然后实际上不释放底层文件描述符。 修复是调用mPfd.close()并设置mPfd = null,这正是Android 5.0现在所做的。
您可以使用此处发布的调用mPfd.close()然后调用平台的BluetoothSocket.close()的其他解决方案来解决此问题,但我发现这对我来说还不够,可能会发生一些奇怪的事情。 我更进一步,先清理mSocket并设置为null,然后调用mPfd.close()并设置为null,最后调用设置mSocketState所需的BluetoothSocket.close()。
public static void cleanClose(BluetoothSocket btSocket)
{
if(btSocket == null)
return;
if(Build.VERSION.SDK_INT >= 17 && Build.VERSION.SDK_INT <= 20)
{
try { cleanCloseFix(btSocket); }
catch (Exception e)
{
Log.d(sLogName, "Exception during BluetoothSocket close bug fix: " + e.toString());
}
//Go on to call BluetoothSocket.close() too, because our code didn't do quite everything
}
//Call BluetoothSocket.close()
try { btSocket.close(); }
catch (Exception e)
{
Log.d(sLogName, "Exception during BluetoothSocket close: " + e.toString());
}
}
private static void cleanCloseFix(BluetoothSocket btSocket) throws IOException
{
synchronized(btSocket)
{
Field socketField = null;
LocalSocket mSocket = null;
try
{
socketField = btSocket.getClass().getDeclaredField("mSocket");
socketField.setAccessible(true);
mSocket = (LocalSocket)socketField.get(btSocket);
}
catch(Exception e)
{
Log.d(sLogName, "Exception getting mSocket in cleanCloseFix(): " + e.toString());
}
if(mSocket != null)
{
mSocket.shutdownInput();
mSocket.shutdownOutput();
mSocket.close();
mSocket = null;
try { socketField.set(btSocket, mSocket); }
catch(Exception e)
{
Log.d(sLogName, "Exception setting mSocket = null in cleanCloseFix(): " + e.toString());
}
}
Field pfdField = null;
ParcelFileDescriptor mPfd = null;
try
{
pfdField = btSocket.getClass().getDeclaredField("mPfd");
pfdField.setAccessible(true);
mPfd = (ParcelFileDescriptor)pfdField.get(btSocket);
}
catch(Exception e)
{
Log.d(sLogName, "Exception getting mPfd in cleanCloseFix(): " + e.toString());
}
if(mPfd != null)
{
mPfd.close();
mPfd = null;
try { pfdField.set(btSocket, mPfd); }
catch(Exception e)
{
Log.d(sLogName, "Exception setting mPfd = null in cleanCloseFix(): " + e.toString());
}
}
} //synchronized
}
如果您在应用程序中使用蓝牙作为服务器,我遇到了与此相同的问题,除了我的问题是当我进行反射时,我在文件描述符mPfd上变为null。 我能够使用这种方法关闭文件,希望这可以帮助。
我使用ParceFileDescriptor从BluetoothSocket中的LoaclSocket通过id / index获取文件。 int mfd = 0; 字段socketField = null; LocalSocket mSocket = null;
try
{
socketField = btSocket.getClass().getDeclaredField("mSocket");
socketField.setAccessible(true);
mSocket = (LocalSocket)socketField.get(btSocket);
}
catch(Exception e)
{
Log ( "Exception getting mSocket in cleanCloseFix(): " + e.toString());
}
if(mSocket != null)
{
FileDescriptor fileDescriptor =
mSocket.getFileDescriptor();
String in = fileDescriptor.toString();
//regular expression to get filedescriptor index id
Pattern p = Pattern.compile("\\[(.*?)\\]");
Matcher m = p.matcher(in);
while(m.find()) {
Log ( "File Descriptor " + m.group(1));
mfd = Integer.parseInt(m.group(1));
break;
}
//Shutdown the socket properly
mSocket.shutdownInput();
mSocket.shutdownOutput();
mSocket.close();
mSocket = null;
try { socketField.set(btSocket, mSocket); }
catch(Exception e)
{
Log ("Exception setting mSocket = null in cleanCloseFix(): " + e.toString());
}
//Close the file descriptor when we have it from the Local Socket
try {
ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.adoptFd(mfd);
if (parcelFileDescriptor != null) {
parcelFileDescriptor.close();
Log ( "File descriptor close succeed : FD = " + mfd);
}
} catch (Exception ex) {
Log ( "File descriptor close exception " + ex.getMessage());
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.