web-dev-qa-db-fra.com

SCAN_RESULTS_AVAILABLE_ACTION renvoie une liste vide dans Android 6.0

Hier, mon Nexus 5 reçoit la mise à jour de Android MNC vers la version 6.0 - Marshmallow. Depuis lors, les actions d'analyse des réseaux disponibles sur l'appareil cessent de recevoir la liste. Dans ce cas, la liste des résultats a une taille de 0, même avec plus de 10 réseaux Wifi répertoriés dans les paramètres du système Wifi.

Le code utilisé est l’habituel: enregistrez le SCAN_RESULTS_AVAILABLE_ACTION et attendez l’événement dans le récepteur, comme ceci:

// Register the Receiver in some part os fragment...
getActivity().registerReceiver(wifiListener, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
WifiManager wifiManager = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE);
wifiManager.startScan();

// Inside the receiver:
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
List<ScanResult> results = wifiManager.getScanResults();
// the result.size() is 0 after update to Android v6.0, same code working in older devices.

J'ai cherché dans le sujet changements de l'API à ce sujet, mais je n'ai pas vu de changements importants pour cette fonctionnalité.

Quelqu'un l'a-t-il remarqué? Y a-t-il quelque chose de nouveau dans l'API ou juste un cas isolé?

45
Deividi Cavarzan

À partir de Android 6.0, le comportement de l'autorisation est passé à l'exécution. Pour utiliser une fonctionnalité nécessitant une autorisation, il faut d'abord vérifier si l'autorisation est accordée précédemment. Utilisation de checkSelfPermission(permissionString) - méthode un résultat est renvoyé, que l'autorisation soit PERMISSION_GRANTED ou PERMISSION_DENIED.

Si l'autorisation n'est pas accordée ou s'il s'agit de la première fois, une demande d'autorisation doit être faite. Donner à un utilisateur une option d'accorder ou de refuser.

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
   requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                 PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION);
    //After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method

}else{
    getScanningResults();
   //do something, permission was previously granted; or legacy device
}

Si votre code est en cours d'exécution sur le périphérique avant M, vous continuez avec votre code, l'autorisation a été accordée à l'aide de la méthode héritée.

Une fois la permission demandée, la boîte de dialogue sera présentée à l'utilisateur. Sa réponse sera livrée sous la forme:

@Override
 public void onRequestPermissionsResult(int requestCode, String[] permissions,
         int[] grantResults) {
     if (requestCode == PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION
             && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
         // Do something with granted permission
        mWifiListener.getScanningResults();
     }
 }

Après cela, vous pouvez vérifier si les services de localisation sont activés en utilisant LocationServices.SettingsApi Et demander à l'utilisateur d'activer si cette option est désactivée. Ceci est possible avec le rappel de Play Services LocationSettingsStatusCodes.RESOLUTION_REQUIRED.

57
Nikola Despotoski

Je trouve un problème connexe dans le problème de suivi des problèmes AOSP 18537 WifiManager # getScanResults () renvoie une liste de tableaux vide si le GPS est désactivé.

Le problème mentionne à partir de # 1 , le mobile doit ouvrir le service de localisation pour obtenir la liste wifi du mobile.

Et à partir de # 18 , le membre du projet Android) affirme que l'équipe de développement a résolu le problème que vous avez signalé et qu'il sera disponible dans une version ultérieure.

L'APP est dans targetSdkVersion 23, il suffit de suivre la solution ci-dessus pour vérifier les autorisations d'exécution. L'application du problème d'activation des services de localisation résoudra le problème dans Android version future.

34
Fantasy Fang

Modifier

Le problème semble donc être lié au nouveau traitement des autorisations. Vous devez demander la permission avant de passer au code wifi. Voici un exemple:

// call this method only if you are on 6.0 and up, otherwise call doGetWifi()
private void getWifi() {
    if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 0x12345);
    } else {
        doGetWifi(); // the actual wifi scanning
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == 0x12345) {
        for (int grantResult : grantResults) {
            if (grantResult != PackageManager.PERMISSION_GRANTED) {
                return;
            }
        }
        getWifi();
    }
}

Cette vérification doit être effectuée dans une activité.

L'exemple de code d'origine est disponible ici , modifié en fonction du problème traité dans cette rubrique.

Original

Selon le lien modifications de l'API , votre application doit posséder l'une des autorisations d'emplacement. Citation:

WifiManager.getScanResults (): votre application doit disposer de l'autorisation ACCESS_FINE_LOCATION ou ACCESS_COARSE_LOCATION.

Notez également qu’il existe une nouvelle clé booléenne reçue par votre BroadcastReceiver à l’action SCAN_RESULTS_AVAILABLE_ACTION: EXTRA_RESULTS_UPDATED. Cela indique si l'analyse est terminée et que vous pouvez accéder aux résultats en appelant wifiManager.getScanResults().

7
Gergely Kőrössy

Cela ne fonctionnera que si le GPS est activé. Bizarre, mais c’est la seule façon pour moi d’obtenir la liste des wifi :-(.

3
Robbie

En plus des réponses données; vous pouvez également utiliser checkSelfPermission sur ContextCompat pour permettre la compatibilité avec les versions antérieures Android):

if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION);
    // Get the result in onRequestPermissionsResult(int, String[], int[])
} else {
    // Permission was granted, do your stuff here
}
3
CptSadface