Android WifiManager getScanResult complains about ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission, although permission is declared

I am developing an application for checking Wi-Fi points.

I get the error "java.lang.SecurityException: ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission is required to get scan results" in wifiManager.getScanResults (), although I already declared these permissions.

Primary activity

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> 

I'm on SDK 6.0

I observed a similar question , but the solution does not apply, since I already announced the permission.

Does anyone know what could be the problem? Thanks.

+5
source share
3 answers

In Android M, you need to ask for permission, which in PermissionModel is defined as dangerous for the user, before you start using it every time, it is as such:

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

Add this to your activity:

 private static final int REQUEST_FINE_LOCATION=0 

and load it at runtime:

 loadPermissions(Manifest.permission.ACCESS_FINE_LOCATION,REQUEST_FINE_LOCATION); 

To evaluate the results of your permission request, you can override the onRequestPermissionsResult method:

 @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; } } 
+5
source

MADAO is right : you must enable GPS to get a list of WIFI access points.

But I'm not sure about PEERS_MAC_ADDRESS. If you look at the source code (line 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); } } 

The first if checks canReadPeerMacAddresses , for which the code is 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; } 

If you add permission, you can bypass if (!canReadPeerMacAddresses && !isActiveNetworkScorer && !isLocationEnabled()) { . I tested, but I can not get the WIFI MAC list, just using permission and turning off the location.

+1
source

ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION . To get a reliable result, you also need to turn on GPS or get PEERS_MAC_ADDRESS permission, such as Setting .

0
source

Source: https://habr.com/ru/post/1236027/


All Articles