使用 SAF(存储访问框架)的 Android SD 卡写入权限

Posted

技术标签:

【中文标题】使用 SAF(存储访问框架)的 Android SD 卡写入权限【英文标题】:Android SD Card Write Permission using SAF (Storage Access Framework) 【发布时间】:2016-08-20 03:34:10 【问题描述】:

经过大量关于如何在 SD 卡(android 5 及更高版本)中写入(和重命名)文件的发现后,我认为 android 提供的新 SAF 将需要获得用户的权限才能写入 SD 卡文件。

我在这个文件管理器应用程序ES文件资源管理器中看到,最初它通过以下方式获取读写权限,如图所示。

选择sd卡后,授予写权限。

因此,我以同样的方式尝试使用 SAF,但重命名文件失败。我的代码:

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    rename = (Button) findViewById(R.id.rename);

    startActivityForResult(new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), 42);


@Override
public void onActivityResult(int requestCode,int resultCode,Intent resultData) 
    if (resultCode != RESULT_OK)
        return;
    Uri treeUri = resultData.getData();
    DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
    grantUriPermission(getPackageName(), treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);


public void renameclick(View v) 
    File ff = new File("/storage/sdcard1/try1.jpg");
    try 
        ff.createNewFile();
     catch (Exception e) 
        Log.d("error", "creating");
        e.printStackTrace();
    

在运行代码后,我仍然获得 EAacces 权限被拒绝。

【问题讨论】:

【参考方案1】:

让用户选择“SD 卡”甚至“内部存储”SAF root 让您的应用程序可以访问相应的存储,但只能通过 SAF API,而不是直接通过文件系统。例如,您的代码可以翻译成类似:

public void writeFile(DocumentFile pickedDir) 
    try 
        DocumentFile file = pickedDir.createFile("image/jpeg", "try2.jpg");
        OutputStream out = getContentResolver().openOutputStream(file.getUri());
        try 

            // write the image content

         finally 
            out.close();
        

     catch (IOException e) 
        throw new RuntimeException("Something went wrong : " + e.getMessage(), e);
    

在最新版本的 Android 中,使用 java.io.File 访问应用程序外部的数据几乎已被完全弃用。

【讨论】:

但是每当我需要创建或重命名文件时,SAF 选择器就会打开 一旦有了树 URI,就可以对它包含的文件和目录做任何你想做的事情。如果 1)您使用 takePersistableUriPermission() 和 2)您将 URI 存储在某处,则您不需要每次都询问用户,以便您可以在应用程序启动时检索它 createFile 只获得MimeType 和名称作为参数时,我们怎么能访问pickedDir 的子目录。我们如何将java.io.file 类路径转换为DocumentFile @Eftekhari 你可以这样做:DocumentFile pickedTree = DocumentFile.fromFile(App.getContext(), uriTree); for (DocumentFile file : pickedTree.listFiles()) if (file.isDirectory()) file.createFile(mimeType, fileName); 如何写入 SD 卡中某个子目录中的文件。

以上是关于使用 SAF(存储访问框架)的 Android SD 卡写入权限的主要内容,如果未能解决你的问题,请参考以下文章

Android SAF(存储访问框架):从 TreeUri 获取特定文件 Uri

SAF(存储访问框架)是不是解决了 Android 4.4(KitKat)中的 SD 卡 WRITE 问题?

额外启用带有存储访问框架 (SAF) 的显示/隐藏 SD 卡

在 Android 中从 File Api 迁移到 Storage Access Framework (SAF)

如何使用android存储访问框架正确覆盖文件内容

SAF(Storage Access Framework)使用攻略