【问题标题】:Connecting to Bluetooth device fails in deep sleep在深度睡眠中连接到蓝牙设备失败
【发布时间】:2014-02-05 14:55:40
【问题描述】:

我尝试每 25 秒连接一次配对的蓝牙设备,通过触发 WakefulBroadcastReceiver 的 AlarmManager 安排来启动服务以进行连接。设备进入睡眠状态后,前几个小时一切正常,但在大约 4-5 小时后开始出现故障,此时我假设设备进入 深度睡眠

我从 ParcelFileDescriptor 收到 NullPointerException,指出“FileDescriptor 不能为空”。我已经尝试过搜索这个错误,甚至已经浏览了 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

任何建议将不胜感激!

【问题讨论】:

  • 如果有人得到相同的解决方案,请在此处发布。
  • 你找到解决办法了吗?目前我只是,在收到此文件描述符错误时关闭 BT,2 秒后,BT 已再次启用。
  • 很遗憾,我还没有找到解决方案。

标签: java android bluetooth sleep android-bluetooth


【解决方案1】:

这看起来像 Android 4.2 - 4.4.4 中的 BluetoothSocket.close() 错误,似乎已在 5.0 中修复。基本上,它不会释放底层文件描述符,所以它会泄漏,直到你达到设备的限制,然后会发生奇怪的坏事。您需要从 BluetoothSocket 中获取 ParcelFileDescriptor 并自行关闭。

在此处查看我的答案以获取解决方法代码:https://stackoverflow.com/a/27873675/1893015

【讨论】:

  • 您知道蓝牙服务器套接字中是否也存在此错误吗?
  • 是的,BluetoothServerSocket 的 mSocket 成员只是一个 BluetoothSocket,并且使用了它的错误 close() 方法。
【解决方案2】:

我在通过蓝牙库类后找到了解决方法,发现它在调用 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 方法处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多