Регистрация широковещательного приемника динамически не работает-BluetoothDevice.ДЕЙСТВИЙ
используя Log
класс для отслеживания времени выполнения показать, что onReceive()
methode не называется, Почему ?
Регистрация вещательного приемника динамически
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
}
6 ответов
то, что вы пропустили, это то, что вам нужно запустить восстановление устройства
во-первых, получить адаптер bluetooth
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
после этого вы начинаете открытие, вызывая
mBtAdapter.startDiscovery();
вы также должны прочитать подробности здесь, например, о cancelDiscovery()
http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery%28%29
П. С. кроме того, предлагается использовать context.getSystemService(Context.BLUETOOTH_SERVICE)
получить BluetoothAdapter на API 18+, согласно официальному документу.
чтобы получить BluetoothAdapter, представляющий локальный адаптер Bluetooth, при запуске на JELLY_BEAN_MR1 и ниже вызовите статический метод getDefaultAdapter (); при запуске на JELLY_BEAN_MR2 и выше, получить его через getSystemService (класс) с BLUETOOTH_SERVICE.
Edit:
Напоминаем, что вам нужно BLUETOOTH_ADMIN разрешение startDiscovery()
кроме того, что начиная с 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 на зефире следующим образом:
-
есть
ACCESS_COARSE_LOCATION
требование разрешения в манифесте вместе с обычными bluetooth permissions:<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
для почти такого же поведения. (Гуру, поправьте меня, если я ошибаюсь)
У меня была аналогичная проблема с радиовещательного приемника. Потом я нашел это.: https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id
в основном, на 6.0 вы должны использовать разрешение место для поиска устройств Bluetooth.
Я не знаю, правильно ли ваш код в получении устройства bluetooth. вот что я думаю о вашем коде. intialising и регистрация BroadcastReceiver внутри функции-плохая идея. вы должны сделать это снаружи onCreate()
метод.
вот что вам нужно сделать в коде
как о регистрации Reciver, который должен быть сделан в onCreate()
такой
registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
после инициализации или reciever
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);
}
}
};
отменить регистрацию reciver в onPause()
do не забывайте, что
и в discoverDevices()
просто вернуть list
устройств, добавленных reciver для каждого вызова этого fumction;
публикация этого в качестве ответа, поскольку я не могу прокомментировать свой текущий уровень репутации.
у вас есть разрешение Bluetooth включить в Вас AndroidManifest.в XML?
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
если нет, попробуйте (и исследуйте) каждый отдельно, поскольку я не помню важности каждого из них.
Если у вас есть эти, Пожалуйста, включите больше кода, чтобы можно было диагностировать вашу проблему.
Как ответили эксперты, Вы можете проверить следующие моменты, чтобы получить ACTION_FOUND работу в Android 6 и выше, 1. В дополнение к настройке разрешений BLUETOOTH и BLUETOOTH_ADMIN, попробуйте
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
иногда эти два могут не понадобиться, но это сработало для меня. Также вы должны искать разрешения пользователя динамически, используя коды
int MY_PERMISSIONS_REQUEST = 200;
int permissions=ContextCompat.checkSelfPermission (this,Manifest.permission.ACCESS_FINE_LOCATION);
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST);
сейчас пишу коды для выполнения требуемой операции. Я добавил один метод startDiscovery() сразу после этот. Конечно, это сработает для вас... Удачи в кодировании...