文档章节

Android 外部存储权限分析

s
 sflfqx
发布于 2015/02/09 17:25
字数 2333
阅读 180
收藏 0

不知道你有么有发现,来自菜鸟的成长史: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:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. on init  

  2.     mkdir /mnt/shell/emulated 0700 shell shell  

  3.     mkdir /storage/emulated 0555 root root  

  4.     mkdir /mnt/media_rw/sdcard1 0700 media_rw media_rw  

  5.     mkdir /storage/sdcard1 0700 root root  

  6.     export EXTERNAL_STORAGE /storage/emulated/legacy  

  7.     export EMULATED_STORAGE_SOURCE /mnt/shell/emulated  

  8.     export EMULATED_STORAGE_TARGET /storage/emulated  

  9.     export SECONDARY_STORAGE /storage/sdcard1  

系统内部的应用可以访问secondary storage的任何部分,对于第三方应用几乎不可能(目前ES FileExploreAirdroidFx等几个文件应用通过

特别的解决方法可以实现对某些机型外部存储文件的操作)。(关于如何在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 设备:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. root@generic :/storage/sdcard # ll  

  2. d---rwxr-x system sdcard_rw 2014-05-06 13:20 Alarms  

  3. d---rwxr-x system sdcard_rw 2014-05-06 13:21 Android  

  4. d---rwxr-x system sdcard_rw 2014-05-06 13:20 DCIM  

  5. d---rwxr-x system sdcard_rw 2014-05-06 13:20 Download  

  6. d---rwxr-x system sdcard_rw 2014-05-06 13:18 LOST.DIR  

  7. d---rwxr-x system sdcard_rw 2014-05-06 13:20 Movies  

  8. d---rwxr-x system sdcard_rw 2014-05-06 13:20 Music  

  9. d---rwxr-x system sdcard_rw 2014-05-06 13:20 Notifications  

  10. d---rwxr-x system sdcard_rw 2014-05-06 13:20 Pictures  

  11. d---rwxr-x system sdcard_rw 2014-05-06 13:20 Podcasts  

  12. d---rwxr-x system sdcard_rw 2014-05-06 13:20 Ringtones  

  13.   

  14. root@generic :/storage/sdcard # ll Android/data/  

  15. drwxrwx--- system sdcard_rw 2014-05-06 13:21 com.google.android.apps.maps  


4.4 设备:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. root@generic :/storage/sdcard # ll  

  2. drwxrwx--- root sdcard_r 2013-11-27 23:35 Alarms  

  3. drwxrwx--x root sdcard_r 2013-11-27 23:36 Android  

  4. drwxrwx--- root sdcard_r 2014-05-06 01:33 DCIM  

  5. drwxrwx--- root sdcard_r 2013-11-27 23:35 Download  

  6. drwxrwx--- root sdcard_r 2013-11-28 04:33 LOST.DIR  

  7. drwxrwx--- root sdcard_r 2013-11-27 23:35 Movies  

  8. drwxrwx--- root sdcard_r 2013-11-27 23:35 Music  

  9. drwxrwx--- root sdcard_r 2013-11-27 23:35 Notifications  

  10. drwxrwx--- root sdcard_r 2013-11-27 23:35 Pictures  

  11. drwxrwx--- root sdcard_r 2013-11-27 23:35 Podcasts  

  12. drwxrwx--- root sdcard_r 2013-11-27 23:35 Ringtones  

  13.   

  14. root@generic :/storage/sdcard # ll Android/data/  

  15. drwxrwx--- u0_a33 sdcard_r 2013-11-27 23:36 com.google.android.apps.maps  

  16.   

  17. root@generic :/storage/sdcard # ll Android/data/com.google.android.apps.maps/  

  18. drwxrwx--- u0_a33 sdcard_r 2013-11-27 23:36 cache  

  19. 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权限。

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. service sdcard /system/bin/sdcard -u 1023 -g 1023 -l /data/media /mnt/shell/emulated  

  2.     class late_start  

  3.   

  4. service fuse_sdcard1 /system/bin/sdcard -u 1023 -g 1023 -w 1023 -d /mnt/media_rw/sdcard1 /storage/sdcard1  

  5.     class late_start  

  6.     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的开发者。


本文转载自:http://blog.csdn.net/zjbpku/article/details/25161131

s
粉丝 43
博文 202
码字总数 0
作品 0
深圳
高级程序员
私信 提问
Android Q (Android 10.0)

通常,我们会在三月份的某个时候看到第一个开发人员的预览版。然后,在 Google I/O上,Google发布了另一个包含更多新功能和优化的开发人员预览版。最后,在八月的第一周,我们的手机上有了新...

desaco
03/18
0
0
Android知识点回顾之Manifest文件-上篇

定义:AndrodiManifest.xml文件为Android程序的入口文件,并且是必须的,位于整个项目的根目录下。拿到一个Android项目,可以先从AndroidManifest.xml文件入手,进行分析。它提供了一些必要的...

星泉毅
2017/11/02
0
0
Android应用正确使用扩展SD卡

Android 开发时如何正确获取使用扩展存储路径 先介绍一下Android的存储 在 2.x 版本中,Android设备都是单存储,第三方App写文件,必须申请 WRITEEXTERNALSTORAGE 权限; 在4.0之后,Android...

Cundong
2014/09/17
8.4K
1
Android平台通用安全问题分析及策略(一)

©著作权归作者所有:来自51CTO博客作者samsunglinux的原创作品,如需转载,请注明出处,否则将追究法律责任 安全Android移动平台信息安全 5 分享 微博QQ微信 收藏 上一篇:译著《Fedora和R...

samsunglinux
2018/07/02
0
0
Android Q Beta 5 外部存储访问权限的说明

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 https://blog.csdn.net/u013553529/article/details/99839095 目前最新是 Android Q Beta 5...

爱博客大伯
08/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

代理模式之JDK动态代理 — “JDK Dynamic Proxy“

动态代理的原理是什么? 所谓的动态代理,他是一个代理机制,代理机制可以看作是对调用目标的一个包装,这样我们对目标代码的调用不是直接发生的,而是通过代理完成,通过代理可以有效的让调...

code-ortaerc
今天
5
0
学习记录(day05-标签操作、属性绑定、语句控制、数据绑定、事件绑定、案例用户登录)

[TOC] 1.1.1标签操作v-text&v-html v-text:会把data中绑定的数据值原样输出。 v-html:会把data中值输出,且会自动解析html代码 <!--可以将指定的内容显示到标签体中--><标签 v-text=""></......

庭前云落
今天
8
0
VMware vSphere的两种RDM磁盘

在VMware vSphere vCenter中创建虚拟机时,可以添加一种叫RDM的磁盘。 RDM - Raw Device Mapping,原始设备映射,那么,RDM磁盘是不是就可以称作为“原始设备映射磁盘”呢?这也是一种可以热...

大别阿郎
今天
12
0
【AngularJS学习笔记】02 小杂烩及学习总结

本文转载于:专业的前端网站☞【AngularJS学习笔记】02 小杂烩及学习总结 表格示例 <div ng-app="myApp" ng-controller="customersCtrl"> <table> <tr ng-repeat="x in names | orderBy ......

前端老手
昨天
16
0
Linux 内核的五大创新

在科技行业,创新这个词几乎和革命一样到处泛滥,所以很难将那些夸张的东西与真正令人振奋的东西区分开来。Linux内核被称为创新,但它又被称为现代计算中最大的奇迹,一个微观世界中的庞然大...

阮鹏
昨天
20
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部