簡體   English   中英

對 Android 10 上的外部文件的訪問權限被拒絕

[英]Access permission denied to external file on Android 10

我的應用是 targetSdkVersion = 29

我拍了一張照片並保存在路徑中:

src = /storage/emulated/0/DCIM/Camera/IMG_20201120_091943.jpg

然后我想使用 FileInputStream/FileOutputStream 將此圖像復制到內部存儲。 雖然,我的應用程序具有 WRITE/READ 存儲權限,但是當我編碼時

InputStream inputStream = FileInputStream(src)

我收到一個 FileNotFoundException(打開失敗:EACCES 權限被拒絕)。

有人有同樣的問題嗎?

注意:我不想通過使用選項 AndroidManifest.xml 來解決這個問題,因為它是臨時的

android:requestLegacyExternalStorage="true"

當您的targetSdkVersion >= 29您必須使用 ScopedStorage,請參閱文檔: https : //developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage

所以簡短的回答是你不能真正做到這一點。 如果您的 targetSdkVersion 是 29,您應該使用 MediaStore API 來寫入共享存儲(“/storage/emulated/0/DCIM/Camera/IMG_20201120_091943.jpg”不是您的應用的私有,因此規則適用)

以下是如何使用 MediaStoreApi 將圖像插入到用戶的圖像中: https : //stackoverflow.com/a/56990305/5601663

此外,如果您真的只想保存文件,以便它僅在您的應用程序中可用,那么您不需要使用 MediaStoreApi,請參閱有關如何將文件保存在您的應用程序私有目錄中的文章: https://medium。 com/@maksymilian.wojcik/android-saving-files-in-internal-storage-image-from-byte-array-etc-dd7d1b86d309

編輯:您當然可以在清單上使用requestLegacyExternalStorage標志,但您已經說過不想使用它

Edit2:我現在看到您想從共享存儲中讀取數據。 這也行不通,因為如果您的targetSdkVersion >= 29 ,您需要使用存儲訪問框架或媒體存儲從那里讀取。 因此,對於這種情況,請按照此處描述的說明進行操作: https : //developer.android.com/training/data-storage/use-cases#import-image-media

我使用 FileInputStream/FileOutputStream 詳細顯示我的代碼

src = /storage/emulated/0/DCIM/Camera/IMG_20201120_091943.jpg

dst = /storage/emulated/0/Android/data/my_app/files/Pictures/IMG_20201118_113434.jpg

src 是保存照片的地方,dst 是我想將文件 src 復制到這里的地方

public void copy(String src, String dst) {
        try {
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(src));
            OutputStream outPutStream = new FileOutputStream(dst);
            int len;
            byte[] buf = new byte[1024];
            while ((len = bufferedInputStream.read(buf)) > 0) {
                outPutStream.write(buf, 0, len);
            }

            outPutStream.flush();
            outPutStream.close();
            bufferedInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

FileNotFoundException(打開失敗:EACCES 權限被拒絕)在行:

BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(src));

在 Android 10 上,您無法使用 File API 訪問共享存儲中的文件,不幸的是,Android 文檔對此不一致,您可以在這里找到它想

要解決此問題,請在 Android 10 上使用 Uri API,盡管這在 Android 11 中不是問題

val uri = ContentUris.withAppendedId(MediaStore.Image.Media.EXTERNAL_CONTENT_URI, id)

applicationContext.contentResolver.openInputStream(uri).use { stream ->
   // do your thing here
}

注意:您仍然可以對您的應用擁有的任何文件使用 File API

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM