Android 6.0 打开失败:EACCES(权限被拒绝)
Android 6.0 open failed: EACCES (Permission denied)
我添加了uses-permission
包括WRITE_EXTERNAL_STORAGE
,MOUNT_UNMOUNT_FILESYSTEMS
,READ_EXTERNAL_STORAGE
到AndroidManifest.xml
.
当我尝试 运行 我在 Nexus5 (Android 6.0) 中的应用程序时,它抛出了如下异常:
java.io.IOException: open failed: EACCES (Permission denied)
然后我尝试了另一个 Android phone(Android 5.1),一切都是 OK.Here 的代码:
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(imageFileName, ".jpg", storageDir);
currentPhotoPath = image.getAbsolutePath();
return image;
}
Android6.0在权限上有区别吗?
Android 为 Android 6.0 (Marshmallow).
添加了新的权限模型
所以你必须检查 Runtime Permission
:
什么是运行时权限?
在 Android 6.0 Marshmallow 中,Google 引入了一种新的权限模型,使用户可以更好地理解应用程序可能请求特定权限的原因。用户在安装时不再盲目地接受所有权限,而是在应用程序使用期间必要时提示用户接受权限。
何时实施新模型?
在您选择在您的应用程序中以版本 23 为目标之前,它不需要完全支持。如果您的目标版本为 22 或更低版本,您的应用程序将在安装时请求所有权限,就像在 Marshmallow 以下的任何设备 运行 和 OS 上一样。
此信息取自此处:
请检查link的实施方法:
在 Android 6(Marshmallow) 中,即使用户在安装时接受了您的所有权限,他们稍后也可以决定从你.
快速解决方案但不推荐: 也许如果您将 gradle 中的 targetSdkVersion
更改为 22
,问题就会解决.
如何实施?(最佳实践)
首先判断用户的设备是否为Marshmallow设备:
private boolean shouldAskPermission(){
return(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1);
}
如果shouldAskPermission()
return true
,请求您需要的权限:
String[] perms = {"android.permission.WRITE_EXTERNAL_STORAGE"};
int permsRequestCode = 200;
requestPermissions(perms, permsRequestCode);
方法 requestPermissions(String[] permissions, int requestCode);
是在 Android Activity class.
中找到的 public 方法
您将在方法 onRequestPermissionResult 中收到您的请求结果,如下所示:
@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
switch(permsRequestCode){
case 200:
boolean writeAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
break;
}
}
收到结果后,您需要妥善处理。
建议的权限流程:
更多信息:
拥有 Marshmallow 设备的用户现在可以通过应用程序设置撤销危险权限
Android 将某些权限定义为“危险”,将某些权限定义为“正常”。在您的应用程序的清单中两者都是必需的,但只有危险权限需要运行时请求。
如果您选择不实施新的权限模型(运行时请求),撤销权限可能会导致不良的用户体验,在某些情况下还会导致应用程序崩溃。
下面的table列出了所有当前的危险权限及其各自的组别:
如果用户在 group/category 中接受一项权限,他们将接受整个组!
来源:http://www.captechconsulting.com
使用 Dexter 库:
您可以使用 Dexter。 Android 简化运行时请求权限过程的库。
您也可以使用 ActivityCompat.requestPermissions 实现向后兼容。
示例:
private static final int REQUEST_CODE = 0x11;
String[] permissions = {"android.permission.WRITE_EXTERNAL_STORAGE"};
ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE); // without sdk version check
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// save file
} else {
Toast.makeText(getApplicationContext(), "PERMISSION_DENIED", Toast.LENGTH_SHORT).show();
}
}
}
从 API-23 开始,您需要在 activity 中声明权限,即使您已经在清单中声明过。
// Storage Permissions variables
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
//persmission method.
public static void verifyStoragePermissions(Activity activity) {
// Check if we have read or write permission
int writePermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int readPermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);
if (writePermission != PackageManager.PERMISSION_GRANTED || readPermission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
要使用,只需在 onCreate 中调用 verifyStoragePermissions(this);
。
这应该很有希望。
如果你很懒,就把targetSdkVersion降到22(棒棒糖之前)
这对我有用。
转到设置 -> 应用程序 -> YourApp -> 提供对存储、联系人等的权限
我遇到了同样的麻烦
可能是您的 phone 安全机制造成的。您可以前往 'settings' 授权 write/read 权限。
对我来说,我的 phone 连接为 USB 作为 MTP 是问题,即使在完成此处所述的所有操作后也是如此。将其切换为 "Charging Only" 对我有用。
Google 在 Android Q 上有一个新功能:外部存储的过滤视图。一个快速解决方法是在 AndroidManifest.xml 文件中添加此代码:
<manifest ... >
<!-- This attribute is "false" by default on apps targeting Android Q. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
您可以在此处阅读更多相关信息:https://developer.android.com/training/data-storage/compatibility
我添加了uses-permission
包括WRITE_EXTERNAL_STORAGE
,MOUNT_UNMOUNT_FILESYSTEMS
,READ_EXTERNAL_STORAGE
到AndroidManifest.xml
.
当我尝试 运行 我在 Nexus5 (Android 6.0) 中的应用程序时,它抛出了如下异常:
java.io.IOException: open failed: EACCES (Permission denied)
然后我尝试了另一个 Android phone(Android 5.1),一切都是 OK.Here 的代码:
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(imageFileName, ".jpg", storageDir);
currentPhotoPath = image.getAbsolutePath();
return image;
}
Android6.0在权限上有区别吗?
Android 为 Android 6.0 (Marshmallow).
添加了新的权限模型所以你必须检查 Runtime Permission
:
什么是运行时权限?
在 Android 6.0 Marshmallow 中,Google 引入了一种新的权限模型,使用户可以更好地理解应用程序可能请求特定权限的原因。用户在安装时不再盲目地接受所有权限,而是在应用程序使用期间必要时提示用户接受权限。
何时实施新模型?
在您选择在您的应用程序中以版本 23 为目标之前,它不需要完全支持。如果您的目标版本为 22 或更低版本,您的应用程序将在安装时请求所有权限,就像在 Marshmallow 以下的任何设备 运行 和 OS 上一样。
此信息取自此处:
请检查link的实施方法:
在 Android 6(Marshmallow) 中,即使用户在安装时接受了您的所有权限,他们稍后也可以决定从你.
快速解决方案但不推荐: 也许如果您将 gradle 中的 targetSdkVersion
更改为 22
,问题就会解决.
如何实施?(最佳实践)
首先判断用户的设备是否为Marshmallow设备:
private boolean shouldAskPermission(){ return(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1); }
如果
shouldAskPermission()
returntrue
,请求您需要的权限:String[] perms = {"android.permission.WRITE_EXTERNAL_STORAGE"}; int permsRequestCode = 200; requestPermissions(perms, permsRequestCode);
方法 requestPermissions(String[] permissions, int requestCode);
是在 Android Activity class.
您将在方法 onRequestPermissionResult 中收到您的请求结果,如下所示:
@Override public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){ switch(permsRequestCode){ case 200: boolean writeAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED; break; } }
收到结果后,您需要妥善处理。
建议的权限流程:
更多信息:
拥有 Marshmallow 设备的用户现在可以通过应用程序设置撤销危险权限
Android 将某些权限定义为“危险”,将某些权限定义为“正常”。在您的应用程序的清单中两者都是必需的,但只有危险权限需要运行时请求。
如果您选择不实施新的权限模型(运行时请求),撤销权限可能会导致不良的用户体验,在某些情况下还会导致应用程序崩溃。
下面的table列出了所有当前的危险权限及其各自的组别:
如果用户在 group/category 中接受一项权限,他们将接受整个组!
来源:http://www.captechconsulting.com
使用 Dexter 库:
您可以使用 Dexter。 Android 简化运行时请求权限过程的库。
您也可以使用 ActivityCompat.requestPermissions 实现向后兼容。
示例:
private static final int REQUEST_CODE = 0x11;
String[] permissions = {"android.permission.WRITE_EXTERNAL_STORAGE"};
ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE); // without sdk version check
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// save file
} else {
Toast.makeText(getApplicationContext(), "PERMISSION_DENIED", Toast.LENGTH_SHORT).show();
}
}
}
从 API-23 开始,您需要在 activity 中声明权限,即使您已经在清单中声明过。
// Storage Permissions variables
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
//persmission method.
public static void verifyStoragePermissions(Activity activity) {
// Check if we have read or write permission
int writePermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int readPermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);
if (writePermission != PackageManager.PERMISSION_GRANTED || readPermission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
要使用,只需在 onCreate 中调用 verifyStoragePermissions(this);
。
这应该很有希望。
如果你很懒,就把targetSdkVersion降到22(棒棒糖之前)
这对我有用。
转到设置 -> 应用程序 -> YourApp -> 提供对存储、联系人等的权限
我遇到了同样的麻烦
可能是您的 phone 安全机制造成的。您可以前往 'settings' 授权 write/read 权限。
对我来说,我的 phone 连接为 USB 作为 MTP 是问题,即使在完成此处所述的所有操作后也是如此。将其切换为 "Charging Only" 对我有用。
Google 在 Android Q 上有一个新功能:外部存储的过滤视图。一个快速解决方法是在 AndroidManifest.xml 文件中添加此代码:
<manifest ... >
<!-- This attribute is "false" by default on apps targeting Android Q. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
您可以在此处阅读更多相关信息:https://developer.android.com/training/data-storage/compatibility