簡體   English   中英

Android 13 - 如何請求 WRITE_EXTERNAL_STORAGE

[英]Android 13 - How to request WRITE_EXTERNAL_STORAGE

我將我的 Android 應用程序定位為 Android 13 (API 33)

WRITE_EXTERNAL_STORAGE 權限似乎在 API 33 以下正常工作,即 Android 12 及以下,但在 Android 13 上運行應用程序時不會出現 WRITE_EXTERNAL_STORAGE 的運行時權限彈出窗口。

我的 Android 應用程序在應用程序的私有存儲中創建了一個密鑰庫文件。

Android 13 的行為更改提到了這一點:

如果您的應用面向 Android 13,則您必須請求一項或多項新權限,而不是 READ_EXTERNAL_STORAGE。

新的權限是:

  • 圖片和照片:READ_MEDIA_IMAGES
  • 視頻:READ_MEDIA_VIDEO 音頻
  • 音頻文件:READ_MEDIA_AUDIO

我沒有在官方文檔中找到有關此的任何信息。 該文檔僅關注媒體文件,沒有提及其他文件類型。

https://developer.android.com/about/versions/13/behavior-changes-13#granular-media-permissions

TLDR:你沒有。

來自谷歌的官方文檔

“如果您的應用以 Android 11 為目標平台,則 WRITE_EXTERNAL_STORAGE 權限和 WRITE_MEDIA_STORAGE 特權權限都不再提供任何額外的訪問權限。”

因此,實際上,如果您要在 Android 11 或更高版本上請求 WRITE_EXTERNAL_STORAGE,您將不會請求任何內容。 這是 Android 遷移到分區存儲的全部要點,它有效地防止應用程序讀取或寫入其他應用程序的存儲目錄,除非它們正在訪問特定文件類型(例如媒體,使用您提到的權限)或被授予特殊文件管理器谷歌自己的權限。 要更深入地了解分區存儲,請參閱這篇寫得很好的文章,但 TLDR 安全性和應用程序卸載留下的文件是谷歌這樣做的主要原因。

所以如果你真的想寫文件,要么確保你只寫你的應用程序指定的存儲目錄,在這種情況下你根本不需要任何權限,或者如果你真的需要寫一個你的應用程序不需要的目錄'own get that file manager permission from Google( 如何獲得那個權限

您可以在Android 官方文檔或“ 如何在 Android 13 中的共享存儲位置保存文件”找到訪問非媒體文件的文檔。 從 Android 10 開始,如果你想寫一個可以被其他應用程序(比如文件管理器)或用戶直接訪問的文件,那么你必須把它寫到共享存儲位置。 這必須分 3 個步驟完成:

第 1 步:啟動系統選擇器以由用戶選擇目的地。 這將返回目標目錄的 Uri。

private ActivityResultLauncher<Intent> launcher; // Initialise this object in Activity.onCreate()
private Uri baseDocumentTreeUri;
public void launchBaseDirectoryPicker() {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
        launcher.launch(intent);
 }

第 2 步:啟動 System Picker 以由用戶選擇目的地。 這將返回目標目錄的 Uri。 此外,您可以選擇保留權限和 Uri 以供將來使用。

@Override
    public void onActivityResult(ActivityResult result) {
        if (result.getResultCode() == Activity.RESULT_OK) {
            baseDocumentTreeUri = Objects.requireNonNull(result.getData()).getData();
            final int takeFlags = (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

            // take persistable Uri Permission for future use
            context.getContentResolver().takePersistableUriPermission(result.getData().getData(), takeFlags);
            SharedPreferences preferences = context.getSharedPreferences("com.example.fileutility", Context.MODE_PRIVATE);
            preferences.edit().putString("filestorageuri", result.getData().getData().toString()).apply();
        } else {
            Log.e("FileUtility", "Some Error Occurred : " + result);
        }
}

第三步:將內容寫入文件。

public void writeFile(String fileName, String content)  {
        try {
            DocumentFile directory = DocumentFile.fromTreeUri(context, baseDocumentTreeUri);
            DocumentFile file = directory.createFile("text/*", fileName);
            ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(file.getUri(), "w");
            FileOutputStream fos = new FileOutputStream(pfd.getFileDescriptor());
            fos.write(content.getBytes());
            fos.close();
        } catch (IOException e) {
            
        }
}

暫無
暫無

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

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