繁体   English   中英

Android 6.0 打开失败:EACCES(权限被拒绝)

[英]Android 6.0 open failed: EACCES (Permission denied)

我添加了uses-permission包括WRITE_EXTERNAL_STORAGEMOUNT_UNMOUNT_FILESYSTEMSREAD_EXTERNAL_STORAGEAndroidManifest.xml

当我尝试在 Nexus5 (Android 6.0) 中运行我的应用程序时,它抛出了如下异常:

java.io.IOException: open failed: EACCES (Permission denied)

我尝试了另一部 Android 手机(Android 5.1),一切正常。代码如下:

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

Android 6.0 在权限上有区别吗?

Android 为Android 6.0 (Marshmallow)添加了新的权限模型。

http://www.captechconsulting.com/blogs/runtime-permissions-best-practices-and-how-to-gracefully-handle-permission-removal

所以你必须检查Runtime Permission

什么是运行时权限?

在 Android 6.0 Marshmallow 中,Google 引入了一种新的权限模型,使用户能够更好地了解应用程序可能会请求特定权限的原因。 与用户在安装时盲目地接受所有权限不同,现在会提示用户接受在应用程序使用过程中变得必要的权限。

何时实施新模式?

在您选择在应用程序中定位到版本 23 之前,它不需要完全支持。 如果您的目标是版本 22 或更低版本,您的应用程序将在安装时请求所有权限,就像在运行 Marshmallow 以下操作系统的任何设备上一样。

此信息取自此处:

请检查如何从此链接实施:

http://www.captechconsulting.com/blogs/runtime-permissions-best-practices-and-how-to-gracefully-handle-permission-removal

Android 6(Marshmallow) 中,即使用户在安装时接受了您的所有权限,他们也可以稍后决定从您那里拿走其中的一些权限。

快速解决方案但不推荐:也许如果您将targetSdkVersion中的 targetSdkVersion 更改为22 ,问题就会解决。

如何实施?(最佳实践)

  1. 首先判断用户的设备是否是 Marshmallow 设备:

     private boolean shouldAskPermission(){ return(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1); }
  2. 如果shouldAskPermission()返回true ,则请求您需要的权限:

     String[] perms = {"android.permission.WRITE_EXTERNAL_STORAGE"}; int permsRequestCode = 200; requestPermissions(perms, permsRequestCode);

方法requestPermissions(String[] permissions, int requestCode); 是在 Android Activity 类中找到的公共方法。

  1. 您将在方法 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 将一些权限定义为“危险”,将一些权限定义为“正常” 您的应用程序清单中都需要两者,但只有危险权限需要运行时请求。

如果您选择不实施新的权限模型(运行时请求),权限的撤销可能会导致不必要的用户体验,并且在某些情况下会导致应用程序崩溃。

下表列出了所有当前的危险权限及其各自的组:

在此处输入图片说明

如果用户接受一个组/类别中的一个权限,则他们接受整个组!

资料来源: http : //www.captechconsulting.com

使用德克斯特库:

您可以使用德克斯特 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 开始,即使您已经在清单中声明,您也需要在活动中声明权限。

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

使用只需调用verifyStoragePermissions(this); 在 onCreate 中。 那应该有希望。

如果你懒惰,只需将 targetSdkVersion 降级到 22(棒棒糖之前)

这对我有用。

转到设置 -> 应用程序 -> YourApp -> 提供对存储、联系人等的权限。

谷歌在 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

对我来说,即使完成了此处所述的所有操作,我的手机仍以 USB 作为 MTP 连接,这仍然是问题。 将其切换为“仅充电”对我有用。

我遇到了同样的麻烦。

可能是你的手机安全机制造成的。 您可以转到“设置”来授权写/读权限。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM