Android KitKat 外部存储权限分析
不知道你有么有发现,来自菜鸟的成长史:http://blog.csdn.net/zjbpku/article/details/25161131,
KitKat之后的版本不再支持用户对外置SDcard(Secondary Storage)的写入等操作。如果用户想要将文件等copy到手机中,则只能
存储到内部存储器中,而无法存储到外置sdcard中,而且无法创建新的文件夹,这样一来给用户和开发者都带来了一定的不便。之所
以在KitKat之后版本中无法操作外置Sdcard,是因为Google更改了此模块的权限,以前我们可以直接获取WRITE_EXTERNAL_STORAGE
和READ_EXTERNAL_STORAGE权限来直接操作Sdcard,现在则不能,其目的是软件卸载时能将该软件创建的文件全部删除。据Google
员工Jeff SharKey(此模块的开发者)介绍,自Kitkat之后Anroid提供了新的API去访问Secondary External Storage,但这不是本文重点,本
文重点是分析外部存储权限是如何作用的。
在KitKat之前的Android版本会给应用程序单独分出一块外部存储空间(external storage),这块存储空间可能在sdcard
(可插拔的外置sdcaard)上,也可能在仅仅是在设备内部的闪存上,我们要获得WRITE_EXTERNAL_STORAGE权限在能对这块
空间进行访问,如果只是读取内容则不需要权限。在4.4 KitKat及之后的版本中,Google做了两个变化:1、进行读取时需要
READ_EXTERNAL_STORAGE权限;2、访问应用所属的目录下(如:android/data/[package name])存储的数据是不需要任
何权限的。
KitKat中,外部存储(external storage)被分割成了多个部分:一个“primary”部分,一个或多个“secondary”部分。在Kitkat之前的
API 可以用来操作 primary external storage,secondary external storage 是对write权限做了稍微修改,与上边所述一样,在应用所
所属的目录(如:android/data/[package name])下,对文件是有所有操作权限的,在应用所能管理到目录之外,该应用则不具有写
的权限,不能进行任何写的操作。这里也就引出了本文的重点。ps:Google虽然没有要求各厂商在Sdcard的操作上添加额外权限,但
是它却强制要求制造商对secondary external storage做了权限限制。如果你对Internal storage和external storage有疑问,可以看看文
档 https://developer.android.com/guide/topics/data/data-storage.html#filesInternal
根据Jeff SharKey 的介绍,当前版本的Android系统,也就是Kitkat,使用FUSE (Filesysgem in Userspace ) 对external storage进
行管理。为了在文件创建时获取必要的权限,动态地接受或拒绝来自用户/组的个别请求,会有一个Android 守护进程参与与FUSE 内核
驱动的交互。这仅仅是Android在FAT File System 格式化后的可移动卷上使用Linux型权限的一部分,在内核中它也允许使用超出基本的
owner/gouper/user 执行的多级权限控制。看看下面Jeff Sharkey的解释:
https://android.googlesource.com/platform/system/core/+/master/sdcard/sdcard.c
在4.4之前,framework api对存储卷(storage volumes)的操作并没有很大的改变,设备制造商可以创建单个“primary”卷或者多个“secondary”
卷,而这些不同的卷都能被系统服务StorageManager和MountService管理,这中情况下访问“primary”部分就像访问单个external storage一样。
很多设备有Sd卡,但是都没有把它当作external storage,实际上这就是这些设备的“secondary volume”。例如,三星的Galaxy系列就是属于这
一类,从权限方面来说,sd卡其实像外部存储卷一样被管理,但是作为设备的“secondary external storage",是没有API可以进行写的操作的。
下面的这段代码来自AOSP device storage conf iguration example:
- on init
- mkdir /mnt/shell/emulated 0700 shell shell
- mkdir /storage/emulated 0555 root root
- mkdir /mnt/media_rw/sdcard1 0700 media_rw media_rw
- mkdir /storage/sdcard1 0700 root root
- export EXTERNAL_STORAGE /storage/emulated/legacy
- export EMULATED_STORAGE_SOURCE /mnt/shell/emulated
- export EMULATED_STORAGE_TARGET /storage/emulated
- export SECONDARY_STORAGE /storage/sdcard1
系统内部的应用可以访问secondary storage的任何部分,对于第三方应用几乎不可能(目前 ES FileExplore 、 Airdroid 、 Fx 等几个文件应用通过
特别的解决方法可以实现对某些机型外部存储文件的操作)。(关于如何在4.4上操作文件可以参考Storage Options。自4.4开始,Google引入
SAF框架(Storage Access Framework),如果Google以后不改变现在对4.4系统外置sd的操作权限,对于开发者而言,熟悉SAF框架也许是必要的。
另,在4.4系统内部应用中,你会发现有一个叫DocumentUI的apk,这个就是用来处理SAF的一些接口的。)
在external storage下的目录文件拥有相同的权限,如下:
4.4 设备:
- root@generic:/storage/sdcard # ll
- d---rwxr-x system sdcard_rw 2014-05-06 13:20 Alarms
- d---rwxr-x system sdcard_rw 2014-05-06 13:21 Android
- d---rwxr-x system sdcard_rw 2014-05-06 13:20 DCIM
- d---rwxr-x system sdcard_rw 2014-05-06 13:20 Download
- d---rwxr-x system sdcard_rw 2014-05-06 13:18 LOST.DIR
- d---rwxr-x system sdcard_rw 2014-05-06 13:20 Movies
- d---rwxr-x system sdcard_rw 2014-05-06 13:20 Music
- d---rwxr-x system sdcard_rw 2014-05-06 13:20 Notifications
- d---rwxr-x system sdcard_rw 2014-05-06 13:20 Pictures
- d---rwxr-x system sdcard_rw 2014-05-06 13:20 Podcasts
- d---rwxr-x system sdcard_rw 2014-05-06 13:20 Ringtones
- root@generic:/storage/sdcard # ll Android/data/
- drwxrwx--- system sdcard_rw 2014-05-06 13:21 com.google.android.apps.maps
4.4 设备:
- root@generic:/storage/sdcard # ll
- drwxrwx--- root sdcard_r 2013-11-27 23:35 Alarms
- drwxrwx--x root sdcard_r 2013-11-27 23:36 Android
- drwxrwx--- root sdcard_r 2014-05-06 01:33 DCIM
- drwxrwx--- root sdcard_r 2013-11-27 23:35 Download
- drwxrwx--- root sdcard_r 2013-11-28 04:33 LOST.DIR
- drwxrwx--- root sdcard_r 2013-11-27 23:35 Movies
- drwxrwx--- root sdcard_r 2013-11-27 23:35 Music
- drwxrwx--- root sdcard_r 2013-11-27 23:35 Notifications
- drwxrwx--- root sdcard_r 2013-11-27 23:35 Pictures
- drwxrwx--- root sdcard_r 2013-11-27 23:35 Podcasts
- drwxrwx--- root sdcard_r 2013-11-27 23:35 Ringtones
- root@generic:/storage/sdcard # ll Android/data/
- drwxrwx--- u0_a33 sdcard_r 2013-11-27 23:36 com.google.android.apps.maps
- root@generic:/storage/sdcard # ll Android/data/com.google.android.apps.maps/
- drwxrwx--- u0_a33 sdcard_r 2013-11-27 23:36 cache
- drwxrwx--- u0_a33 sdcard_r 2013-11-27 23:36 testdata
注意:在4.3中,sdcard_rw组有全部的读写权限,在Kitkat中,sdcard_r 组有 +rwx 所有权限,实际上这是明显不对的。并不等表示全部,
因为Fuse守护进程会在运行时中积极地参与修改应用的权限。这对File APIs canWrite(),canRead()和canExecute()的执行结果有很大的影
响,这些方法返回的值被单独地记录在内核文件系统中,所以他们都会返回true,即使试图以POSIX打开文件也会失败。(在4.4的外置sd
卡上,是不能在文件夹写入一下文件的,但是当你试图调用canWrite()方法来判断该文件夹是否可写时,它仍会返回true值,所以此法不可取)
android.permission.WRITE_EXTERNAL_STORAGE权限被授给sdcard_r组和sdcard_rw组的成员,但在kitkat中认证write权限需要一些动
态的检查,因此FUSE守护进程会被用来补充文件系统的权限,FUSE守护进程会强制赋予拥有特定目录的App每个权限(也就是访问自身数
据存储的目录android/data/pack-agename...及一些公共目录)。对于sdcard_rw组中使用-w标志配置的非默认所有者,FUSE守护进程也会强
制赋予write-protected权限。
- service sdcard /system/bin/sdcard -u 1023 -g 1023 -l /data/media /mnt/shell/emulated
- class late_start
- service fuse_sdcard1 /system/bin/sdcard -u 1023 -g 1023 -w 1023 -d /mnt/media_rw/sdcard1 /storage/sdcard1
- class late_start
- disabled
从上面两句程序可以看到,FUSE守护进程强制控制GID 1023(media_rw,系统应用才有)才能对secondar storage进行写操作。再引入
一个问题,在4.4中将external storage 分为primary和secondary,在primary部分(内置sdcard)是可以进行写操作的,而在secondary部分
(外置sdcard)是不允许的,那FUSE Daemon是如何区分控制的呢?据Jeff 解释说: “-w 2013" 就表明了强制使用media_rw GID才能在
secondary部分具有write权限。
下面我们就梳理一下,如果在拥有外置sd卡的kitkat设备上进行文件操作,对于开发者而言哪些能做、哪些不能做?下图给出开发者会尝试
的一些操作及结果:
总结一下,自4.4开始Google对secondary volume做了限制之后,不仅为用户带来了不便,也为设备制造商及开发者带来了诸多不便,华为
更是为此给开发者们发了一份通告:Android4.4上应用写外卡的兼容性问题与解决建议。如今,除了一些OEM厂商自行修改权限后的Rom对
第三方应用没有限制外,大牛们也为已Root的设备用户提出修改platform.xml文件来修改权限(具体放法请百度之)以使第三方应用可以操作
外置sd卡;还有一些上面提到的文件管理工具也可以操作外置sd卡。不管Google做限制的初衷是什么,希望Google从用户的角度来考虑问题,
对Android系统做出更好的该进。在此感谢一下FX 文件管理工具的开发者Tod Liebeck 在G+对我问题的及时解答及帮助,同时也感谢一下给
Tod Liebeck解决Kitkat外置sd文件操作方案的X-plore的开发者。
Android KitKat 外部存储权限分析相关推荐
- 魅族的android m l,Android M 外部存储剖析
这篇文章是建立在你已经对 Android 外部存储的基础知识有一定了解的基础之上,如果之前并不是太了解这个部分,阅读起来可能会比较费劲,可以先阅读参考下面文章:http://blog.csdn.net ...
- kotlin读取sd卡里的文件_Kotlin Android读写外部存储
本文概述 Android外部存储空间是我们执行读写操作的存储空间.外部存储器中的文件存储在/ sdcard或/ storage文件夹等中.保存在外部存储器中的文件是可读的, 并且可由用户修改. 在访问 ...
- android查询所有照片,Android查询外部存储中所有照片
最近写了个自定义相册模块,其中比较核心的算是查询照片了,直接上代码吧 val contentUri = MediaStore.Files.getContentUri("external&qu ...
- 存储当时android,Android之外部存储(SD卡)
*手机的外部存储空间,这个我们可以理解成电脑的外接移动硬盘,U盘也行.所有的Android设备都有两个文件存储区域:"内部"和"外部"存储器.这两个名称来自早期 ...
- android的访问存储权限,使用SAF(存储访问框架)的Android SD卡写权限
关于如何在SD卡(android 5及以上版本)中编写(和重命名)文件的大量调查结果后,我认为android提供的新SAF需要获得用户写入SD卡文件的许可. 我在这个文件管理器应用程序ES文件资源管理 ...
- 转:彻底搞懂Android文件存储---内部存储,外部存储以及各种存储路径解惑
转自:https://blog.csdn.net/u010937230/article/details/73303034 前言: 对于任何一个应用来说,无论是PC端应用还是Android应用,存储肯定 ...
- Android文件存储---内部存储,外部存储以及各种存储路径解惑
本文转自:https://blog.csdn.net/u010937230/article/details/73303034 前言: 对于任何一个应用来说,无论是PC端应用还是Android应用,存储 ...
- android存储视频文件夹在哪,Android 中 视频存储路径的一个方案
版权声明:本文为博主原创文章,未经博主允许不得转载. 在进行视频的下载时,我们经常会面临存储路径的选择,选择一个好的存储路径能对Android系统中的内存起到优化的作用.主流app下载路径分析和常见的 ...
- requestPermissions读写手机存储权限_Android 11 开发者常见问题: 存储 | FAQ?第二期
我们在 Android 10 中首次引入了 "分区存储" 的概念,旨在保护应用和用户数据并减少文件混乱.自此之后我们收到了开发者们的宝贵建议,这些建议有助于我们对该功能的持续优化, ...
最新文章
- Ninja提升编译速度的方法-Android10.0编译系统(十)
- python中用*打印一个上三角形和下三角形组成的三角形
- 软件版本号命名规范_软件发布版本介绍
- python爬取b站评论_python高效之爬了B站再爬微博
- CMU | 深度学习模型中集成优化、约束和控制
- Linux编程(4)_gcc
- MySQL数据库和表名大小写敏感开关的打开办法
- 8.4. Socket 方式
- poj 1094 Sorting It All Out 很好的拓扑排序,让我对拓扑排序有了一个很好的写法!!!
- 双 JK 触发器 74LS112 逻辑功能。真值表_【数电笔记】时序逻辑电路设计举例
- 算法题--广度优先算法(素数行李箱密码解法加步骤)
- 关于计算机的英语谜语,英语的谜语大全及答案
- 用python提取发票扫描件常用的10多个发票信息保存到excel表
- 【漏洞复现】phpstudy隐藏后门漏洞的验证与利用
- 7-4 大炮打蚊子 (20分)__C++
- Android之ContentProvider
- 科比投篮预测——可视化与探索性数据分析(二)
- [PHP]用PHP自己写一个zoomeye的api(偷懒必备quq)
- FinallShell 离线激活步骤,适用MAC/WIN
- 使用CreateJS制作动画