关于 Android 没有文件存储权限保存文件的问题

我发现Android 有些APP 他们不需要申请文件存储权限就可以进行文件的保存翻阅大量文章总结如下:

前言:

从 Android 10 开始,Android 引入了一种新的存储权限模型,其中应用需要明确请求运行时权限以访问外部存储。在这种情况下,许多应用程序可能需要请求 WRITE_EXTERNAL_STORAGE 权限才能将文件下载到公共目录(例如 "Download" 目录)。这是为了提高用户的隐私和数据安全。

但是,有一些应用可能使用特定的权限或 API 或者具有特定的使用案例,可以绕过运行时权限请求。这通常是因为这些应用可能是系统应用、文件管理器、云存储应用、或者拥有其他特权。这些应用可能不受相同的权限限制。

在一些情况下,应用可能会使用不需要特定存储权限的公共存储 API(例如 MediaStoreDownloadManager)来保存文件到公共目录。这些 API 可能会更加灵活,但通常仍受到安全限制,以确保访问的合法性。

如果您注意到其他应用可以在不申请存储权限的情况下将文件下载到公共目录,那可能是因为它们在特权环境中运行,或者它们使用了特殊的 API,或者它们使用了其他方式来绕过权限限制。不过,通常情况下,普通的应用仍然需要明确请求存储权限,以确保合法的文件操作。

官网说明:

  • 应用专属存储空间:存储仅供应用使用的文件,可以存储到内部存储卷中的专属目录或外部存储空间中的其他专属目录。使用内部存储空间中的目录保存其他应用不应访问的敏感信息。
  • 共享存储:存储您的应用打算与其他应用共享的文件,包括媒体、文档和其他文件。
  • 偏好设置:以键值对形式存储私有原始数据。
  • 数据库:使用 Room 持久性库将结构化数据存储在专用数据库中
  • 内容类型 访问方法 所需权限 其他应用是否可以访问? 卸载应用时是否移除文件?
    应用专属文件 仅供您的应用使用的文件 从内部存储空间访问,可以使用 getFilesDir() 或 getCacheDir() 方法

    从外部存储空间访问,可以使用 getExternalFilesDir() 或 getExternalCacheDir() 方法
    从内部存储空间访问不需要任何权限

    如果应用在搭载 Android 4.4(API 级别 19)或更高版本的设备上运行,从外部存储空间访问不需要任何权限
    媒体 可共享的媒体文件(图片、音频文件、视频) MediaStore API 在 Android 11(API 级别 30)或更高版本中,访问其他应用的文件需要 READ_EXTERNAL_STORAGE

    在 Android 10(API 级别 29)中,访问其他应用的文件需要 READ_EXTERNAL_STORAGE 或 WRITE_EXTERNAL_STORAGE

    在 Android 9(API 级别 28)或更低版本中,访问所有文件均需要相关权限
    是,但其他应用需要 READ_EXTERNAL_STORAGE 权限
    文档和其他文件 其他类型的可共享内容,包括已下载的文件 存储访问框架 是,可以通过系统文件选择器访问
    应用偏好设置 键值对 Jetpack Preferences 库
    数据库 结构化数据 Room 持久性库
    公共存储(只介绍 --- 共享存储):

如果用户数据可供或应可供其他应用访问,并且即使在用户卸载应用后也可对其进行保存,请使用共享存储空间。Android 提供用于存储和访问以下类型的可共享数据的 API:

  • 媒体内容:系统提供标准的公共目录来存储这些类型的文件,这样用户就可以将所有照片保存在一个公共位置,将所有音乐和音频文件保存在另一个公共位置,依此类推。您的应用可以使用此平台的 MediaStore API 访问此内容。
  • 文档和其他文件:系统有一个特殊目录,用于包含其他文件类型,例如 PDF 文档和采用 EPUB 格式的图书。您的应用可以使用此平台的存储访问框架访问这些文件。
  • 数据集:在 Android 11(API 级别 30)及更高版本中,系统会缓存多个应用可能使用的大型数据集。这些数据集可为机器学习和媒体播放等用例提供支持。应用可以使用 BlobStoreManager API 访问这些共享数据集。

具体公共目录内容说明:

  • 图片(包括照片和屏幕截图),存储在 DCIM/ 和 Pictures/ 目录中。系统将这些文件添加到 MediaStore.Images 表格中。
  • 视频,存储在 DCIM/Movies/ 和 Pictures/ 目录中。系统将这些文件添加到 MediaStore.Video 表格中。
  • 音频文件,存储在 Alarms/Audiobooks/Music/Notifications/Podcasts/ 和 Ringtones/ 目录中。此外,系统还可以识别 Music/ 或 Movies/ 目录中的音频播放列表,以及 Recordings/ 目录中的录音。系统将这些文件添加到 MediaStore.Audio 表格中。Recordings/ 目录在 Android 11(API 级别 30)及更低版本中不可用。
  • 下载的文件,存储在 Download/ 目录中。在搭载 Android 10(API 级别 29)及更高版本的设备上,这些文件存储在 MediaStore.Downloads 表格中。此表格在 Android 9(API 级别 28)及更低版本中不可用。

个人总结:

通过以上资料的说明:APP需要下载的文件例如是图片、视频、音乐会保存放在DCIM、Movies 或者Movies 目录中;像PDF、APK等文件可以放在Download目录中,他们不需要进行对应权限的申请;例如在Android 13中保存apk文件使用 getExternalStoragePublicDirectory 如果不申请 WRITE_EXTERNAL_STORAGE权限会保存文件失败;如果我们只用官方说明的MediaStore  API 来保存文件则不会遇到权限申请的问题。

示例代码1:

 String destinationPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/app_update.apk";

示例代码2:

public class ApkFileSaver {

    // 定义保存文件的目录和文件名
    private static final String DIRECTORY_NAME = Environment.DIRECTORY_DOWNLOADS;
    private static final String FILE_NAME = "my_app.apk";

    public static Uri saveApkFileToDownloads(Context context, byte[] apkData) {
        ContentResolver contentResolver = context.getContentResolver();
        ContentValues contentValues = new ContentValues();
        contentValues.put(MediaStore.Downloads.DISPLAY_NAME, FILE_NAME);
        contentValues.put(MediaStore.Downloads.MIME_TYPE, "application/vnd.android.package-archive");
        contentValues.put(MediaStore.Downloads.RELATIVE_PATH, DIRECTORY_NAME);

        Uri contentUri = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
        Uri fileUri = contentResolver.insert(contentUri, contentValues);

        if (fileUri != null) {
            try {
                // 打开文件输出流并写入APK数据
                contentResolver.openOutputStream(fileUri).write(apkData);
                return fileUri;
            } catch (Exception e) {
                e.printStackTrace();
                // 处理保存文件时的异常
            }
        }
        return null;
    }
}

参考文章:https://developer.android.com/training/data-storage/shared/media?hl=zh-cn

你可能感兴趣的:(android)