当前位置: 首页 > 知识库问答 >
问题:

在Android11上使用外部存储写入多个应用程序使用的文件

高泳
2023-03-14

对于如何在Android11上实现这一点有什么想法吗?BlobManager似乎很合适,但文档很糟糕(我尝试了它,但没有成功:Android11上的新BlobStoreManager读写)

private void writeFile(String data) {
    try {
        File f = new File(Environment.getExternalStorageDirectory(), FOLDER_NAME);
        if (!f.exists()) {
            boolean mkdirs = f.mkdirs();
            if (!mkdirs) {
                return;
            }
        }

        File file = new File(f, FILE_NAME);
        FileOutputStream outputStream = new FileOutputStream(file);

        String encoded = Base64.encodeToString(data.getBytes(), Base64.DEFAULT);

        outputStream.write(encoded.getBytes());
        outputStream.close();
    } catch (IOException e) {
        Logger.e(TAG, "writeFile: IOException", e);
    } catch (Exception e) {
        Logger.e(TAG, "writeFile: Basic exception", e);
    }
}

private String readFile() {
    String data;
    try {
        File file = new File(Environment.getExternalStorageDirectory(), FOLDER_NAME + "/" + FILE_NAME);
        if (!file.exists()) {
            return "";
        }
        InputStream is = new FileInputStream(file);

        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();

        String text = new String(buffer, Charset.forName("UTF-8"));
        data = new String(Base64.decode(text, Base64.DEFAULT));
        Logger.d(TAG, "readFile: decoded = " + data);
    } catch (IOException e) {
        Logger.e(TAG, "readFile: IOException", e);
        return "";
    } catch (IllegalArgumentException e) {
        Logger.e(TAG, "readFile: Illegal Base64 import preset", e);
        return "";
    } catch (Exception e) {
        Logger.e(TAG, "readFile: Basic exception", e);
        return "";
    }
    return data;
}

编辑:我尝试了一些其他解决方案

外部公共存储方式

应用程序“A”可以写入文件,然后读取文件。但另一个应用程序“B”不能读取“A”所写的文件

我只得到一个访问错误:notificationhelper-readfile:IOException java.io.fileNotfoundexception:/storage/emulated/0/download/myfolder/settings.bin:open失败:EACCES(权限被拒绝)在libcore.io.iobridge.open(iobridge.java:492)在java.io.fileInputStream.(fileInputStream.java:160)

file = new File (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), FOLDER_NAME + "/" + FILE_NAME);

纵隔道

但仅仅使用一个应用程序,我就遇到了问题:应用程序不能重写文件writtend之前,它创建了多个实例“my_file”、“myfile(1),...”,而我在尝试读取它时出现了错误:

java.io.FileNotFoundException:打开失败:位于Android.Database.Databaseutils.ReadexceptionWithFileNotFoundExceptionFromparcel(Databaseutils.java:151)位于Android.Content.ContentProviderProxy.OpenTypedAssetFile(ContentProviderNative.java:781)位于Android.Content.ContentResolver.OpenTypedAssetFileDescriptor(ContentResolver.java:1986)位于

private void writeFile(String data) {
        String outputFilename = "my_file";
        String outputDirectory = "my_sub_directory"; // The folder within the Downloads folder, because we use `DIRECTORY_DOWNLOADS`

        ContentResolver resolver = AbstractMobileApplication.getInstance().getApplicationContext().getContentResolver();
        ContentValues values = new ContentValues();
        // save to a folder
        values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, outputFilename);
        values.put(MediaStore.Files.FileColumns.MIME_TYPE, "application/my-custom-type");
        values.put(MediaStore.Files.FileColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + "/" + outputDirectory);
        values.put(MediaStore.Files.FileColumns.IS_PENDING, 1);

        Uri uri = resolver.insert(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), values);
        // You can use this outputStream to write whatever file you want:
        OutputStream outputStream = null;
        Log.d(TAG, "writeFile: >>>>>>>>" + uri.getPath());
        try {
            outputStream = resolver.openOutputStream(uri);

            String encoded = Base64.encodeToString(data.getBytes(), Base64.DEFAULT);

            outputStream.write(encoded.getBytes());
            outputStream.close();

            values.clear();
            values.put(MediaStore.Files.FileColumns.IS_PENDING, 0);
            resolver.update(uri, values, null, null);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
}

private String readFile() {
    String data;
        String outputFilename = "my_file";
        String outputDirectory = "my_sub_directory"; // The folder within the Downloads folder, because we use `DIRECTORY_DOWNLOADS`

        ContentResolver resolver = AbstractMobileApplication.getInstance().getApplicationContext().getContentResolver();
        ContentValues values = new ContentValues();
        // save to a folder
        values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, outputFilename);
        values.put(MediaStore.Files.FileColumns.MIME_TYPE, "application/my-custom-type");
        values.put(MediaStore.Files.FileColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + "/" + outputDirectory);

        Uri uri = resolver.insert(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), values);
        // You can use this outputStream to write whatever file you want:
        Log.d(TAG, "readFile: >>>>>>>>" + uri.getPath());
        try {
            InputStream is = resolver.openInputStream(uri);

            int size = is.available();
            byte[] buffer = new byte[size];
            is.read(buffer);
            is.close();

            String text = new String(buffer, Charset.forName("UTF-8"));
            data = new String(Base64.decode(text, Base64.DEFAULT));
            Logger.d(TAG, "readFile: decoded = " + data);

        } catch (FileNotFoundException e) {
            data = "";
            e.printStackTrace();
        } catch (IOException e) {
            data = "";
            e.printStackTrace();
        }
    return data;
}

共有1个答案

万俟光临
2023-03-14

您可以考虑一个选举协议,让一个应用程序成为数据的“所有者”,其他应用程序只有备份副本,如果卸载了当前的所有者应用程序,则使用一个新的选举。如果处理得当,这可以减少碰撞的风险,但代价是更加复杂。

简单的解决方案是允许用户通过action_create_document(对于第一个应用程序)和action_open_document(对于后续应用程序)指定共享内容的驻留位置。但是,您拒绝了这一点(“并且它要求对用户来说是”不可见的“:没有文件拾取器”)。我建议你放宽这一要求。而且,你还需要一些协调机制,如果多个应用程序可能会修改你的公共内容,就像你最初使用的公共文件方法一样。

而且,您可以考虑取消套件,将功能合并到一个应用程序中。或者,为套件采用更多的“主机和插件”模型,这样每个插件应用程序就不需要独立访问数据。

 类似资料:
  • 最近我更新了我的智能手机到Android11,我注意到我的一个应用程序在创建外部存储目录时崩溃了。我读过Android11文档,这里是。很奇怪,因为当我打开Android/Data dir时,有很多应用程序文件夹,所以有可能这样做,或者有应用程序在更新之前创建的文件夹?

  • 我的舱单中有权限条目: 编辑:我正在使用sdk 23

  • 我想在同一个主机上部署两个不同的django应用程序:第一个对应于url/site1,第二个对应于url/site2。这是我的配置: 这是两个应用程序的wsgi.py文件 现在,我的问题来了。当我转到服务器时,假设http://app1.sites.gr/site1它有时加载site1,有时加载site2!!!!我访问时也是如此http://app1.sites.gr/site2 ... 有时我会

  • 问题内容: 我正在尝试使用多个线程在Java中编写一个大文件。 我已经尝试了Java 和类。 实际上,要写入的内容是使用和写入的整个表(Postgres)。文件中的每一行都是表中的一个元组,我一次要写100行。 编写方法: 单个待写入文件由附加模式下的多个线程打开。此后,每个线程都尝试写入文件文件。 以下是我面临的问题: 有时,文件的内容将被覆盖,即:一行仍然不完整,而下一行从那里开始。我的假设是

  • 我正在尝试创建许多文件,作为用户的一个功能。例如,我可能会编写一个应用程序,为他们过去几周听的每首歌创建一个文件(例如,一个带有歌词的文本文件)。我不能让用户为我生成的每个文件选择目录和文件名,这将花费他们数小时的时间。用户应该可以从其他应用程序访问这些文档。 在Android11中,存储访问框架似乎没有什么用处。我注意到最初有两个有趣的选项: 创建一个新文件(该文件创建启动用户与之交互的活动,以