L'utilisation de la classe Log
pour suivre l'exécution montre que la méthode onReceive()
ne s'appelle pas, pourquoi?
Enregistrer le récepteur de diffusion de manière dynamique
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
}
Qu'est-ce que vous avez manqué, c'est que vous devez démarrer une récupération de périphérique
D'abord, procurez-vous l'adaptateur Bluetooth
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Après cela, vous commencez la découverte en appelant
mBtAdapter.startDiscovery();
Vous devriez également lire les détails ici, par exemple: à propos de cancelDiscovery()
http://developer.Android.com/reference/Android/bluetooth/BluetoothAdapter.html#startDiscovery%28%29
P.S. En outre, il est suggéré d'utiliser context.getSystemService(Context.BLUETOOTH_SERVICE)
pour obtenir l'adaptateur Bluetooth sur l'API 18+, selon la documentation officielle.
Pour obtenir un BluetoothAdapter représentant l’adaptateur Bluetooth local, lors de l'exécution sur JELLY_BEAN_MR1 et inférieur, appelez le statique méthode getDefaultAdapter (); lors de l'exécution sur JELLY_BEAN_MR2 et supérieur, récupérez-le via getSystemService (Class) avec BLUETOOTH_SERVICE.
Edit: Rappelez-vous que vous devez disposer de BLUETOOTH_ADMIN permission pour _startDiscovery()
Outre le fait que à partir d'Android 6.0, vous devez disposer de l'autorisation ACCESS_COARSE_LOCATION
pour recevoir ACTION_FOUND
(comme @siniux déjà mentionné), il existe un autre élément connexe:
ACCESS_COARSE_LOCATION
fait partie des autorisations dangereuses que vous devez demander explicitement à l'utilisateur au moment de l'exécution (autre amélioration de la sécurité fournie avec la version 6.0).
Pour diagnostiquer, vous pouvez exécuter adb logcat | grep BroadcastQueue
et voir quelque chose comme ceci:
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)
Ainsi, la procédure correcte pour la découverte de périphérique BT sur Marshmallow est la suivante:
Avoir l'autorisation ACCESS_COARSE_LOCATION
dans le manifeste avec les autorisations Bluetooth habituelles:
<uses-permission Android:name="Android.permission.BLUETOOTH" />
<uses-permission Android:name="Android.permission.BLUETOOTH_ADMIN" />
<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION" />
Assurez-vous de disposer de l'autorisation d'exécution pour 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;
}
}
}
Enregistrez un récepteur de diffusion pour ACTION_FOUND
et appelez BluetoothAdapter.startDiscovery()
protected void proceedDiscovery() {
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_NAME_CHANGED);
registerReceiver(mReceiver, filter);
mBluetoothAdapter.startDiscovery();
}
_ {Ce qui est drôle avec ACTION_NAME_CHANGED
. Bien que la version 6.0 ne vous fournisse pas ACTION_FOUND
sans l’autorisation pour un emplacement approximatif, vous obtiendrez quand même des événements ACTION_NAME_CHANGED
, qui sont généralement associés à ACTION_FOUND
lors de la découverte des périphériques. C'est à dire. vous obtenez les deux événements, donc sans permission, vous pouvez toujours gérer ACTION_NAME_CHANGED
pour à peu près le même comportement. (Gourous, corrigez-moi si je me trompe)
J'avais un problème similaire avec un récepteur de radiodiffusion . Puis j'ai trouvé ceci: https://developer.Android.com/about/versions/Marshmallow/Android-6.0-changes.html#behavior- identifiant du matériel
Fondamentalement, sur 6.0, vous devez utiliser l'autorisation d'emplacement pour rechercher des périphériques Bluetooth.
je ne sais pas si votre code est correct pour obtenir un périphérique Bluetooth. Voici ce que je ressens à propos de votre code est. Intialiser et enregistrer BroadcastReceiver dans une fonction est une mauvaise idée. vous devriez le faire en dehors de la méthode onCreate()
. voici ce que vous devez faire dans votre code
comme pour enregistrer Reciver qui doit être fait dans onCreate()
comme ceci
registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
suivi d'initialisation ou de réception
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);
}
}
};
annuler l'enregistrement dans onPause()
ne pas oublier que
et dans votre discoverDevices()
, renvoyez la list
de périphériques ajoutés par reciver pour chaque appel de cette réaction;
Selon les réponses des experts, vous pouvez vérifier les points suivants pour que ACTION_FOUND fonctionne avec Android 6 et les versions ultérieures, 1. En plus de définir les autorisations de BLUETOOTH et BLUETOOTH_ADMIN, essayez
<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
Parfois, ces deux ne sont peut-être pas nécessaires, mais cela a fonctionné pour moi. Aussi, vous devez rechercher les autorisations des utilisateurs de manière dynamique en utilisant les codes
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);
Maintenant, écrivez vos codes pour effectuer l'opération requise. J'ai ajouté une méthode startDiscovery () juste après ceci . Cela fonctionnera sûrement pour vous ... Bon codage ...
J'ai constaté que le périphérique sur lequel je développais (Galaxy S4) devait être redémarré avant que les émissions ne continuent à être reçues.
Cependant, dans mon cas, je les recevais sans problème jusqu'à ce qu'ils (de manière aléatoire?) Cessent d'être reçus et peu importe ce que j'ai fait (fermer l'application, réinstaller l'application), les émissions ne sont pas reçues.
En publiant ceci comme réponse, je ne peux pas commenter avec mon niveau actuel de représentant.
Avez-vous la permission Bluetooth inclure dans votre AndroidManifest.xml?
<uses-permission Android:name="Android.permission.BLUETOOTH"/>
<uses-permission Android:name="Android.permission.BLUETOOTH_ADMIN"/>
Sinon, essayez (et recherchez) chacun séparément, car je ne me souviens pas de l'importance de chacun.
Si vous en avez, veuillez inclure plus de code afin qu’il soit possible de diagnostiquer votre problème.