#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:
- A fetching command is sent
- An ACL connection is made to retrieve the UUIDs from the device
- UUIDs are retrieved
- ACL connection is terminated.
And lets get this clear:
- Широковещательный приемник UUID получает UUID, сохраненные в кэше, если устройство было ранее обнаружено во время того же сеанса. После выключения адаптера Bluetooth все устройства, обнаруженные во время этого сеанса, которые были сохранены в кэше, теперь удаляются, поэтому при включении адаптера Bluetooth и попытке получить UUID с другого устройства, которое сейчас выключено, значение, полученное внутри широковещательного приемника, теперь равно нулю.
На самом деле:
- При выборке UUID с уже найденного устройства порядок, в котором все должно происходить, происходит случайным образом или не происходит вообще.
- Не всегда существует предварительное соединение ACL для извлечения UUID с устройства.
- Подключение и отключение 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? Честно говоря, это немного расстраивает…