2015-11-16 30 views
5

dichiarato Sto sviluppando un App per controllare Wifi punti.Android WifiManager getScanResult lamenta bisogno ACCESS_COARSE_LOCATION o permesso ACCESS_FINE_LOCATION anche se il permesso

Ricevo l'errore "java.lang.SecurityException: è necessario il permesso ACCESS_COARSE_LOCATION o ACCESS_FINE_LOCATION per ottenere i risultati di scansione" su wifiManager.getScanResults() anche se ho già dichiarato tali autorizzazioni.

attività principale

public class MainActivity extends AppCompatActivity { 

WifiManager wifiManager; 
String[] wifis; 
WifiReceiver wifiReceiver; 

ListView wifiListView; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    wifiListView = (ListView) findViewById(R.id.wifi_list); 

    wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); 
    wifiReceiver = new WifiReceiver(); 
    wifiManager.startScan(); 
} 

protected void onPause() { 
    unregisterReceiver(wifiReceiver); 
    super.onPause(); 
} 

protected void onResume() { 
    registerReceiver(wifiReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); 
    super.onResume(); 
} 

private class WifiReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     List<ScanResult> wifiScanList = wifiManager.getScanResults(); 
     wifis = new String[wifiScanList.size()]; 

     for (int i = 0; i < wifiScanList.size(); i++) { 
      wifis[i] = wifiScanList.get(i).toString(); 
     } 

     wifiListView.setAdapter(new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, wifis)); 
    } 
} 

manifesta

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
package="com.example.sample"> 

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

<application 
    android:allowBackup="true" 
    android:icon="@mipmap/ic_launcher" 
    android:label="@string/app_name" 
    android:supportsRtl="true" 
    android:theme="@style/AppTheme"> 
    <activity android:name=".MainActivity"> 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
</application> 

Sono in SDK 6.0

ho osservato simile question, ma soluzione non è valida in quanto ho già dichiarato il permesso.

Qualcuno sa quello che potrebbe essere un problema? Grazie.

+0

Prova a riavviare l'IDE. –

+1

Provare a pulire e compilare – sean

+0

provato a riavviare IDE, disinstallare l'app, pulire il progetto, creare il progetto, ancora lo stesso errore – kevin0228ca

risposta

5

In Android M, è necessario chiedere il permesso che viene definita come pericolosa PermissionModel per l'utente prima di iniziare a utilizzare di volta in volta, come tale:

private boolean mayRequestLocation() { 
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 
      return true; 
     } 
     if (checkSelfPermission(ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { 
      return true; 
     } 
     if (shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) { 
      Snackbar.make(mView, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE) 
        .setAction(android.R.string.ok, new View.OnClickListener() { 
         @Override 
         @TargetApi(Build.VERSION_CODES.M) 
         public void onClick(View v) { 
          requestPermissions(new String[]{ACCESS_FINE_LOCATION}, REQUEST_FINE_LOCATION); 
         } 
        }); 
     } else { 
      requestPermissions(new String[]{ACCESS_FINE_LOCATION}, REQUEST_FINE_LOCATION); 
     } 
     return false; 
    } 

aggiungere questo alla tua attività:

private static final int REQUEST_FINE_LOCATION=0 

e caricarlo durante il runtime con:

loadPermissions(Manifest.permission.ACCESS_FINE_LOCATION,REQUEST_FINE_LOCATION); 

valutare ° e risultati della sua richiesta di autorizzazione, è possibile ignorare onRequestPermissionsResult metodo:

@Override 
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 
    switch (requestCode) { 
     case REQUEST_FINE_LOCATION: { 
      // If request is cancelled, the result arrays are empty. 
      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
       // The requested permission is granted. 
      } 
      else{ 
       // The user disallowed the requested permission. 
      } 
      return; 
     } 

} 
0

ACCESS_FINE_LOCATION o ACCESS_COARSE_LOCATION è necessario. Per ottenere un risultato valido, si hanno anche per attivare il GPS o ottenere un permesso PEERS_MAC_ADDRESS come Setting.

1

MADAO is right: è necessario attivare il GPS per ottenere l'elenco dei punti di accesso Wi-Fi.

Ma io non sono sicuro di PEERS_MAC_ADDRESS. Se si guarda alla the source code (linea 957):

/** 
* Return the results of the most recent access point scan, in the form of 
* a list of {@link ScanResult} objects. 
* @return the list of results 
*/ 
public List<ScanResult> getScanResults(String callingPackage) { 
    enforceAccessPermission(); 
    int userId = UserHandle.getCallingUserId(); 
    int uid = Binder.getCallingUid(); 
    boolean canReadPeerMacAddresses = checkPeersMacAddress(); 
    boolean isActiveNetworkScorer = 
      NetworkScorerAppManager.isCallerActiveScorer(mContext, uid); 
    boolean hasInteractUsersFull = checkInteractAcrossUsersFull(); 
    long ident = Binder.clearCallingIdentity(); 
    try { 
     if (!canReadPeerMacAddresses && !isActiveNetworkScorer 
       && !isLocationEnabled()) { 
      return new ArrayList<ScanResult>(); 
     } 
     if (!canReadPeerMacAddresses && !isActiveNetworkScorer 
       && !checkCallerCanAccessScanResults(callingPackage, uid)) { 
      return new ArrayList<ScanResult>(); 
     } 
     if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage) 
       != AppOpsManager.MODE_ALLOWED) { 
      return new ArrayList<ScanResult>(); 
     } 
     if (!isCurrentProfile(userId) && !hasInteractUsersFull) { 
      return new ArrayList<ScanResult>(); 
     } 
     return mWifiStateMachine.syncGetScanResultsList(); 
    } finally { 
     Binder.restoreCallingIdentity(ident); 
    } 
} 

Il primo if sta controllando canReadPeerMacAddresses che il codice per checkPeersMacAddress() è:

/** 
* Returns true if the caller holds PEERS_MAC_ADDRESS. 
*/ 
private boolean checkPeersMacAddress() { 
    return mContext.checkCallingOrSelfPermission(
      android.Manifest.permission.PEERS_MAC_ADDRESS) == PackageManager.PERMISSION_GRANTED; 
} 

Se si aggiunge il permesso è possibile ignorare if (!canReadPeerMacAddresses && !isActiveNetworkScorer && !isLocationEnabled()) {. Ho provato ma non riesco ad ottenere la lista WIFI MAC semplicemente usando il permesso e disabilitando la posizione.

+0

Stai dicendo che hai verificato l'autorizzazione e quando chiami 'mContext.checkCallingOrSelfPermission ( android.Manifest.permission.PEERS_MAC_ADDRESS) == PackageManager.PERMISSION_GRANTED' ottieni vero? In tal caso, forse l'accesso è bloccato dalla chiamata a 'enforceAccessPermission()'? – davidgyoung

+0

No. Come ho detto, ho aggiunto l'autorizzazione PEERS_MAC_ADDRESS ma non sono riuscito a ottenere l'elenco dei punti di accesso senza attivare la posizione. Inoltre, faccio della mia app un'app di sistema, ma non riesco ancora a ottenere l'elenco dei punti di accesso senza attivare la posizione. –

+0

Il codice per 'enforceAccessPermission()' è il seguente: 'private void enforceAccessPermission() { mContext.enforceCallingOrSelfPermission (android.Manifest.permission.ACCESS_WIFI_STATE, " WifiService "); } 'E ho l'autorizzazione' ACCESS_WIFI_STATE' in manifest. –