2015-07-22 13 views
10

Sto utilizzando un PendingIntent lanciato da AlarmManager (con setRepeating) per avviare le scansioni wifi (utilizzando IntentService) ogni pochi minuti. Sulla maggior parte dei dispositivi e nella maggior parte dei casi, non c'è alcun problema. Tuttavia, su diversi dispositivi ottengo il seguente errore (. Impossibile riprodurre l'errore su qualsiasi dispositivo di prova Si tratta di un crash log dal dispositivo di un utente):SecurityException generato quando si chiama 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) 
     ... 

Sto creando il PendingIntent dalla mia app quindi non vedo alcun motivo per il SecurityException generato da WifiManager (Soprattutto perché questo accade raramente).

Il IntentService lanciato dal codice PendingIntent è la seguente:

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

boolean ok = mWifiManager.startScan(); 

Tutte le idee su quello che potrebbe essere la causa?

+0

Si dice che esso richiede android.permission.INTERACT_ACROSS_USERS_FULL o android.permission.INTERACT_ACROSS_USERS premission, hai cercato di aggiungere un po 'nel vostro manifesta? –

+3

@ Berťák, questa autorizzazione è un'autorizzazione di sistema e nessuna app (a meno che non si tratti di un'app di sistema) può richiederlo. Inoltre, non è necessario per chiamare "startScan" e ottenere i risultati attraverso la trasmissione "SCAN_RESULTS_AVAILABLE_ACTION". Questo è ciò che lo rende strano ... – Muzikant

+0

Sembra che il tuo IntentService funzioni in un contesto utente differente. Sembra che uno o più utenti abbiano effettuato l'accesso al tuo telefono. È strano. – ShihabSoft

risposta

3

Questo sta accadendo a causa delle nuove autorizzazioni app per Android m. Vedere il commento di cui sopra il codice sorgente di 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; 
     } 
    } 

Quindi, si dovrà chiedere all'utente autorizzazioni per l'esecuzione. Metti queste autorizzazioni nel tuo 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"/> 

Da api 23 in poi è necessario il permesso di accedere alla posizione dell'utente per usarlo. Suggerisco di utilizzare un controllo delle autorizzazioni basato sul livello API e avviare l'intento solo se le autorizzazioni sono state concesse. Qualcosa come questo-

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

seguito per verificare Risultati

@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:

android.permission.INTERACT_ACROSS_USERS_FULL è un'autorizzazione livello di firma. Basta aggiungere questo android: protectionLevel = "signature" nel tuo manifest.

Per maggiori dettagli è possibile controllare questo

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

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

Grazie per la risposta dettagliata ma questo non fornisce una soluzione al problema. Sono a conoscenza delle modifiche alle autorizzazioni in SDK 23 e il manifest ha le autorizzazioni che hai citato ma questo non spiega l'errore 'broadcast da Android chiede di essere eseguito come utente -1 ma sta chiamando dall'utente 0; questo richiede android.permission.INTERACT_ACROSS_USERS_FULL o android.permission.INTERACT_ACROSS_USERS'. Inoltre, ciò accade molto raramente e non sono stato in grado di riprodurre lo stesso errore sullo stesso identico dispositivo con lo stesso livello API – Muzikant

+0

Un'altra cosa, il frammento di codice nella tua risposta si riferisce a 'getScanResults' mentre l'errore viene ricevuto su' startScan' – Muzikant

+0

@Muzikant il wifimanager chiama getScanResults per ottenere i risultati della scansione dopo aver chiamato startscsan. Inoltre ho aggiornato la mia risposta. –

0

Se hai intenzione di ignorare

onCreate() 

nel vostro

IntentService, 

poi fare sur e chiami

super.onCreate() 

in esso. Questo sembra essere probabilmente il tuo problema.

-1

Il problema è che si sta chiamando da un altro utente e si richiede di eseguire su un altro utente e che richiede android.permission.INTERACT_ACROSS_USERS_FULL e questo è il permesso a livello di firma.Basta aggiungere questo android:protectionLevel="signature" nel tuo manifest.

Per maggiori dettagli è possibile controllare questo

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

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