2015-11-16 11 views
5

Pracuję nad aplikacją do sprawdzania punktów Wi-Fi.Android WifiManager getScanResult narzekania Potrzebuję pozwolenia ACCESS_COARSE_LOCATION lub ACCESS_FINE_LOCATION pomimo deklarowanej zgody

Otrzymuję komunikat o błędzie "java.lang.SecurityException: Potrzebuję uprawnienia ACCESS_COARSE_LOCATION lub ACCESS_FINE_LOCATION, aby uzyskać wyniki skanowania" na stronie wifiManager.getScanResults(), mimo że już zadeklarowałem te uprawnienia.

aktywność główny

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

manifest

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

jestem w SDK 6.0

zauważyłem podobną question, ale rozwiązanie to nie ma zastosowania, ponieważ ja już zadeklarował zgodę.

Ktoś wie, co może być przyczyną problemu? Dziękuję Ci.

+0

Spróbuj ponownie uruchomić IDE. –

+1

Spróbuj wyczyścić i zbudować – sean

+0

próbowałem restartować IDE, odinstalować aplikację, oczyścić projekt, zbudować projekt, ciągle ten sam błąd – kevin0228ca

Odpowiedz

5

W Android M, trzeba prosić o pozwolenie, które jest zdefiniowane jako niebezpieczne w PermissionModel do użytkownika przed rozpoczęciem korzystania za każdym razem, to jako takie:

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

Dodaj to do swojej działalności:

private static final int REQUEST_FINE_LOCATION=0 

i załadować go podczas wykonywania z:

loadPermissions(Manifest.permission.ACCESS_FINE_LOCATION,REQUEST_FINE_LOCATION); 

Aby ocenić th Wyniki e Twojego prosić o pozwolenie, można zastąpić onRequestPermissionsResult metody:

@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 lub ACCESS_COARSE_LOCATION jest konieczne. Aby uzyskać prawidłowy wynik, musisz włączyć GPS lub uzyskać uprawnienie PEERS_MAC_ADDRESS, takie jak Setting.

1

MADAO is right: należy włączyć GPS, aby uzyskać listę punktów dostępu WIFI.

Ale nie jestem pewien o PEERS_MAC_ADDRESS. Jeśli spojrzeć na the source code (linia 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); 
    } 
} 

Pierwszy if sprawdza canReadPeerMacAddresses które kodują checkPeersMacAddress() jest:

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

Jeśli dodać pozwolenie można ominąć if (!canReadPeerMacAddresses && !isActiveNetworkScorer && !isLocationEnabled()) {. Przetestowałem, ale nie mogę uzyskać listy WIFI MAC, używając tylko pozwolenia i wyłączając lokalizację.

+0

Czy mówisz, że zweryfikowałeś, że używasz tego pozwolenia i kiedy wywołujesz 'mContext.checkCallingOrSelfPermission ( android.Manifest.permission.PEERS_MAC_ADDRESS) == PackageManager.PERMISSION_GRANTED', to prawda? Jeśli tak, być może dostęp jest blokowany przez wywołanie metody 'enforceAccessPermission()'? – davidgyoung

+0

Nie. Jak już powiedziałem, dodałem uprawnienia PEERS_MAC_ADDRESS, ale nie udało mi się uzyskać listy punktów dostępu bez włączania lokalizacji. Co więcej, tworzę aplikację jako systemową, ale nadal nie mogę uzyskać listy punktów dostępu bez włączania lokalizacji. –

+0

Kod 'enforceAccessPermission()' jest jak poniżej: 'private void enforceAccessPermission() { mContext.enforceCallingOrSelfPermission (android.Manifest.permission.ACCESS_WIFI_STATE, " WifiService "); } 'Mam uprawnienie' ACCESS_WIFI_STATE' w manifeście. –

Powiązane problemy