2015-07-22 2 views
10

Ich verwende eine PendingIntent gestartet von AlarmManager (mit setRepeating), um Wifi-Scans (mit IntentService) alle paar Minuten zu starten. Auf den meisten Geräten und in den meisten Fällen gibt es kein Problem damit. jedoch auf mehrere Geräte, die ich die folgende Fehlermeldung (zu. Den Fehler auf jedem Testgerät nicht reproduzieren Dies ist ein Crash-Protokoll von einem Gerät des Benutzers):SecurityException ausgelöst beim Aufrufen von WifiManager StartScan

java.lang.RuntimeException: Unable to start service [email protected] 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) 
     ... 

ich die PendingIntent von meiner app zu schaffen also sehe ich keinen Grund für die SecurityException geworfen von WifiManager (zumal dies selten passiert).

Die IntentService vom PendingIntent Code gestartet ist wie folgt:

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

boolean ok = mWifiManager.startScan(); 

Alle Ideen, was dieses verursachen könnte?

+0

Er sagt, dass es android.permission.INTERACT_ACROSS_USERS_FULL oder android.permission.INTERACT_ACROSS_USERS premission erfordert, haben Sie versucht, einige in Ihrem Manifest hinzufügen? –

+3

@ Berťák, diese Erlaubnis ist eine Systemerlaubnis und keine App (es sei denn, es ist eine System-App) kann dies anfordern. Außerdem ist es nicht erforderlich, um 'startScan' aufzurufen und die Ergebnisse über die 'SCAN_RESULTS_AVAILABLE_ACTION'-Übertragung zu erhalten. Das ist, was es komisch macht ... – Muzikant

+0

Es scheint, dass Ihr IntentService in einem anderen Benutzerkontext ausgeführt wird. Es scheint, dass sich ein oder mehrere Benutzer bei Ihrem Telefon angemeldet haben. – ShihabSoft

Antwort

3

Dies geschieht aufgrund der neuen App-Berechtigungen für Android m. Siehe Kommentar über den Quellcode 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; 
     } 
    } 

Daher werden Sie den Benutzer nach Berechtigungen zur Laufzeit fragen. Setzen Sie diese Berechtigungen in Ihr Manifest -

<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"/> 

Ab api 23 benötigen Sie eine Erlaubnis, auf den Benutzerstandort zuzugreifen, um es zu verwenden. Ich schlage vor, dass Sie eine Berechtigungsprüfung basierend auf der API-Ebene und der Startabsicht nur dann verwenden, wenn die Berechtigungen erteilt wurden. So etwas wie this-

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); 
     } 
} 

Weitere ergebnis-

@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; 
    } 
    } 

UPDATE zu überprüfen:

android.permission.INTERACT_ACROSS_USERS_FULL ist eine Signatur-Ebene Erlaubnis. Fügen Sie einfach dieses Android: protectionLevel = "Signatur" in Ihrem Manifest hinzu.

Für weitere Informationen können Sie überprüfen diese

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

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

Danke für die detaillierte Antwort, aber das bietet keine Lösung für das Problem. Ich bin mir der Änderung der Berechtigungen in SDK 23 bewusst, und das Manifest hat die von Ihnen erwähnten Berechtigungen, aber dies erklärt nicht den Fehler "broadcast from android fragt, ob er als Benutzer -1 ausgeführt wird, sondern von Benutzer 0 anruft; Dies erfordert android.permission.INTERACT_ACROSS_USERS_FULL oder android.permission.INTERACT_ACROSS_USERS'. Außerdem passiert das sehr selten und ich konnte denselben Fehler nicht auf dem gleichen Gerät mit der gleichen API-Ebene reproduzieren. – Muzikant

+0

Noch eine Sache, das Codefragment in Ihrer Antwort bezieht sich auf 'getScanResults', während der Fehler empfangen wird' startScan' – Muzikant

+0

@Muzikant Der Wifimanager ruft getScanResults auf, um nach dem Aufruf von startscsan die Scan-Ergebnisse zu erhalten. Auch ich habe meine Antwort aktualisiert. –

0

Wenn Sie

onCreate() 

in Ihrem

IntentService, 

dann sur machen außer Kraft zu setzen gehen Sie rufen

super.onCreate() 

in es. Das scheint sehr wahrscheinlich dein Problem zu sein.

-1

Ihr Problem ist, dass Sie von verschiedenen Benutzern aufrufen und fragen, auf verschiedenen Benutzer ausgeführt werden, und das erfordert android.permission.INTERACT_ACROSS_USERS_FULL und das ist Signaturebene Berechtigung.Fügen Sie einfach dieses android:protectionLevel="signature" in Ihrem Manifest hinzu.

Für weitere Informationen können Sie dies überprüfen

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

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