[英]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
是检查canReadPeerMacAddresses
, 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 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_LOCATION
或ACCESS_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.