致命异常:java.lang.SecurityException:需要 ACCESS_COARSE_LOCATION 或 ACCESS_FINE_LOCATION 许可
FATAL EXCEPTION: java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission
我在尝试更新大于 22 的 compileSdkVersion 和 TargetSdkversion 后收到此错误。似乎我正在我的 doInBackground 方法中执行任何 GUI 任务,但我无法弄清楚。如果能提供解决方案,我将不胜感激。
这是我的堆栈跟踪:
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: xy.abc.xyz.xy, PID: 15246
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask.done(AsyncTask.java:309)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results
at android.os.Parcel.readException(Parcel.java:1599)
at android.os.Parcel.readException(Parcel.java:1552)
at android.net.wifi.IWifiManager$Stub$Proxy.getScanResults(IWifiManager.java:1066) at android.net.wifi.WifiManager.getScanResults(WifiManager.java:1311)
at xy.abc.xyz.xy.config.WlanInfoAdapter.getNewItems(WlanInfoAdapter.java:72)
at xy.abc.xyz.xy.android.data.ChangeableArrayAdapter.doInBackground(ChangeableArrayAdapter.java:78)
at xy.abc.xyz.xy.android.data.ChangeableArrayAdapter.doInBackground(ChangeableArrayAdapter.java:74)
at android.os.AsyncTask.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
class中的方法WlanInfoAdapter.java:72在这里:
@Override
protected List<WlanInfo> getNewItems() {
WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
List<ScanResult> scanResults = wifiManager.getScanResults();
List<WlanInfo> infoList = new ArrayList<>(scanResults.size());
WifiInfo connectionInfo = wifiManager.getConnectionInfo();
try {
List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks();
Map<String, WifiConfiguration> configuredNetworkIds = new HashMap<>();
for (WifiConfiguration configuredNetwork : configuredNetworks) {
if (configuredNetwork.SSID != null) {
configuredNetworkIds.put(WlanInfo.cleanSSID(configuredNetwork.SSID), configuredNetwork);
} else {
wifiManager.removeNetwork(configuredNetwork.networkId);
}
}
for (ScanResult scanResult : scanResults) {
WlanInfo wlanInfo = new WlanInfo(scanResult);
WifiConfiguration configuration = configuredNetworkIds.get(wlanInfo.getSSID());
wlanInfo.setConfiguration(configuration);
wlanInfo.setIsActive(configuration != null && configuration.networkId == connectionInfo.getNetworkId());
if (showUnknown || wlanInfo.isConfigured() || wlanInfo.isOpen()) {
infoList.add(wlanInfo);
}
}
}
catch (Exception e) { e.printStackTrace(); return null; }
return infoList;
}
changeableArrayAdapter.javaclass中的方法显示错误如下。它在哪里调用 getNewItems() 方法:
ChangeableArrayAdapter.java:78
ChangeableArrayAdapter.java:74
public void triggerRefresh() {
AsyncTask<Void, Void, List<T>> asyncTask = new AsyncTask<Void, Void, List<T>>() {
@Override
protected List<T> doInBackground(Void... objects) {
return getNewItems();
//return null;
}
您需要添加 ACCESS_COARSE_LOCATION
或 ACCESS_FINE_LOCATION
作为 Android 清单文件的权限。
如果您只针对 API 22,那么您需要在 android 清单文件中添加这 2 权限
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
如果您的目标是 Android Marshmallow(Api 23 岁及以上),您需要在您的应用中授予运行时权限。
将这些添加到 AndroidManifest.xml
之前的 application
标签
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
同样对于Android版本>=23,您需要在run-time
中请求权限
if (ContextCompat.checkSelfPermission(YourActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&&
ContextCompat.checkSelfPermission(YourActivity.this,
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
askForLocationPermissions();
} else {
//do your work
}
和
private void askForLocationPermissions() {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
new android.support.v7.app.AlertDialog.Builder(this)
.setTitle("Location permessions needed")
.setMessage("you need to allow this permission!")
.setPositiveButton("Sure", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(YourActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
}
})
.setNegativeButton("Not now", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// //Do nothing
}
})
.show();
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
// MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
还有
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
switch (requestCode) {
case LOCATION_PERMISSION_REQUEST_CODE:
if (isPermissionGranted(permissions, grantResults, Manifest.permission.ACCESS_FINE_LOCATION)) {
//Do you work
} else {
Toast.makeText(this, "Can not proceed! i need permission" , Toast.LENGTH_SHORT).show();
}
break;
}
}
和
public static boolean isPermissionGranted(@NonNull String[] grantPermissions, @NonNull int[] grantResults,
@NonNull String permission) {
for (int i = 0; i < grantPermissions.length; i++) {
if (permission.equals(grantPermissions[i])) {
return grantResults[i] == PackageManager.PERMISSION_GRANTED;
}
}
return false;
}
我在尝试更新大于 22 的 compileSdkVersion 和 TargetSdkversion 后收到此错误。似乎我正在我的 doInBackground 方法中执行任何 GUI 任务,但我无法弄清楚。如果能提供解决方案,我将不胜感激。
这是我的堆栈跟踪:
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: xy.abc.xyz.xy, PID: 15246
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask.done(AsyncTask.java:309)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results
at android.os.Parcel.readException(Parcel.java:1599)
at android.os.Parcel.readException(Parcel.java:1552)
at android.net.wifi.IWifiManager$Stub$Proxy.getScanResults(IWifiManager.java:1066) at android.net.wifi.WifiManager.getScanResults(WifiManager.java:1311)
at xy.abc.xyz.xy.config.WlanInfoAdapter.getNewItems(WlanInfoAdapter.java:72)
at xy.abc.xyz.xy.android.data.ChangeableArrayAdapter.doInBackground(ChangeableArrayAdapter.java:78)
at xy.abc.xyz.xy.android.data.ChangeableArrayAdapter.doInBackground(ChangeableArrayAdapter.java:74)
at android.os.AsyncTask.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
class中的方法WlanInfoAdapter.java:72在这里:
@Override
protected List<WlanInfo> getNewItems() {
WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
List<ScanResult> scanResults = wifiManager.getScanResults();
List<WlanInfo> infoList = new ArrayList<>(scanResults.size());
WifiInfo connectionInfo = wifiManager.getConnectionInfo();
try {
List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks();
Map<String, WifiConfiguration> configuredNetworkIds = new HashMap<>();
for (WifiConfiguration configuredNetwork : configuredNetworks) {
if (configuredNetwork.SSID != null) {
configuredNetworkIds.put(WlanInfo.cleanSSID(configuredNetwork.SSID), configuredNetwork);
} else {
wifiManager.removeNetwork(configuredNetwork.networkId);
}
}
for (ScanResult scanResult : scanResults) {
WlanInfo wlanInfo = new WlanInfo(scanResult);
WifiConfiguration configuration = configuredNetworkIds.get(wlanInfo.getSSID());
wlanInfo.setConfiguration(configuration);
wlanInfo.setIsActive(configuration != null && configuration.networkId == connectionInfo.getNetworkId());
if (showUnknown || wlanInfo.isConfigured() || wlanInfo.isOpen()) {
infoList.add(wlanInfo);
}
}
}
catch (Exception e) { e.printStackTrace(); return null; }
return infoList;
}
changeableArrayAdapter.javaclass中的方法显示错误如下。它在哪里调用 getNewItems() 方法: ChangeableArrayAdapter.java:78 ChangeableArrayAdapter.java:74
public void triggerRefresh() {
AsyncTask<Void, Void, List<T>> asyncTask = new AsyncTask<Void, Void, List<T>>() {
@Override
protected List<T> doInBackground(Void... objects) {
return getNewItems();
//return null;
}
您需要添加 ACCESS_COARSE_LOCATION
或 ACCESS_FINE_LOCATION
作为 Android 清单文件的权限。
如果您只针对 API 22,那么您需要在 android 清单文件中添加这 2 权限
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
如果您的目标是 Android Marshmallow(Api 23 岁及以上),您需要在您的应用中授予运行时权限。
将这些添加到 AndroidManifest.xml
之前的 application
标签
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
同样对于Android版本>=23,您需要在run-time
中请求权限 if (ContextCompat.checkSelfPermission(YourActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&&
ContextCompat.checkSelfPermission(YourActivity.this,
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
askForLocationPermissions();
} else {
//do your work
}
和
private void askForLocationPermissions() {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
new android.support.v7.app.AlertDialog.Builder(this)
.setTitle("Location permessions needed")
.setMessage("you need to allow this permission!")
.setPositiveButton("Sure", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(YourActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
}
})
.setNegativeButton("Not now", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// //Do nothing
}
})
.show();
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
// MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
还有
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
switch (requestCode) {
case LOCATION_PERMISSION_REQUEST_CODE:
if (isPermissionGranted(permissions, grantResults, Manifest.permission.ACCESS_FINE_LOCATION)) {
//Do you work
} else {
Toast.makeText(this, "Can not proceed! i need permission" , Toast.LENGTH_SHORT).show();
}
break;
}
}
和
public static boolean isPermissionGranted(@NonNull String[] grantPermissions, @NonNull int[] grantResults,
@NonNull String permission) {
for (int i = 0; i < grantPermissions.length; i++) {
if (permission.equals(grantPermissions[i])) {
return grantResults[i] == PackageManager.PERMISSION_GRANTED;
}
}
return false;
}