Регистрировать широковещательный приемник динамически не работает - BluetoothDevice.ACTION_FOUND
Использование класса Log
для отслеживания времени выполнения показывает, что onReceive()
метод не вызван, почему?
Регистрировать широковещательный приемник динамически
private void discoverDevices () {
Log.e("MOHAB","BEFORE ON RECEIVE");
mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
Log.e("MOHAB","ON RECEIVE");
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
Bluetooth b = new Bluetooth(device.getName(),device.getAddress());
list.add(b);
}
}
};
Log.e("MOHAB","create intentFilter");
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
}
Ответы
Ответ 1
Что вы пропустили, так это то, что вам нужно запустить восстановление устройства.
Сначала получите адаптер Bluetooth
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
После этого вы начинаете открытие, вызывая
mBtAdapter.startDiscovery();
Вы также должны прочитать подробности здесь, например. около cancelDiscovery()
http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery%28%29
P.S. Также предлагается использовать context.getSystemService(Context.BLUETOOTH_SERVICE)
для получения BluetoothAdapter на API 18+, согласно официальному документу.
Чтобы получить BluetoothAdapter, представляющий локальный адаптер Bluetooth, при запуске на JELLY_BEAN_MR1 и ниже, вызовите статический метод getDefaultAdapter(); при запуске на JELLY_BEAN_MR2 и выше, получить его через getSystemService (класс) с помощью BLUETOOTH_SERVICE.
Edit:
Напоминаем, что вам нужно BLUETOOTH_ADMIN разрешение startDiscovery()
Ответ 2
Помимо того, что начиная с Android 6.0, вы должны иметь разрешение ACCESS_COARSE_LOCATION
на получение ACTION_FOUND
(как уже упоминалось @siniux), есть еще один связанная вещь:
ACCESS_COARSE_LOCATION
относится к опасным разрешениям, которые вы должны явно запрашивать у пользователя во время выполнения (другое улучшение безопасности, которое появилось в версии 6.0).
Чтобы диагностировать, вы можете запустить adb logcat | grep BroadcastQueue
и увидеть что-то вроде этого:
W/BroadcastQueue: Permission Denial: receiving Intent {
act=android.bluetooth.device.action.FOUND flg=0x10 (has extras) }
to ProcessRecord{9007:com.examplepackage} (pid=9007, uid=10492)
requires android.permission.ACCESS_COARSE_LOCATION due to sender
com.android.bluetooth (uid 1002)
Итак, правильная процедура обнаружения устройства BT в Marshmallow выглядит следующим образом:
-
У вас есть требование для разрешения ACCESS_COARSE_LOCATION
в манифесте вместе с обычными разрешениями Bluetooth:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
-
Убедитесь, что у вас есть разрешение во время выполнения для ACCESS_COARSE_LOCATION
protected void checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_COARSE_LOCATION);
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_COARSE_LOCATION: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
proceedDiscovery(); // --->
} else {
//TODO re-request
}
break;
}
}
}
-
Зарегистрируйте широковещательный приемник для ACTION_FOUND
и вызовите BluetoothAdapter.startDiscovery()
protected void proceedDiscovery() {
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_NAME_CHANGED);
registerReceiver(mReceiver, filter);
mBluetoothAdapter.startDiscovery();
}
Смешная вещь о ACTION_NAME_CHANGED
. Хотя 6.0 не доставляет вам ACTION_FOUND
без разрешения на грубое местоположение, вы все равно получите события ACTION_NAME_CHANGED
, которые, как правило, объединяются с ACTION_FOUND
при обнаружении устройств. То есть вы получаете оба события, поэтому без разрешения вы все равно можете обрабатывать ACTION_NAME_CHANGED
для почти такого же поведения. (Гуру, поправьте меня, если я ошибаюсь)
Ответ 3
У меня была аналогичная проблема с широковещательным приемником.
Тогда я нашел это:
https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id
В принципе, в версии 6.0 вы должны использовать разрешение на размещение для сканирования устройств Bluetooth.
Ответ 4
Я не знаю, правильный ли код для получения Bluetooth-устройства. вот что я чувствую о вашем коде. intialising и регистрация BroadcastReceiver внутри функции - плохая идея. вы должны сделать это вне метода onCreate()
.
вот что вам нужно сделать в своем коде
как о регистрации Reciver, который должен быть сделан в onCreate()
, как этот
registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
после инициализации или приемника
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.e("MOHAB","ON RECEIVE");
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
Bluetooth b = new Bluetooth(device.getName(),device.getAddress());
list.add(b);
}
}
};
отменить регистратор в onPause()
не забывайте, что
и в вашем discoverDevices()
просто верните list
устройств, добавленных ресивером, для каждого вызова этого взрыва;
Ответ 5
Проводя это как ответ, так как я не могу прокомментировать мой текущий уровень Rep.
Есть ли у вас разрешение Bluetooth в AndroidManifest.xml?
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
Если нет, попробуйте (и исследуйте) каждый отдельно, так как я не помню важность каждого из них.
Если у вас есть это, укажите больше кода, чтобы можно было диагностировать вашу проблему.