如何使用范围存储创建和删除公共文件,Android Q

Posted

技术标签:

【中文标题】如何使用范围存储创建和删除公共文件,Android Q【英文标题】:How to create and delete public files using scoped storage, Android Q 【发布时间】:2021-12-26 07:08:59 【问题描述】:

我们有一个发送彩信的应用程序。 android MmsManager 需要一个指向文件的 URI 参数。看来这个文件需要公开,否则 MmsService 会因为权限被拒绝而获得 Io 异常。因此,为了符合新的范围存储规则,我在 MediaStore DownLoads 文件夹中创建了一个 .dat 文件。这很好用,即使在 MediaStore 中存储 .dat 文件对我来说没有意义。但是彩信发送后,我需要删除这个文件。如果不征求用户许可或使用 android.permission.MANAGE_EXTERNAL_STORAGE,我看不到任何这样做的方法。要求用户允许删除他甚至不知道的文件显然是不好的。当然 android.permission.MANAGE_EXTERNAL_STORAGE 需要获得 Google 的许可才能使用,而且仅仅为了能够删除由应用程序创建的数据文件似乎有点矫枉过正。那么,有没有办法创建一个以后可以删除的公共文件。我已经知道 android:requestLegacyExternalStorage="true" 是一个非常临时的解决方案,而 Environment.getExternalStoragePublicDirectory 已被弃用。该文件是使用类似于下面的代码创建的。 pdu 是之前创建的字节数组。

final String fileName = "send." + String.valueOf(Math.abs(mRandom.nextLong())) + ".dat";
    ContentResolver contentResolver = mContext.getContentResolver();
    ContentValues contentValues = new ContentValues();

    contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
    contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);

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

try 
     writer = mContext.getContentResolver().openOutputStream(contentUri);
     writer.write(pdu);
     catch (final IOException e) 
        Log.e(TAG, "Error writing to output stream in MmsSender. e= ", e);
     finally 
        if (writer != null) 
            try 
                writer.close();
             catch (IOException e) 
                Log.e(TAG, "IOException writing PDU file in MmsSender, e= " + e);
            
        
    

【问题讨论】:

“看来这个文件需要公开,否则 MmsService 会因为 Permission denied 获得 Io 异常”——您是否尝试过使用 FileProvider? “Environment.getExternalStoragePublicDirectory 已弃用”——FWIW,it is undeprecated in Android 12L and is safe to use,尽管它不会增加您的访问权限。 Environment.getExternalStoragePublicDirectory 会给我一个路径名列表。然后我可以创建文件对象,然后调用删除。文件 f = 新文件(路径); f.删除();所以这将解决我的问题。我对 FileProvider 很感兴趣。我查看了文档。它似乎适用于授予其他包或 Intents 的权限。但我只是将 urii 作为参数传递给一个方法, smsManager.sendMultimediaMessage(context, uri, ... 在这种情况下无论如何要授予权限。将这些文件存储在公共存储区。 对我自己的问题的另一条评论。删除文件的主要原因是为了节省存储空间,因为它们有点大。 Media Store 似乎没有提供此功能,但它可以让您打开文件的输出流。因此,当我完成它们时,我可以只覆盖其中没有任何内容的文件,因此它们不会占用任何空间。然后我将重复使用相同的文件。 我可能会选择“斧头”:实现一个不需要权限的ContentProvider(因此短信内容可以读取内容)并采取其他步骤确保没有其他人可以访问内容(仅尊重您使用路径中的随机数据生成的Uri 值,并为您保留内容的时间设置合理的时间限制)。我很抱歉没有意识到 FileProvider 在你的情况下不起作用——我没有太多处理 MMS。 我会看看你的通知铃声。不需要道歉,仅仅因为 FileProvider 不适用于这种情况并不意味着它不是我应该知道的。非常感谢您的帮助。 【参考方案1】:

如果您的应用可以使用媒体商店创建文件,那么您的应用也可以删除该文件。

【讨论】:

这应该是一条评论。 我同意,如果我创建文件,我应该能够删除它。但是,您的回答不是很有帮助。 它应该鼓励您发布用于删除同一文件的代码。我们错过了它。 是的,这家伙 ^ 惹人,他不是很有帮助

以上是关于如何使用范围存储创建和删除公共文件,Android Q的主要内容,如果未能解决你的问题,请参考以下文章

使用 Android 的 MediaStore(ContentResolver/范围存储)创建图像文件后文件扩展名和文件名错误

如何在 Android 10 中创建公共文件夹/文件

如何使用 android 范围/共享存储获取可用空间?

从android 11的范围存储中删除图像

如何将文件写入 Android 中的外部公共存储,以便它们在 Windows 中可见?

如何删除android中的内部存储文件?