簡體   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