外部存储、WRITE_EXTERNAL_STORAGE权限与maxSdkVersion属性的使用

概述

最近在项目中发现READ_EXTERNAL_STORAGE配置了maxSdkVersion 属性,于是决定对maxSdkVersion属性研究一番。研究过程中涉及好几个知识点:文件存储结构、外部存储权限、动态权限申请等。

1.存储空间概述

Android 的文件存储分为:Internal file storage 和 External file storage。

  • 内部文件存储:存储应用的私有文件,其他应用无法自然访问的数据(除非拥有 Root 访问权限)。
  • 外部文件存储:在共享外部文件系统中存储文件,此方式通常为您要与其他应用共享用户文件数据,如照片等。
内部存储
  • 内部存储存的是应用私有文件,其他应用(和用户)不能访问这些文件,除非拥有 Root 访问权限。
  • 系统会为每个应用提供私有目录,您可以在该目录中整理应用所需的任何文件。
  • 当用户卸载应用时,内部存储中的私有文件也将随之移除。
  • 如果您希望在卸载应用后仍能访问这些文件或照片,您可以改用 MediaStore 将这些类型的文件保存至合适的媒体集合中,或者存储于外部存储里的“公共共享目录”
外部存储
  • 每个 Android 设备都支持共享的“外部存储”空间,“外部存储”从名字上可能会被理解为外置的SD卡,其实并不是,有的设备没有SD卡插槽,但系统会从内部存储分配出一部分存储空间来用作外部存储
  • 所以说外部存储包括了分出来的虚拟外部存储SD卡存储
  • 当存在多个存储位置时,会有主要外部存储和其他外部存储之分。
  • 对于外部存储,用户并非始终都能访问该外部空间,用户有可能会拔出SD卡,因此,在尝试访问应用外部存储中的文件时,应检查外部存储目录及您尝试访问的文件是否可用。

如果您希望与其他应用共享文件,可以使用 FileProvider。

外部存储空间里又有两种区分:

  • 公共文件目录:如 /storage/emulated/0/Pictures
    如果你的用户数据可供其他应用访问,系统提供了一系列的标准公共文件目录,如Download、Pictures、Music、Movies等目录,位于外部存储的根目录下。
    这些数据的存储不会随着您应用的卸载而删除。
  • 私有文件目录:如 /storage/emulated/0/Android/data/应用包名/files
    由于内部存储的空间资源往往是比较紧缺的,如果想要存储更多的数据,可将文件保存至外部存储中的“应用特定目录”中。
    当用户卸载应用时,系统也会删除该目录,所以叫应用在外部存储中的私有文件目录。但这些文件仍是全局可读取文件,只不过其他应用无法共享保存该文件的位置。

外部存储空间中的文件并非始终都能访问到,因其存储于外部存储空间,有可能是从内部存储中分配出来的虚拟外部存储,有可能是SD卡存储。还有可能会移除 SD卡,因此在访问之前,您应检查外部存储目录及您尝试访问的文件是否可用。

注意:如果用户移除了外部存储设备(例如 SD 卡)或断开其连接,则存储在外部存储上的文件可能会变得不可用。如果您的应用功能非常依赖于这些文件,则应将文件写入“内部存储”。

外部存储,在多个存储位置之间的选择

市场上有些设备将内部存储分出虚拟外部存储,同时还会提供 SD 卡插槽。这意味着这些设备会有两个不同的外部存储目录,因此在将“私有”文件写入外部存储时,需要选择使用哪个目录。

从 Android 4.4 API 19 开始,可以通过调用getExternalFilesDirs()来访问这两个位置,它返回一个File数组,包含了每个存储位置的条目。数组中的第一个条目被视为主要外部存储,除非该位置已满或不可用,否则应该一律使用该位置。
如果应用支持 API 18 及更低版本,则应使用静态方法 ContextCompat.getExternalFilesDirs(),它始终会返回一个 File 数组,但如果设备搭载的是 API 18 及更低版本,数组中将仅包含主要外部存储的条目。(如果有第二个存储位置,您将无法在 Android 4.3 及更低版本上访问它。)

2.请求外部存储权限

Android 包含以下访问外部存储中的文件的权限:

READ_EXTERNAL_STORAGE
允许应用访问外部存储设备中的文件
WRITE_EXTERNAL_STORAGE
允许应用在外部存储设备中写入和修改文件。API 19 开始,拥有此权限的应用也会自动获得 READ_EXTERNAL_STORAGE 权限。

从 Android 4.4(API 19)开始,在“应用特定的目录(“私有文件目录”)”中读取或写入文件不再需要任何与存储相关的权限。

因此,如果您的应用支持 Android 4.3(API 18)及更低版本,并且您只想访问应用特定的目录(“私有文件目录”),则可以添加 maxSdkVersion 属性,声明仅在较低版本的 Android 上请求权限:(这里可能有坑,会和Android6.0权限有点小问题,慎用。)

<manifest>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                     android:maxSdkVersion="18" />
</manifest>

具体说明:

  • 如果应用需要访问其他应用的文件或者“公共文件目录”,则需要在清单中配置存储权限,且不能添加 maxSdkVersion 属性。
  • 如果应用只需要访问应用特定的目录即私有文件目录:(这种情况实际中很少)
    - 如果应用仅支持 API 19 及之后版本,则不需要在清单中配置存储权限。
    - 如果应用还支持 API 18 及更低版本,则需要在清单中配置存储权限,且可以添加 maxSdkVersion 属性,声明仅在较低版本的 Android 上请求权限。
    - maxSdkVersion 这里可能有坑,会和Android6.0权限有点小问题,慎用。

最后关于权限的结论:
"存储权限最好还是都在清单中配置上,而且maxSdkVersion属性要慎用。"

可能有人会问,我这篇文章说了这么多,好像是都在说废话,还得出了一个废话结论,其实我是带着下面的疑问和设想来研究本文的。
以下几点是我对外部存储权限的理解,本文旨在理清其中一些隐藏细节。

1.只有在清单文件中配置了的权限,在应用的权限管理中才会出现。而且6.0动态权限开始,用户还可以手动修改权限,这种情况如果用户手动关闭了权限,则有可能导致应用无法“正常”的运行。
2.如果应用仅访问外部存储中的“私有文件目录”,那么我们是不是可以不用在清单文件中配置权限,或者使用maxSdkVersion属性限定只在低版本上配置权限?那么在应用的权限管理中就不会出现存储权限也不会有存储权限的开关,因而用户就无法关闭该权限,应用不会因为用户主动关闭权限而无法正常运行。
3.如果应用还要访问其他应用文件或者公共文件目录,那就必须乖乖在清单文件中配置权限吧。

上面是我的理解,欢迎大家指出我理解不对的地方~

参考链接:
https://developer.android.google.cn/guide/topics/data/data-storage
https://developer.android.google.cn/training/data-storage/files/external

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容