Question SecurityException levée lors de l'appel de WifiManager startScan


J'utilise un PendingIntent lancé par AlarmManager (avec setRepeating) pour lancer des analyses wifi (en utilisant IntentService) toutes les quelques minutes. Sur la plupart des appareils et dans la plupart des cas, cela ne pose aucun problème. Cependant, sur plusieurs appareils, je reçois l'erreur suivante (impossible de reproduire l'erreur sur un périphérique de test. Il s'agit d'un journal des incidents sur le périphérique d'un utilisateur):

java.lang.RuntimeException: Unable to start service com.myapp.android.service.MyService@44a9701 with Intent { act=com.myapp.android.ACTION_PERFORM_WIFI_SCAN flg=0x4 cmp=com.myapp/com.mayapp.android.service.MyService (has extras) }: java.lang.SecurityException: Permission Denial: broadcast from android asks to run as user -1 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL or android.permission.INTERACT_ACROSS_USERS
       at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3021)
       at android.app.ActivityThread.-wrap17(ActivityThread.java)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1443)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:148)
       at android.app.ActivityThread.main(ActivityThread.java:5415)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:725)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:615)
Caused by: java.lang.SecurityException: Permission Denial: broadcast from android asks to run as user -1 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL or android.permission.INTERACT_ACROSS_USERS
       at android.os.Parcel.readException(Parcel.java:1599)
       at android.os.Parcel.readException(Parcel.java:1552)
       at android.net.wifi.IWifiManager$Stub$Proxy.startScan(IWifiManager.java:1045)
       at android.net.wifi.WifiManager.startScan(WifiManager.java:1088)
       ...

Je crée le PendingIntent de mon application donc je ne vois aucune raison pour la SecurityException jeté de WifiManager (Surtout que cela arrive rarement).

le IntentService lancé à partir du PendingIntent le code est comme suit:

mContext.registerReceiver(mWifiScanReceiver, new IntentFilter(
                    WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

boolean ok = mWifiManager.startScan();

Des idées sur ce qui pourrait causer cela?


10
2017-07-22 15:24


origine


Réponses:


Cela se produit en raison des nouvelles autorisations d'application pour Android m. Voir le commentaire ci-dessus le code source de wifimanager's getScanResults() for api 23-

/**
     * Return the results of the latest access point scan.
     * @return the list of access points found in the most recent scan. An app must hold
     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
     * in order to get valid results.
     */
public List<ScanResult> getScanResults() {
        try {
            return mService.getScanResults(mContext.getOpPackageName());
        } catch (RemoteException e) {
            return null;
        }
    }

Par conséquent, vous devrez demander à l'utilisateur des autorisations sur l'exécution. Mettez ces autorisations dans votre manifeste-

  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

A partir de api 23, vous avez besoin d'une autorisation pour accéder à l'emplacement de l'utilisateur pour l'utiliser. Je vous suggère d'utiliser une vérification des autorisations basée sur le niveau de l'API et de commencer intentionnellement uniquement si les autorisations ont été accordées. Quelque chose comme ça-

if (Build.VERSION.SDK_INT >= 23) {
int hasReadLocationPermission = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
      if (hasReadLocationPermission != PackageManager.PERMISSION_GRANTED) {
        if (!ActivityCompat.shouldShowRequestPermissionRationale(HomeActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)) {
          showMessageOKCancel("You need to allow access to GPS",
              new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                  ActivityCompat.requestPermissions(HomeActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, GPS_ENABLE_REQUEST);
                }
              });
          return;
        }
        ActivityCompat.requestPermissions(HomeActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, GPS_ENABLE_REQUEST);
        return;
      }
      if (locationManager != null && !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
        gotoGPSEnableScreen();
      } else {
        //Permissions granted and gps is on
        launchService(true);
      }
}

Pour vérifier les résultats-

@Override
  public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
      case GPS_ENABLE_REQUEST:
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
          if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            gotoGPSEnableScreen();
          }
        } else {
          launchService(false);
        }
      default:
        return;
    }
  }

METTRE À JOUR:

android.permission.INTERACT_ACROSS_USERS_FULL est une autorisation au niveau de la signature. Ajoutez simplement cet Android: protectionLevel = "signature" dans votre manifeste.

Pour plus de détails vous pouvez vérifier ceci

http://developer.android.com/guide/topics/manifest/permission-element.html

<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" android:protectionLevel="signature"/>

3
2018-02-22 07:32



Si vous allez passer outre

onCreate() 

dans ton

IntentService,

alors assurez-vous d'appeler

super.onCreate()

dedans. Cela semble être probablement votre problème.


0
2018-02-22 08:00



Votre problème est que vous appelez de différents utilisateurs et demandez à exécuter sur différents utilisateurs et cela nécessite android.permission.INTERACT_ACROSS_USERS_FULL et c'est la permission au niveau de la signature. Ajoutez juste ceci android:protectionLevel="signature" dans votre manifeste.

Pour plus de détails vous pouvez vérifier ceci

http://developer.android.com/guide/topics/manifest/permission-element.html

<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" android:protectionLevel="signature"/>

-1
2018-02-23 08:36