Android 6.0 запрашивает сопряжение с удаленными устройствами при получении UUIDS
Я пытаюсь получить UUIDS с удаленного устройства Bluetooth, как это:
device.fetchUuidsWithSdp();
Это будет работать бесшумно и без взаимодействия с пользователем на всех устройствах, кроме тех, которые имеют Android 6.0, которые с помощью диалогового окна сопряжения явно запрашивают соединение с удаленным устройством для получения UUID. Это ожидаемое поведение? Где это задокументировано? Есть ли способ инициировать обнаружение UUID без явного разрешения этого с другого конца?
2 ответа
Я нашел обходной путь, используя скрытый метод sdpSearch вместо fetchUuidsWithSdp. Это требует немного размышлений. Это работало для меня на Android 6.0 и 5.1.1, без устройств, пытающихся спариться. Надеюсь, что это поможет, и не стесняйтесь улучшать довольно плохую обработку исключений.
public class DeviceFinder{
public interface Callback{
void onDeviceFound(BluetoothDevice bd);
void onFinishedCallback();
void onStartCallback();
}
private ArrayList<BluetoothDevice> tempDevices = new ArrayList<>();
private Callback mCallback;
private Context mContext;
private String ACTION_SDP_RECORD;
private String EXTRA_SDP_SEARCH_RESULT;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)){
// Aggregating found devices
BluetoothDevice bd = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
tempDevices.add(bd);
}else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
// Prepare for new search
tempDevices = new ArrayList<>();
mCallback.onStartCallback();
}else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
// Do a sdpSearch for all found devices
for (BluetoothDevice bd : tempDevices){
try {
Method m = bd.getClass().getDeclaredMethod("sdpSearch", ParcelUuid.class);
m.invoke(bd, new ParcelUuid(/* your uuid here */));
} catch (Exception e) {
e.printStackTrace();
}
}
mCallback.onFinishedCallback();
}else if( ACTION_SDP_RECORD.equals(action)){
// check if the device has the specified uuid
BluetoothDevice bd = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (intent.getIntExtra(EXTRA_SDP_SEARCH_RESULT, 1) == 0){
mCallback.onDeviceFound(bd);
}
}
}
};
public DeviceFinder(Context context, Callback mCallback){
this.mCallback = mCallback;
this.mContext = context;
try {
Field f = BluetoothDevice.class.getDeclaredField("ACTION_SDP_RECORD");
ACTION_SDP_RECORD = ((String)f.get(null));
f = BluetoothDevice.class.getDeclaredField("EXTRA_SDP_SEARCH_STATUS");
EXTRA_SDP_SEARCH_RESULT = ((String)f.get(null));
} catch (Exception e) {
e.printStackTrace();
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
intentFilter.addAction(ACTION_SDP_RECORD);
context.registerReceiver(mReceiver, intentFilter);
startScan();
}
public void startScan(){
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.startDiscovery();
}
}
public void unregisterReciever(){
mContext.unregisterReceiver(mReceiver);
}
}
edit: sdpSearch был добавлен в Android 6.0, поэтому он не работает для более ранних версий
Обновить
Официальный ответ Google на ваш вопрос:
Привет! Мы понимаем, что у вас есть запрос на конкретное использование, который можно посмотреть здесь в stackru.
/questions/12742717/android-bluetooth-poluchit-identifikatoryi-uuid-obnaruzhennyih-ustrojstv
Спасибо
В Android 6.0 есть изменения в разрешениях. Введение разрешений во время выполнения, а не глобальное принятие всех приложений требует разрешения при установке приложения.
Короче говоря, типы разрешений свободно делятся на два типа, нормальные или опасные. Любое разрешение, которое посягает на конфиденциальность пользователя, считается опасным.
Разрешения также помещаются в группы схожих разрешений, например, точное расположение и грубое расположение.
Пользователям предоставляется выбор при использовании приложения, чтобы принять разрешение определенной группы, которая считается опасной. После того, как разрешение для конкретной группы дается для запуска этого приложения, оно не запрашивается снова для разрешений из той же группы, но запрашивается разрешение от других групп по мере необходимости.
Подробности см. Ниже:
Разрешения во время выполнения.
В этом выпуске представлена новая модель разрешений, в которой пользователи теперь могут напрямую управлять разрешениями приложений во время выполнения. Эта модель предоставляет пользователям улучшенную видимость и контроль над разрешениями, оптимизируя процессы установки и автоматического обновления для разработчиков приложений. Пользователи могут предоставлять или отзывать разрешения отдельно для установленных приложений.
В своих приложениях, ориентированных на Android 6.0 (уровень API 23) или выше, обязательно проверяйте и запрашивайте разрешения во время выполнения. Чтобы определить, было ли предоставлено разрешение вашему приложению, вызовите новый метод checkSelfPermission(). Чтобы запросить разрешение, вызовите новый метод requestPermissions(). Даже если ваше приложение не ориентировано на Android 6.0 (уровень API 23), вы должны протестировать свое приложение в соответствии с новой моделью разрешений.
... /
Начиная с Android 6.0 (уровень API 23), пользователи предоставляют и отменяют разрешения приложения во время выполнения, вместо того, чтобы делать это при установке приложения. В результате вам придется тестировать ваше приложение в более широком диапазоне условий. До Android 6.0 вы могли разумно предположить, что если ваше приложение вообще работает, оно имеет все разрешения, которые оно объявляет в манифесте приложения. В соответствии с новой моделью разрешений вы больше не можете делать это предположение.
Разрешения классифицируются как нормальные или опасные
Доступ по Bluetooth считается нормальным разрешением, а сопряжение или чтение подробностей приложения - опасным.
Опасные разрешения охватывают области, где приложению требуются данные или ресурсы, которые включают в себя личную информацию пользователя или могут потенциально повлиять на сохраненные данные пользователя или работу других приложений. Например, возможность читать контакты пользователя является опасным разрешением. Если приложение заявляет, что оно нуждается в опасном разрешении, пользователь должен явно предоставить разрешение приложению.
Поэтому при запросе информации с устройства:
Если приложение запрашивает опасное разрешение, указанное в его манифесте, и приложение в настоящее время не имеет каких-либо разрешений в группе разрешений, система отображает диалоговое окно для пользователя, описывающее группу разрешений, к которой оно хочет получить доступ. Диалоговое окно не описывает конкретное разрешение в этой группе. Например, если приложение запрашивает разрешение READ_CONTACTS, системное диалоговое окно просто говорит, что приложению необходим доступ к контактам устройства. Если пользователь дает разрешение, система дает приложению только то разрешение, которое оно запрашивает.
Посмотрите Работу с Системными Разрешениями для деталей реализации.
редактировать В ответ на ваш комментарий
Есть много проблем с ошибками Bluetooth и выпуском Android 6.0. как и в случае с 5.0, ожидается, что они будут исправлены в следующем патче. Тем не менее, я не вижу вашу проблему как ошибку.
И после просмотра вашего поста здесь на Google, мой ответ прямо отвечает на то, что вы воспринимаете как ошибку.
Ваш снимок экрана:
И из вашего кода здесь на GitHub:
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "me.bluetoothuuidsample"
minSdkVersion 18
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
Устройства с зефиром ведут себя точно так же, как и для разрешений во время выполнения, но я уверен, что Google подтвердит это для вас.
Чтобы на этом этапе не приходилось иметь дело с переключением, используйте целевой sdk менее 23.
targetSdkVersion 22
Этот Cheesefactory блог подробно в деталях. Все, что каждый Android-разработчик должен знать о новом Android Runtime Permission
редактировать 2
Выбор UUID требует разрешения местоположения, здесь есть пост, в котором более подробно: /questions/46892416/bluetooth-low-energy-startscan-na-android-60-ne-nahodit-ustrojstva/46892454#46892454