我试图每隔25秒连接一个配对的蓝牙设备,通过AlarmManager调度,触发WakefulBroadcastReceiver启动服务进行连接。一旦设备进入睡眠状态,一切都会在最初的几个小时内发挥作用,但是大约4-5个小时后,当我假设设备进入<深度睡眠时,它开始失效。
我从ParcelFileDescriptor得到一个NullPointerException,声明“FileDescriptor不能为null”。我已经尝试过搜索这个错误,甚至已经完成了ParcelFileDescriptor.java中的代码,但我已经走到了尽头。我在带有Android 4.4.2的Nexus 10上运行它。尝试连接的代码如下:
public GatewaySocket getSocket() throws IOException
{
if (!BluetoothAdapter.checkBluetoothAddress(macAddress))
return new GatewaySocket("Address " + macAddress + " is not a valid Bluetooth MAC Address");
BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
if (bluetooth == null)
return new GatewaySocket("Sorry, no Bluetooth adapter available");
BluetoothDevice device = bluetooth.getRemoteDevice(macAddress);
BluetoothSocket btSocket = null;
try
{
btSocket = device.createRfcommSocketToServiceRecord(uuid);
}
catch (Exception e)
{
log(3, "" + this, "Error closing socket on connection: " + e);
}
if (btSocket == null)
return new GatewaySocket("Unable to launch insecure connection to " + device);
try
{
btSocket.connect();
}
catch (IOException ex)
{
try
{
btSocket.close();
}
catch (IOException ex2)
{
// do nothing
}
throw (ex);
}
GatewaySocket socket = new GatewaySocket(btSocket, btSocket.getInputStream(), btSocket.getOutputStream());
return socket;
}
GatewaySocket是BluetoothSocket的瘦子类。错误发生在btSocket.connect()行,包含以下堆栈跟踪:
01-10 09:13:57.796: W/BluetoothAdapter(3591): getBluetoothService() called with no BluetoothManagerCallback
01-10 09:13:57.801: D/BTIF_SOCK(979): service_uuid: 00001101-0000-1000-8000-00805f9b34fb
01-10 09:13:57.801: E/bt-btif(979): SOCK_THREAD_FD_RD signaled when rfc is not connected, slot id:4374, channel:-1
01-10 09:13:57.801: W/System.err(3591): java.lang.NullPointerException: FileDescriptor must not be null
01-10 09:13:57.806: W/System.err(3591): at android.os.ParcelFileDescriptor.<init>(ParcelFileDescriptor.java:174)
01-10 09:13:57.806: W/System.err(3591): at android.os.ParcelFileDescriptor$1.createFromParcel(ParcelFileDescriptor.java:905)
01-10 09:13:57.806: W/System.err(3591): at android.os.ParcelFileDescriptor$1.createFromParcel(ParcelFileDescriptor.java:897)
01-10 09:13:57.806: W/System.err(3591): at android.bluetooth.IBluetooth$Stub$Proxy.connectSocket(IBluetooth.java:1322)
01-10 09:13:57.806: W/System.err(3591): at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:308)
01-10 09:13:57.806: W/System.err(3591): at com.gateway.service.AndroidGMConversation.getSocket(AndroidGMConversation.java:162)
01-10 09:13:57.806: W/System.err(3591): at com.gateway.GatewayManagerConversation.converse(GatewayManagerConversation.java:81)
01-10 09:13:57.806: W/System.err(3591): at com.gateway.GatewayManagerConversation.run(GatewayManagerConversation.java:72)
01-10 09:13:57.806: W/System.err(3591): at java.lang.Thread.run(Thread.java:841)
01-10 09:13:57.806: V/PS(3591): Finished with device 06:92:25:0A:A5:50
任何建议都将不胜感激!
答案 0 :(得分:3)
我在浏览蓝牙库类后找到了解决方法,并发现它在调用bluetoothsocket.close();
时没有关闭FileDescriptor,尽管它调用FileDescriptor上的dispatch()
方法,而不是关闭它。
只需在bluetoothsocket.close();
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, "LocalSocket could not be cleanly closed.");
}
}
希望这也能解决其他问题。但它应该由BluetoothSocket类通过close方法处理。
答案 1 :(得分:1)
这看起来像Android 4.2 - 4.4.4中的BluetoothSocket.close()错误,似乎在5.0中得到修复。基本上,它没有释放底层文件描述符,所以它泄漏直到你达到设备的限制,然后发生奇怪的坏事。您需要从BluetoothSocket获取ParcelFileDescriptor并自行关闭它。
请在此处查看我的答案,了解解决方法代码:https://stackoverflow.com/a/27873675/1893015