简体   繁体   English

Android WifiManager getScanResult抱怨虽然声明了权限,但需要ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限

[英]Android WifiManager getScanResult complains Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission although declared permission

I am developing an App to check Wifi points. 我正在开发一个应用程序来检查Wifi点。

I am getting error "java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results" at wifiManager.getScanResults() even though I already declared those permissions. 我收到错误“java.lang.SecurityException:需要ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限来获取扫描结果”在wifiManager.getScanResults(),即使我已经声明了这些权限。

main 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 am on SDK 6.0 我在SDK 6.0上

I observed similar question , but solution does not apply since I already declared permission. 我观察到类似的问题 ,但解决方案不适用,因为我已经宣布了许可。

Anyone know what might be problem? 谁知道可能有什么问题? Thank you. 谢谢。

In Android M, you need to ask for the permission which is defined as dangerous in PermissionModel to the user before start using each time, it as such: 在Android M中,您需要在每次开始使用之前向用户请求在PermissionModel中定义为危险的权限,如下所示:

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 during runtime with: 并在运行时加载它:

loadPermissions(Manifest.permission.ACCESS_FINE_LOCATION,REQUEST_FINE_LOCATION);

To evaluate the results of your permission request, you can override onRequestPermissionsResult method: 要评估权限请求的结果,可以覆盖onRequestPermissionsResult方法:

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

}

MADAO is right : you should turn on GPS to get the WIFI access point list. MADAO是对的 :您应该打开GPS以获取WIFI接入点列表。

But I'm not sure about PEERS_MAC_ADDRESS. 但我不确定PEERS_MAC_ADDRESS。 If you look at the source code (line 957): 如果你看一下源代码 (第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 is checking canReadPeerMacAddresses which the code for checkPeersMacAddress() is: 第一个if是检查canReadPeerMacAddressescheckPeersMacAddress()的代码是:

/**
 * 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 the permission you can bypass if (!canReadPeerMacAddresses && !isActiveNetworkScorer && !isLocationEnabled()) { . 如果添加权限,则可以绕过if (!canReadPeerMacAddresses && !isActiveNetworkScorer && !isLocationEnabled()) { I've tested but I cannot get WIFI MAC list by just using the permission and disabling location. 我已经测试但是我只能通过使用权限和禁用位置来获取WIFI MAC列表。

ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION is necessary. ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION是必要的。 To get a valid result, you also have to turn on GPS or get a PEERS_MAC_ADDRESS permission like Setting . 要获得有效的结果,您还必须打开GPS或获得像Setting一样的PEERS_MAC_ADDRESS权限。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ACCESS_FINE_LOCATION 权限是否包括 ACCESS_COARSE_LOCATION 权限 - Does ACCESS_FINE_LOCATION permission include ACCESS_COARSE_LOCATION permissons 错误:java.lang.SecurityException:我的位置需要权限 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION - ERROR:java.lang.SecurityException: my location requires permission ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION Android权限ACCESS_FINE_LOCATION始终被拒绝 - Android Permission ACCESS_FINE_LOCATION is always denied 无法在Android中获得ACCESS_FINE_LOCATION权限 - Can't get ACCESS_FINE_LOCATION permission in android 缺少 GoogleMap.setMyLocationEnabled 所需的权限:android.permission.ACCESS_COARSE_LOCATION 或 android.permission.ACCESS_FINE_LOCATION - Missing permissions required by GoogleMap.setMyLocationEnabled: android.permission.ACCESS_COARSE_LOCATION or android.permission.ACCESS_FINE_LOCATION 由以下原因引起:java.lang.SecurityException:“被动”位置提供者需要ACCESS_FINE_LOCATION权限 - Caused by: java.lang.SecurityException: “passive” location provider requires ACCESS_FINE_LOCATION permission java.lang.SecurityException:“被动”位置提供者需要API级别26的ACCESS_FINE_LOCATION权限 - java.lang.SecurityException: “passive” location provider requires ACCESS_FINE_LOCATION permission on API level 26 客户端必须具有ACCESS_FINE_LOCATION权限才能请求PRIORITY_HIGH_ACCURACY位置运行时错误 - Client must have ACCESS_FINE_LOCATION permission to request PRIORITY_HIGH_ACCURACY locations runtime error java.lang.SecurityException:提供者gps需要ACCESS_FINE_LOCATION权限 - java.lang.SecurityException: Provider gps requires ACCESS_FINE_LOCATION permission java.lang.SecurityException: UID 10243 在 Android 10 中没有粗略/精细定位权限 - java.lang.SecurityException: UID 10243 does not have Coarse/Fine Location permission in Android 10
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM