使用 MediaStore 在 Android Q 中创建/复制文件

2023-12-14

我正在尝试找到一种方法,可以处理除媒体文件(图片/视频/音频)之外的任何文件的创建和复制,以便从 Android Q 内部存储中的一个位置复制到另一个位置。在此,我在应用程序文件夹中创建了我的文件我希望将它们移动到下载文件夹或我可以在内部存储中创建的某个目录,然后移动它们。

我搜索并发现修改了下面的代码,但缺少一些使其可行的东西。有人可以帮忙吗?

ContentResolver contentResolver = getContentResolver();

ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "sam.txt");
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "text/plain");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);

Uri uri = contentResolver.insert(MediaStore.Files.getContentUri("external"), contentValues);

try {
    InputStream inputStream = contentResolver.openInputStream(uri);
    OutputStream outputStream = new FileOutputStream(Environment.DIRECTORY_DOWNLOADS+"/");

    byte[] buffer = new byte[1024];

    int length;

    //copy the file content in bytes
    while ((length = inputStream.read(buffer)) > 0) {
            outputStream.write(buffer, 0, length);
        }
        inputStream.close();
        outputStream.close();
        } catch (Exception e) {
           e.printStackTrace();
        }

上面是完整的代码,因为我收到错误“未知 URL”。缺什么?请帮忙。


NOTE:如果您重新安装该应用程序,MediaStore将不再识别之前创建的文件:应用重新安装后,Android 11 无法检索使用 MediaStore 创建的文件, using Intent让用户选择文件是唯一的解决方案。


1. 创建并写入文件

createAndWriteButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        try {
            ContentValues values = new ContentValues();

            values.put(MediaStore.MediaColumns.DISPLAY_NAME, "menuCategory");       //file name                     
            values.put(MediaStore.MediaColumns.MIME_TYPE, "text/plain");        //file extension, will automatically add to file
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOCUMENTS + "/Kamen Rider Decade/");     //end "/" is not mandatory

            Uri uri = getContentResolver().insert(MediaStore.Files.getContentUri("external"), values);      //important!

            OutputStream outputStream = getContentResolver().openOutputStream(uri);

            outputStream.write("This is menu category data.".getBytes());

            outputStream.close();

            Toast.makeText(view.getContext(), "File created successfully", Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            Toast.makeText(view.getContext(), "Fail to create file", Toast.LENGTH_SHORT).show();
        }
    }
});

2.查找并读取文件

findAndReadButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Uri contentUri = MediaStore.Files.getContentUri("external");

        String selection = MediaStore.MediaColumns.RELATIVE_PATH + "=?";

        String[] selectionArgs = new String[]{Environment.DIRECTORY_DOCUMENTS + "/Kamen Rider Decade/"};

        Cursor cursor = getContentResolver().query(contentUri, null, selection, selectionArgs, null);

        Uri uri = null;

        if (cursor.getCount() == 0) {
            Toast.makeText(view.getContext(), "No file found in \"" + Environment.DIRECTORY_DOCUMENTS + "/Kamen Rider Decade/\"", Toast.LENGTH_LONG).show();
        } else {
            while (cursor.moveToNext()) {
                String fileName = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME));

                if (fileName.equals("menuCategory.txt")) {
                    long id = cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns._ID));

                    uri = ContentUris.withAppendedId(contentUri, id);

                    break;
                }
            }

            if (uri == null) {
                Toast.makeText(view.getContext(), "\"menuCategory.txt\" not found", Toast.LENGTH_SHORT).show();
            } else {
                try {
                    InputStream inputStream = getContentResolver().openInputStream(uri);

                    int size = inputStream.available();

                    byte[] bytes = new byte[size];

                    inputStream.read(bytes);

                    inputStream.close();

                    String jsonString = new String(bytes, StandardCharsets.UTF_8);

                    AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());

                    builder.setTitle("File Content");
                    builder.setMessage(jsonString);
                    builder.setPositiveButton("OK", null);

                    builder.create().show();
                } catch (IOException e) {
                    Toast.makeText(view.getContext(), "Fail to read file", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
});

3. 查找并覆盖文件

findAndWriteButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Uri contentUri = MediaStore.Files.getContentUri("external");

        String selection = MediaStore.MediaColumns.RELATIVE_PATH + "=?";

        String[] selectionArgs = new String[]{Environment.DIRECTORY_DOCUMENTS + "/Kamen Rider Decade/"};    //must include "/" in front and end

        Cursor cursor = getContentResolver().query(contentUri, null, selection, selectionArgs, null);

        Uri uri = null;

        if (cursor.getCount() == 0) {
            Toast.makeText(view.getContext(), "No file found in \"" + Environment.DIRECTORY_DOCUMENTS + "/Kamen Rider Decade/\"", Toast.LENGTH_LONG).show();
        } else {
            while (cursor.moveToNext()) {
                String fileName = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME));

                if (fileName.equals("menuCategory.txt")) {                          //must include extension
                    long id = cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns._ID));

                    uri = ContentUris.withAppendedId(contentUri, id);

                    break;
                }
            }

            if (uri == null) {
                Toast.makeText(view.getContext(), "\"menuCategory.txt\" not found", Toast.LENGTH_SHORT).show();
            } else {
                try {
                    OutputStream outputStream = getContentResolver().openOutputStream(uri, "rwt");      //overwrite mode, see below

                    outputStream.write("This is overwritten data。\n你就不要想起我。".getBytes());

                    outputStream.close();

                    Toast.makeText(view.getContext(), "File written successfully", Toast.LENGTH_SHORT).show();
                } catch (IOException e) {
                    Toast.makeText(view.getContext(), "Fail to write file", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
});
  • 读/写模式:https://developer.android.com/training/data-storage/shared/media#open-file-descriptor

Demo: https://www.youtube.com/watch?v=idsUMiWjfnM

希望这可以帮助你。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 MediaStore 在 Android Q 中创建/复制文件 的相关文章

随机推荐

  • 直到在 FluentWait 中无法应用 - java

    我之前有一个 Selenium 的辅助类 它的作用就像一个魅力 突然之间 这个问题出现了 我还附上了受影响功能的屏幕截图 直到 java util function Function 在 FluentWait 中无法应用 到 org ope
  • 如何将 QWebEngineProfile 设置为 QWebEngineView

    我想将不同的 QWebEngineProfiles 设置为不同的 QWebEngineViews 这意味着每个视图都有自己的 cookie 存储 我找不到任何有关它的文档 因此我们将不胜感激所有帮助 任何将独立 cookie 存储设置为独立
  • 在 GWT 中使用查询字符串

    我必须创建一个包含用户 ID 和电子邮件参数的动态 URL 它将直接指向我的 GWT 应用程序中的注册表单 我想设置和获取查询字符串中的参数 我已经提到tphttp code google com p gwt examples source
  • 无法使用java命令行打开PDF文件

    我正在尝试使用命令行参数从 java 打开 PDF 文件 String command cmd c start AcroRd32 exe dir 但是当文件自动打开时我收到错误 Windows cannot find acroRd32 ex
  • 线程访问另一个线程的堆栈

    我的想法是否正确 线程可以访问另一个线程堆栈中存在的变量 这是假设实例化堆栈变量的函数尚未返回 我想我在某处读到线程应该只共享堆内存 但我现在怀疑这是否正确 这是在 C 中使用 POSIX pthreads 严格来说 从提供线程支持 但接口
  • 什么是 XAML 在未处理的异常和 app.g.i.cs 文件上生成的中断

    我是 Windows 应用程序开发新手 我正在尝试使用 x64 平台在本地计算机上执行解决方案 但每当我执行 Button Click 事件时 我都会收到此异常 if DEBUG DISABLE XAML GENERATED BREAK O
  • jQuery 添加的 div 上的 Google 地图 addDomListener 只能看到循环的最后一次迭代

    我有以下简单的脚本 var fruits new Array apple orange lemon fruit canvas append Mouse over these fruits for var i 0 i lt fruits le
  • maven-cxf-codegen-plugin 使用 Jaxb 绑定为所有生成的类添加继承

    我正在使用 Apache CXF 的 cxf codegen plugin 将 wsdl 转换为 java 对象 我指定了一个绑定文件来添加额外的 jaxb 处理 我希望所有这些文件都从接口继承 或扩展抽象类 我的问题是 虽然我可以使用一个
  • 基于 Leaflet 和 AngularJS 的地图未正确加载

    我的基于 Leaflet 和 AngularJS 的地图无法正确加载 我不知道发生了什么 但地图图块没有按应有的方式布局 这是底图 这是我的代码 function setMapPosition scope center lat 51 505
  • 在shinyApp中使用R text2vec包和LDAvis的LDA主题模型

    以下是使用 R text2vec 包进行 LDA 主题建模的代码 library text2vec tokens docs text gt docs text a colection of text documents word token
  • 对 tsvector 中的每个元素使用 Levenshtein 函数?

    我正在尝试使用 Postgres 创建模糊搜索 并一直使用 django watson 作为基本搜索引擎来工作 我有一个名为 search tsv 的字段 它是一个 tsvector 其中包含我要搜索的模型的所有字段值 我想使用 Leven
  • 在网页中添加“导出到 Excel”按钮,以在 Web 应用程序中将 gridview 导出到 Excel

    我为诊所构建了一个患者管理软件 我需要将患者列表从 ASP net 网格视图导出到 Excel 文件 我的问题是 有没有办法将gridview导出到excel 我正在使用 vb net 和 Visual Web Developer 2010
  • 在 BeautifulSoup 中将一个标签替换为另一个标签

    我试图在 XML 文档中查找标签 并用新标签完全替换它 我认为下面应该有效 para monograph find para text Some text newpara
  • 如何在R中将减号从右移到左/从后到前?

    我已从文本文件导入数据 负数的形式为 100 右侧的减号 我应该将其转换为 100 任何想法 提前致谢 我们可以使用以下方法来做到这一点sub 我们将数字作为一个组来捕获 d 后面跟着一个 在最后 的字符串并替换为 接下来是反向引用 1 的
  • navigator.getusermedia

    我正在研究 html5 新规范 尤其是网络摄像头功能 By 按照本教程 我收到以下错误 Native web camera streaming getUserMedia is not supported in this browser 这是
  • 使用 Python OpenCV 删除图像的黑色标题部分

    我需要使用 Python CV 删除图像多个部分的黑色部分 我尝试过去噪 但没有给出令人满意的结果 例如 我需要删除表标题中的黑色部分 下图 并将标题背景转换为白色 内容为黑色 谁能帮助我选择正确的库或解决方案来克服这个问题 正如您所看到的
  • 在 Jetpack Compose 中创建垂直滑块

    我正在构建一个Android应用程序 需要在同一页面中创建多个垂直滑块用于音乐均衡器调整 但我只能从官方材料设计文档中找到水平滑块 我尝试从官方文档中实现默认滑块并使用修改器旋转它并且它可以工作 但问题是我现在无法使用调整高度Modifie
  • 如何设置 DJANGO_SETTINGS_MODULE 环境变量?

    我正在尝试修复在 django 应用程序中看到的一个不发送邮件的错误 请注意 该应用程序运行良好 只是邮件功能失败了 我尝试收集错误日志 但找不到与发送邮件相关的任何错误 所以 我做了一个例子来尝试强制错误 这是示例 from django
  • Windows 7 64 位上的 eslint-v8 Ruby gem 安装问题

    在 Windows 7 64 位 上设置 Rally App SDK 2 0p 环境时出现问题 我已经从 ruby installer org 安装了 Ruby 1 8 7 p358 并成功安装了 rake Ruby gem 但我安装时遇到
  • 使用 MediaStore 在 Android Q 中创建/复制文件

    我正在尝试找到一种方法 可以处理除媒体文件 图片 视频 音频 之外的任何文件的创建和复制 以便从 Android Q 内部存储中的一个位置复制到另一个位置 在此 我在应用程序文件夹中创建了我的文件我希望将它们移动到下载文件夹或我可以在内部存