Bluetooth UUID API в Android Studio действует случайным образом

#android #android-studio #bluetooth #uuid #android-bluetooth

#Android #android-studio #bluetooth #uuid #android-bluetooth

Вопрос:

Для начала я использую Android Studio 4.0.1 в Windows 8.1.

Итак, еще одна проблема возникла при проведении дополнительных тестов в проекте приложения, над которым я работал некоторое время. Я наткнулся на эту проблему при создании приложения, которое собирает данные с окружающих устройств Bluetooth, чтобы позже подключиться к правильному (пользовательской встроенной системе, использующей Bluetooth Classic, а не Low Energy).

Как упоминалось в предыдущем посте, я попробовал одно и то же приложение на двух разных телефонах (с разными версиями Android), на одном Android 5.1.1, а на другом Android 9; принимая во внимание их соответствующие разрешения и ограничения.

На этот раз я специально пытался собрать UUID с окружающих меня устройств. Чтобы было понятно, получение имен устройств и их соответствующих MAC-адресов не составило труда, и все отлично отображается на разных телефонах. Но UUID — это эти маленькие звери, которые меня сильно раздражают, и кажется, что API Android Studio для извлечения UUID-идентификаторов имеет недостатки и действует случайным образом, и вот почему:

Чтобы упростить ситуацию, я создал еще одно очень простое приложение, которое собирает UUID с известного устройства, что означает, что я жестко закодировал MAC-адрес, с которого я хочу получать UUID.

Я создал кнопку для запуска выборки, вызвав этот фрагмент кода:

             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) amp;amp; 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;

        }



    }


};
  

Now, the supposed order in which things are supposed to happen is:

  1. A fetching command is sent
  2. An ACL connection is made to retrieve the UUIDs from the device
  3. UUIDs are retrieved
  4. ACL connection is terminated.

And lets get this clear:

  1. Широковещательный приемник UUID получает UUID, сохраненные в кэше, если устройство было ранее обнаружено во время того же сеанса. После выключения адаптера Bluetooth все устройства, обнаруженные во время этого сеанса, которые были сохранены в кэше, теперь удаляются, поэтому при включении адаптера Bluetooth и попытке получить UUID с другого устройства, которое сейчас выключено, значение, полученное внутри широковещательного приемника, теперь равно нулю.

На самом деле:

  1. При выборке UUID с уже найденного устройства порядок, в котором все должно происходить, происходит случайным образом или не происходит вообще.
  2. Не всегда существует предварительное соединение ACL для извлечения UUID с устройства.
  3. Подключение и отключение ACL выполняется даже после получения кэшированных идентификаторов UUID.

Вот зарегистрированные результаты после многократной выборки 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 с других устройств (клавиатур Bluetooth, других телефонов, гарнитур и т.д.), Я также могу подтвердить, что это не просто задержка в журналах, потому что в более полном приложении, над которым я работаю, флаги, связанные с подключениями и отключениями ACL, вообще не срабатывают или не срабатывают в том порядке, в котором они должны произойти.

Итак … после этого длинного поста… что здесь происходит?

Комментарии:

1. Итак … никто не разрабатывает приложения для Android с функциональностью Bluetooth? Честно говоря, это немного расстраивает…