Android Studio上的Bluetooth UUID API随机起作用

问题描述

首先,我在Windows 8.1上使用Android Studio 4.0.1。

因此,对我已经工作了一段时间的应用程序项目进行更多测试时,出现了另一个问题。 在制作一个应用程序时,我偶然发现了这个问题,该应用程序从周围的蓝牙设备收集数据,然后再连接到正确的应用程序(使用Bluetooth Classic而不是Low Energy的自定义嵌入式系统)。

如前一篇文章所述,我在两部不同的手机(具有不同的android版本)上尝试了相同的应用,其中一部使用Android 5.1.1,另一部使用Android 9;考虑到它们各自的权限和限制。

这次,我专门尝试从周围的设备中收集UUID。需要明确的是,获取设备名称及其各自的MAC地址并不费吹灰之力,并且一切都完美地显示在不同的手机上。但是UUID是这些让我非常烦恼的小野兽,似乎Android Studio的用于提取UUID的API有缺陷,并且行为随机,这就是原因:

为简化起见,我制作了另一个非常简单的应用程序,该应用程序从已知设备中收集UUID,这意味着我对要从中获取UUID的MAC地址进行了硬编码。

我创建了一个Button,通过调用以下代码来开始获取:

            isFetchUUIDSButtonPressed = true;
            bluetoothDiscoveredUUID.clear();
            String UUID = "00:00:00:00:00:00"; // MAC ADDRESS IS OBVIOUSLY SOMETHING DIFFERENT,BUT I AM NOT SHOWING IT HERE.
            BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
            BluetoothDevice mBluetoothDevice = bluetoothManager.getAdapter().getRemoteDevice(UUID);

            Log.w(TAG,"BEFORE Check if fetch succeeded: " + checkIfUUIDFetchSucceeded);
            checkIfUUIDFetchSucceeded = mBluetoothDevice.fetchUuidsWithSdp();
            Log.w(TAG,"AFTER Check if fetch succeeded: " + checkIfUUIDFetchSucceeded);
            checkIfUUIDFetchSucceeded = false;

现在,有一个广播接收器向我显示建立ACL连接的时间,因为完成了低级连接以便从所需设备中获取UUID:

////////////////////////////// BLUETOOTH IN GENERAL BROADCAST RECEIVER //////////////////////////////
 BroadcastReceiver bluetoothBroadcastReceiver = new BroadcastReceiver(){

    @Override
    public void onReceive(Context context,Intent intent){

        String action = intent.getAction();

        if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)){

            //STATE_OFF = 10;
            //STATE_TURNING_ON = 11;
            //STATE_ON = 12;
            //STATE_TURNING_OFF = 13;

            int previousBluetoothState = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE,BluetoothAdapter.ERROR);
            int currentBluetoothState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.ERROR);

            Log.w(TAG,"Previous Bluetooth Adapter State: " + previousBluetoothState);
            Log.w(TAG,"Current Bluetooth Adapter State: " + currentBluetoothState);


            if( previousBluetoothState == BluetoothAdapter.STATE_ON ){

                //TODO: CANCEL CURRENT OPERATIONS,RESET ALL VARIABLES,LISTVIEWS,BUTTONS,etc,TO THEIR INITIAL STATES.
                // this is to guarantee a fresh restart of operations after the Bluetooth adapter is turned ON again.

                Log.w(TAG,"Bluetooth Turning Off: RESETTING ALL FIELDS AND VIEWS TO THEIR INITIAL STATES");
                resetFields();

            }

        }


        ////////////////////////////// CONNECTION ESTABLISHED //////////////////////////////
        else if(BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)){

                Log.w(TAG,"Provisional Connection to Retrieve UUID");

        }


        ////////////////////////////// DISCONNECTION VERIFIED //////////////////////////////
        else if(BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)){

            Log.w(TAG,"ACTION_ACL_DISCONNECTED: Provisional connection finished!");
            Log.w(TAG,"ACTION_ACL_DISCONNECTED: Disconnected from device");

        }

    }

};

建立低级连接后,将获取UUID并将其捕获到另一个广播接收器上:

////////////////////////////// UUIDs BROADCAST RECEIVER //////////////////////////////
private final BroadcastReceiver UUIDBroadcastReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context,Intent intent) {

        String action = intent.getAction();

        if( BluetoothDevice.ACTION_UUID.equals(action) && isFetchUUIDSButtonPressed){

            Parcelable[] uuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
            Log.e(TAG,"FROM ACTION_UUID");

            bluetoothDiscoveredUUID.add(new ArrayList<UUID>());

            if (uuids != null) {

                for (Parcelable ep : uuids) {
                    Log.e(TAG,"UUID = " + ep.toString());
                    bluetoothDiscoveredUUID.get((bluetoothDiscoveredUUID.size()) - 1).add(UUID.fromString(ep.toString()));
                }

            }


            else{
                bluetoothDiscoveredUUID.get((bluetoothDiscoveredUUID.size()) - 1).add(nullUUID);
                Log.e(TAG,"Null UUID");
            }

                Log.w(TAG,"UUID data acquired");
                isFetchUUIDSButtonPressed = false;

        }



    }


};

现在,事情发生的假定顺序是:

  1. 已发送获取命令
  2. 建立ACL连接以从设备中检索UUID
  3. 检索到UUID
  4. ACL连接已终止。

让我们弄清楚这一点:

  1. UUID广播接收器获取存储在缓存中的UUID(如果设备是 之前在同一会话中发现的。蓝牙之后 适配器已关闭,在该会话期间发现了所有设备 现在已删除存储在缓存中的数据,因此,当打开蓝牙适配器并尝试 从现在关闭的另一台设备获取UUID,该值在广播内部获取 接收器现在为空。

实际上:

  1. 从已经搜索过的设备中获取UUID时,事物应该发生,随机发生或根本不发生的顺序。
  2. 并非总是有临时的ACL连接来从设备中检索UUID。
  3. 即使在获取缓存的UUID之后,也会执行ACL连接和断开连接。

这是一遍又一遍地在同一设备上获取UUID之后的记录结果:

D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
W/MainActivity: BEFORE Check if fetch succeeded: false
W/MainActivity: AFTER Check if fetch succeeded: true
E/MainActivity: FROM ACTION_UUID
    Null UUID -------------------------------------->>>> //Other device is off and no UUIDs stored in cache
W/MainActivity: UUID data acquired


D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
W/MainActivity: BEFORE Check if fetch succeeded: false
W/MainActivity: AFTER Check if fetch succeeded: true
W/MainActivity: Provisional Connection to Retrieve UUID!
E/MainActivity: FROM ACTION_UUID
    UUID = 00001101-0000-1000-8000-00805f9b34fb
    UUID = 00000000-0000-1000-8000-00805f9b34fb
W/MainActivity: UUID data acquired
W/MainActivity: ACTION_ACL_DISCONNECTED: Provisional connection finished!
ACTION_ACL_DISCONNECTED: Disconnected from device


D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
W/MainActivity: BEFORE Check if fetch succeeded: false
W/MainActivity: AFTER Check if fetch succeeded: true
E/MainActivity: FROM ACTION_UUID
    UUID = 00001101-0000-1000-8000-00805f9b34fb
    UUID = 00000000-0000-1000-8000-00805f9b34fb
W/MainActivity: UUID data acquired


D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
W/MainActivity: BEFORE Check if fetch succeeded: false
W/MainActivity: AFTER Check if fetch succeeded: true
E/MainActivity: FROM ACTION_UUID
    UUID = 00001101-0000-1000-8000-00805f9b34fb
    UUID = 00000000-0000-1000-8000-00805f9b34fb
W/MainActivity: UUID data acquired
W/MainActivity: Provisional Connection to Retrieve UUID!
W/MainActivity: ACTION_ACL_DISCONNECTED: Provisional connection finished!
ACTION_ACL_DISCONNECTED: Disconnected from device

我可以确认这不是特定于设备的问题,因为它发生在不同的手机上,并且从其他设备(蓝牙键盘,其他手机,耳机等)获取UUID时,我也可以确认这不仅是滞后记录日志,因为在我正在使用的更完整的应用程序上,与ACL连接和断开连接有关的标志根本不会被触发,或者也不会按照它们应该发生的顺序被触发。

那么...在这篇漫长的帖子之后...这里发生了什么事?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...