[Android]将应用程序特定文件夹中的文件复制到您的“下载”文件夹。

この記事は約7分で読めます。
スポンサーリンク

我想做的事情

Android 应用的唯一文件夹(\Android\data\包名)中创建的文件将被复制到用户的下载文件夹。

在现代安卓开发中, java.io.文件 使用这种方式旅行已经变得困难。. Android 10(API 29)及更高版本引入作用域存储 因此,对外部存储设备的访问权限变得更加严格。

本文讨论的是安卓应用的隐私区域。/date/date/... 或者 /Android/data/.../files)从,写入外部存储 无需太多权威一个用于共享文件的安全区域(下载这解释了如何将其移动到)。

背景

在之前的安卓版本中,应用曾经是 写入外部存储 一旦我获得了必要的权限,我就可以向外部存储设备上的几乎任何位置写入文件。

然而,随着作用域存储的引入,每个应用都可以使用自己的私有空间。媒体商店 由以下机构管理的特定共享集合:图片下载访问权限仅限于(等等)。

换句话说,应用程序不能再随意将文件放置在其他应用程序的文件夹中或共享存储上的任意位置。

这是将文件从私有区域移动到用户共享区域的简单方法。. 文件.重命名为() 或者 文件.复制() 这就是它不能使用的主要原因。

你打算用它来做什么?

在处理过程中,文件在私有文件夹中进行处理;处理完成后,文件将被移动到用户可以访问的文件夹(用于下载等)。

将私人文件夹中的文件移动到用户可访问的文件夹(进行归档)以进行备份。

スポンサーリンク

执行

具体操作如下:

(这是作为 Activity 的一个方法实现的。)

import android.provider.MediaStore;
import android.content.ContentValues; 
import android.os.Environment;

    public void moveFileToDownloads( Path privatePath) {
        File privateFile = privatePath.toFile();
        ContentValues values = new ContentValues();
        values.put(MediaStore.MediaColumns.DISPLAY_NAME, privateFile.getName());
        values.put(MediaStore.MediaColumns.MIME_TYPE, "application/zip");

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + File.separator + APPNAME);
        }

        ContentResolver resolver = this.getContentResolver();
        Uri uri = null;

        try {
            uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values);
            if (uri == null) {
                throw new RuntimeException("MediaStore insert failed.");
            }

            try (OutputStream os = resolver.openOutputStream(uri);
                 FileInputStream is = new FileInputStream(privateFile)) {
                if (os == null) {
                    throw new RuntimeException("Failed to open output stream.");
                }

                byte[] buffer = new byte[4096];
                int length;
                while ((length = is.read(buffer)) > 0) {
                    os.write(buffer, 0, length);
                }

                privateFile.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (uri != null) {
                resolver.delete(uri, null, null);
            }
        }
    }

参数 `privatePath` 是要移动到 Downloads 文件夹的文件的路径。

如果您将文件路径存储为字符串,则可以使用 `Path path = Paths.get(pathString);` 进行转换。

代码说明

        ContentValues values = new ContentValues();
        values.put(MediaStore.MediaColumns.DISPLAY_NAME, privateFile.getName());
        values.put(MediaStore.MediaColumns.MIME_TYPE, "application/zip");

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + File.separator + APPNAME);
        }

正在创建内容值(有关已保存文件的信息)。请根据需要更改 MIME_TYPE。

`values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + File.separator + APPNAME);` 中的 `APPNAME` 部分是要在下载文件夹中创建的文件夹的名称。如果您直接保存到下载文件夹,则使用 `Environment.DIRECTORY_DOWNLOADS` 即可。

        ContentResolver resolver = this.getContentResolver();
        Uri uri = null;

        try {
            uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values);
            if (uri == null) {
                throw new RuntimeException("MediaStore insert failed.");
            }

创建解析器并获取 URI(保存路径)。

                byte[] buffer = new byte[4096];
                int length;
                while ((length = is.read(buffer)) > 0) {
                    os.write(buffer, 0, length);
                }

                privateFile.delete();

这段代码会复制文件内容并删除原文件。如果您只是复制文件而不是移动文件,请不要调用 `privateFile.delete();`。

        } catch (Exception e) {
            e.printStackTrace();
            if (uri != null) {
                resolver.delete(uri, null, null);
            }
        }

这是错误处理。`resolver.delete(uri, null, null);` 会删除下载文件夹中失败的文件。

コメント

タイトルとURLをコピーしました