Android 10分区存储

Android 10(API 级别 29)引入了多项功能和行为变更,目的是更好地保护用户的隐私权。其中最重要的变化之一就是存储访问权限。Android 10中,Google针对外部存储引入了一个新特性,它的名字叫:Scoped Storage,Google官方对它的翻译为分区存储,我们也可以把它叫做作用域存储。

文件的归属:

系统记录文件由哪个应用创建,而应用就是这个文件的归属者即:owner,这个应用拥有文件的所有权,所以我们操作该文件不需要任何权限,包括增删改查,但是如果你不是文件的归属者,那么需要申请相应的权限,当然我们所说的是外置存储的公共目录,那么我们怎么获取到该文件是否属于我们自己的,请看下面的图:


externadb.png

这张图是我从模拟器导出的external.db数据库文件,这里就存放了,我们公共目录中的数据,我们可以获取到文件名(_display_name)、文件的相对路径(relative_path)和绝对路径(_data)以及文件的所属者(owner_package_name),在表中还有很多字段保存了文件的信息,感兴趣可以去看看:/data/data/com.android.providers.media/databases/external.db,里面还有内部存储的数据库;

应用数据保护

1、添加外部存储应用私有目录文件访问限制,应用即使申请了存储权限也不能访问其他应用外部存储私有目录文件,可能有人不明白,就是说在Android Q之后google出分区存储,也就是沙盒机制,但是如果是公共目录先的文件其他应用是可以查看的,但是不能修改和删除即使有了存储权限也不能,其他应用修改和删除是需要申请额外的权限。
2、添加pdf、office、doc等文件的访问限制,用户即使申请了存储权限也不能访问其他应用创建的pdf、office、doc等文件

共享目录文件访问存储权限

Uri类型 无权限 READ_EXTERNAL
Audio 可读写APP自己创建的文件,但不可直接使用路径访问 可以读取其他APP创建的媒体类文件,删除和修改操作需要用户授权。
Image 可读写APP自己创建的文件,但不可直接使用路径访问 可以读其他APP创建的媒体类文件,删改操作需要用户授权
File 可读写APP自己创建的文件,但不可直接使用路径访问 不可读写其他APP创建的非媒体类文件
Downloads 可读写APP自己创建的文件,但不可直接使用路径访问 不可读写其他APP创建的非媒体类文件

共享目录文件需要通过MediaStore API或者Storage Access Framework方式访问
(1) MediaStore API 在共享目录指定目录下创建文件或者访问应用自己创建文件,不需要申请任何存储权限,所有者拥有文件的所有权;
(2)MediaStore API访问其他应用在共享目录创建的媒体文件(图片、音频、视频), 需要申请存储权限,未申请存储权限,通过ContentResolver查询不到文件Uri,即使通过其他方式获取到文件Uri,读取或创建文件会抛出异常;
(3)MediaStore API不能够访问其他应用创建的非媒体文件(pdf、office、doc、txt等), 只能够通过Storage Access Framework方式访。

MediaStore API介绍

系统会自动扫描外部存储,添加文件到系统已定义的Images、Videos、Audio files、Downloaded files集合中,Android 10通过MediaStore.Images、MediaStore.Video、MediaStore.Audio、MediaStore.Downloads 访问共享目录文件资源

MediaStore API创建文件

Android 10版本 MeidaStore API只允许在共享目录指定目录创建文件, 非指定目录创建文件会抛出IllegalArgumentException, 创建文件目录汇总如下:

媒体类型 Uri 默认创建目录 允许存储文件
Image content://media/external/images/media Pictures 只能放图片
Audio content://media/external/audio/media Music 只能放音频
Video content://media/external/video/media Movies 只能放视频
Download content://media/external/downloads Download 任意类型

MediaStore.Downloads.EXTERNAL_CONTENT_URI是Android10版本新增API,用于创建、访问非媒体文件,需要注意的是:虽然获取了存储权限,但是依然不能够删除和修改其他应用的文件。

MediaStore API 文件访问

MediaStore.png

Storage Access Framework介绍

上面提到MediaStore API不能够访问其他应用创建的非媒体文件(pdf、office、doc、txt等), 只能够通过Storage Access Framework方式访。
Android 4.4引入了Storage Access Framework框架,应用通过系统选择器访问 DocumentsProvider 提供文件(包含外部存储以及云端存储, 外部存储包含应用私有目录以及共享目录), SAF机制不需要申请任何存储权限, 包含Document provider、Client app、Picker三部分:

  • Document provider:一个特殊的ContentProvider,让一个存储服务(比如Google Drive)可以 对外展示自己所管理的文件。它是DocumentsProvider的子类,另外,document-provider的存储格式 和传统的文件存储格式一致,至于你的内容如何存储,则完全决定于你自己,Android系统已经内置了几个 这样的Document provider,比如关于下载,图片以及视频的Document provider。

  • Client app:一个普通的客户端软件,通过触发ACTION_OPEN_DOCUMENT 和/或 ACTION_CREATE_DOCUMENT就可以接收到来自于Document provider返回的内容,比如选择一个图片, 然后返回一个Uri。

  • Picker:类似于文件管理器的界面,而且是系统级的界面,提供额访问客户端过滤条件的 Document provider内容的通道,就是起说的那个DocumentsUI程序,下面是打开系统相册。

     Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
      intent.addCategory(Intent.CATEGORY_OPENABLE);
      intent.setType("image/*");
      startActivityForResult(intent, 100);
    
     @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
          Uri uri;
          if (data != null) {
              uri = data.getData();
          }
      }
      }
    

通过Uri你可以就可以做你想做的事情了,而Uri的获取则是通过SAF得到,如果你觉得的系统相册不好看,那你可以自定义Document Provider。

你可能感兴趣的:(Android 10分区存储)