标签: storage-access-framework

Android - 如何使用新的存储访问框架将文件复制到外部SD卡

我正在我的应用程序中实现文件浏览器功能.我知道如何使用ACTION_OPEN_DOCUMENT_TREE意图获得外部SD卡的持久权限,以及如何使用DocumentFile类创建文件夹和删除文件/文件夹.

但是,我找不到将文件复制/移动到外部SD卡文件夹的方法.你能指出我正确的方向吗?

android android-external-storage storage-access-framework

4
推荐指数
1
解决办法
3198
查看次数

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

>> 背景

我想使用 SAF(存储访问框架字)将我的应用程序的数据文件保存到用户在存储介质上所需的位置。我首先在应用程序专用文件夹中创建文件,然后将其复制到用户从文件选择器对话框中选择的文件(代码稍后发布)。

此过程适用于新文件但对于现有文件,尽管文件选择器会警告覆盖文件,但在写入之前不会删除最终文件。

通过计算写入的字节数并使用十六进制编辑器调查文件,代码将正确的字节写入输出流,但是:如果现有文件的字节数多于要写入的字节数,则最终覆盖的文件已损坏(实际上并未损坏,请参阅下一节进行澄清),如果现有的字节数少于要写入的字节数,则最终覆盖的文件是正确的。

>> 更多细节和代码

我使用下面的代码来显示问题(jpg 为示例):我将尝试使用两个文件:

file1.jpg 166,907 bytes
file2.jpg 1,323,647 bytes
file3.jpg The final file with variable size
Run Code Online (Sandbox Code Playgroud)

首先,我将把 file1 复制到用户选择的名为 file3 的文件夹(目标文件),然后用 file2 覆盖它,最后我将用 file1 再次覆盖它。看看代码是什么以及会发生什么:

调用文件选择器的代码:

val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
    addCategory(Intent.CATEGORY_OPENABLE)
    type = "image/jpeg"
}
startActivityForResult(intent, request)
Run Code Online (Sandbox Code Playgroud)

现在在 onActivityResult() 我处理数据如下:

contentResolver.openOutputStream(fileUri)?.use {output->
        val input = FileInputStream(File(getExternalFilesDir(null),"Pictures/file1.jpg"))
    // file1.jpg for first run, file2.jpg for 2nd run and file1.jpg again for 3rd run     
        copyStream(input, output)

    }
Run Code Online (Sandbox Code Playgroud)

以及复制流的代码:

@Throws(IOException::class)
fun copyStream(input: InputStream, output: …
Run Code Online (Sandbox Code Playgroud)

android overwrite fileoutputstream storage-access-framework

4
推荐指数
2
解决办法
1655
查看次数

Permission error when trying to open folder after restart in Android app

I have a preferences page in my app that asks the user for a place to save a file. This place is returned as a URI using Storage Access Framework and I'm able to use it to store files between activites. The problem is that after I restart the phone, I retrieve the URI from the sharedPreferences, and I receive this:

DocumentFile: Failed query: java.lang.SecurityException: Permission Denial: opening provider com.android.externalstorage.ExternalStorageProvider from ProcessRecord (pid=23302, uid=10334) requires that you obtain access using …
Run Code Online (Sandbox Code Playgroud)

android android-intent android-activity kotlin storage-access-framework

4
推荐指数
2
解决办法
740
查看次数

Android - 存储访问框架 - Uri 到本地文件

我正在Storage Access Framework(SAF)我的应用程序中使用。为了扫描文件(照片或文档),我需要通过 API 发送本地文件路径。我已经成功地正确设置了SAF,现在当用户选择一个文件时,我得到了一个应该的 Uri。

看来 Uri 是云的密钥,而不是本地文件。

Uri 值如下所示:

content://com.android.providers.media.documents/document/image:11862 
Run Code Online (Sandbox Code Playgroud)

如何将此 Uri 转换为本地文件?我应该从云端下载文件吗?我该怎么做?

java android storage-access-framework

3
推荐指数
1
解决办法
3458
查看次数

将文件路径转换为 ​​TreeUri(存储访问框架)

在我的图库应用程序中,我使用媒体内容提供程序图像来扩充回收器视图。长按图像时,我会为用户提供重命名该图像文件的选项。所以我在回收站视图中为每个图像都有完整的文件路径(例如:- /storage/sdcard1/DCIM/100ANDRO/ak.jpg )。然后我想重命名该文件。

现在的问题是,由于提供的文件路径是外部 SD 卡的路径,对于 Android 5 及更高版本,需要 SAF(存储访问框架)来写入文件。

所以通常我们使用此代码使用 SAF 重命名文件:-

public void onActivityResult(int requestCode, int resultCode, Intent resultData){
    if (resultCode == RESULT_OK) {
        Uri treeUri = resultData.getData();
        getContentResolver().takePersistableUriPermission(treeUri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION |
                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
        DocumentFile newFIle = pickedDir.createFile("text/plain","MyFile")
        // or rename as
        pickedDir.renameTo("fdtd.jpg");
    } else {
        Log.d("test","NOt OK RESULT");
    }
}
Run Code Online (Sandbox Code Playgroud)

但是当我们知道 TreeUri 时就是这种情况。在我的情况下,我知道文件路径,因此想将其转换为 TreeUri。

android filewriter android-sdcard storage-access-framework

3
推荐指数
1
解决办法
3028
查看次数

SAF DocumentFile-检查路径是否存在,而不在每个文件夹级别创建每个DocumentFile

成像,您要检查是否存在“ /folder/subfolder/subsubfolder/test/test.txt”文件,请执行以下操作:

DocumentFile sdCard = ...; // i have already retrieved the sd card root with the users help via SAF

String path = "<SD CARD>/folder/subfolder/subsubfolder/test/test.txt";
List<String> pathParts = Arrays.asList(path.split("/"));
DocumentFile doc = sdCard;
// go through all folders, starting at sd card, to check, if the desired file exists
for (int i = 1; i < pathParts.size(); i++)
{
    DocumentFile nextDoc = doc.findFile(pathParts.get(i));
    if (nextDoc != null)
        doc = nextDoc;
    else
    {
        doc = null;
        break;
    }
}

if …
Run Code Online (Sandbox Code Playgroud)

android storage-access-framework documentfile

3
推荐指数
1
解决办法
1354
查看次数

Scoped Storage - 下载文件夹访问

我的目标是 android 10,我不使用android:requestLegacyExternalStorage. 我用的是DownloadManager通过下载到下载文件夹:request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)。我收听下载完整广播,提取 uri ( file:///storage/emulated/0/Download/<name>.pdf) 并通过 .pdf 文件在 pdf 阅读器中打开它FileProvider。它有效......为什么?自 android 10 和范围存储以来,它不应该不起作用吗?为什么我可以访问下载文件夹中的文件?

编辑:Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).listFiles()列出所有文件,尽管文档说:

为了提高用户隐私,不推荐直接访问共享/外部存储设备。当应用以 Q 为目标时,此方法返回的路径不再可供应用直接访问

android android-download-manager storage-access-framework android-10.0 scoped-storage

3
推荐指数
1
解决办法
2433
查看次数

SAF - ACTION_CREATE_DOCUMENT - 将文件保存到 Drive 后,文件为空

我是 SAF 的初学者。我想要做的是保存配置超级简单。假设文件是​​ .conf。

我将 .conf 复制到 conf.txt 并将其保存在 Drive 上。

这是我的代码:

            tools.deleteFile(dst);   // delete conf.txt if it exists
            int res = tools.copyFile(src,dst); // copy .conf to conf.txt
            if(res == -1) return;

            tools.viewFile(dst);  
// verify in Log info that the content of cnf.txt is correct

            Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);

            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("text/plain");
            intent.putExtra(Intent.EXTRA_TITLE, dst);
            startActivity(intent);
Run Code Online (Sandbox Code Playgroud)

我在云端硬盘中保存。该文件出现在我的电脑上,但当我打开它时,它是空的。

当我做相反的事情时:ACTION_OPEN_DOCUMENT

   public void onActivityResult(int requestCode, int resultCode,
                                 Intent resultData) {
    Uri uri;

    if (resultCode == Activity.RESULT_OK){
         if (requestCode == 30){
            if (resultData != null) …
Run Code Online (Sandbox Code Playgroud)

android storage-access-framework

2
推荐指数
1
解决办法
1762
查看次数

Android 无法对 SD 卡进行写入和删除操作

我现在正在研究 ImageCompressor 应用程序。

我需要deletewrite(更新)图像文件。在内部存储中完美运行,但 **SD​​ 卡无法让我访问删除和写入文件。

我的应用程序如何能够在 SD 卡writedelete(可移动存储)执行操作

我已经完成了没有这个的整个项目,所以我必须找到一种方法。

更新:

我已经在研究和讨论这个问题。并了解我必须使用storage access framework但我是 SAF 的新手。

我使用了一个来压缩需要File 而不是 Uri 的照片。为此,我Uri -> File使用Intent.ACTION_OPEN_DOCUMENT并从可移动存储中选择图像。

但是对于可移动存储,我无法从 uri 中找到 Image Real Path。

我不知道这是否正确。如果在 SAF 中有任何方法可以使用 uri 压缩我的图像,请告诉我。或如何从可移动存储照片的uri 获取图像真实路径

更新代码 SAF:

//  -----------  Intent  -------------
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");

//  ------------  On …
Run Code Online (Sandbox Code Playgroud)

java permissions android file-permissions storage-access-framework

2
推荐指数
1
解决办法
610
查看次数

如何使用 android 存储访问框架附加到文件?

如何使用存储访问框架获取 FileOutputStream 以附加到文件?以下代码覆盖该文件

void write(Uri uri){
        try {
            ParcelFileDescriptor descriptor=getContentResolver().openFileDescriptor(uri,"w");
            if(descriptor!=null) {
                FileOutputStream op=new FileOutputStream(descriptor.getFileDescriptor());
                op.write("test string".getBytes());
                op.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
Run Code Online (Sandbox Code Playgroud)

我知道使用 java.io.File 来做到这一点FileOutputStream(File file,boolean append)

但我看不到FileOutputStream(FileDescriptor fd,boolean append)

android storage-access-framework

2
推荐指数
1
解决办法
1352
查看次数

Android - 使用 Intent 打开音频内容 uri

我有一个应用程序,可以让用户制作从设备中选择的歌曲列表。然后,他们可以选择要播放的歌曲,应用程序将使用 Intent 打开歌曲的 uri,以便使用默认音乐播放器实际播放歌曲。

\n\n

如果我使用 Astro 文件管理器选择歌曲,则效果很好,但如果我通过 google Drive、音频部分或下载部分选择文件,则该歌曲将无法播放。

\n\n

我正在选择具有如下意图的文件:

\n\n
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);\nintent.setType("audio/*");\nintent = Intent.createChooser(intent, "Select audio or music");\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后使用 检索 Uri data.getData()

\n\n

稍后使用如下意图打开 Uri Im:

\n\n
Intent intent = new Intent(Intent.ACTION_VIEW, uri);\ncontext.startActivity(intent);\n
Run Code Online (Sandbox Code Playgroud)\n\n

Astro 文件管理器以表单返回 Uris file:///storage/sdcard0/Download/My%20Song.mp3,这些文件可以使用默认媒体应用程序打开并正常播放。

\n\n

Google 云端硬盘以 形式返回 Uris content://com.google.android.apps.docs.storage/document/acc%3D1%3Bdoc%3D421。\n当我尝试使用默认媒体应用程序通过 Intent 打开这样的 Uris 时,它会显示一个弹出窗口“无法播放您请求的曲目”。

\n\n

如何打开 Google Drive 使用该媒体类型的默认应用程序返回的内容 Uri?

\n\n

编辑:我还尝试在使用 Intent 打开 uri 时显式设置 mime 类型:

\n\n
Intent intent = new Intent(Intent.ACTION_VIEW, audio.getAudioUri());\nintent.setType("audio/*");\ncontentController.startActivity(intent);\n …
Run Code Online (Sandbox Code Playgroud)

audio android android-intent storage-access-framework

0
推荐指数
1
解决办法
4743
查看次数