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

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系统做出更好的该进。

在此感谢一下

id=nextapp.fx&hl=zh_CN">FX 文件管理工具的开发人员Tod
Liebeck
 在G+对我问题的及时解答及帮助。同一时候也感谢一下给

Tod Liebeck解决Kitkat外置sd文件操作方案的X-plore的开发人员。

Android 外部存储权限分析的更多相关文章

  1. Android外部存储

    WeTest 导读 外部存储作为开发中经常接触的一个重要系统组成,在Android历代版本中,有过许许多多重要的变更.我也曾疑惑过,为什么一个简简单单外部存储,会存在存在这么多奇奇怪怪的路径:/sdc ...

  2. Android外部存储 - 官方文档解读

    预备知识:External Storage Technical Information 摘要: "The WRITE_EXTERNAL_STORAGE permission must onl ...

  3. Android数据存储原理分析

    Android上常见的数据存储方式为: SharedPreferences是 Android 中比较常用的存储方法,本篇将从源码角度带大家分析一下Android中常用的轻量级数据存储工具SharedP ...

  4. Android - 数据存储 -存储文件

    Android使用的文件系统和其他平台的基本磁盘的文件系统很相似.这里将要介绍如何使用File API在Android文件系统中读写文件. File对象适合按顺序读写大量的数据.例如,适合图片文件或者 ...

  5. (数据存储)Android系统存储数据

    移动设备需要存储数据,处理数据并输出处理后的信息. 主题一:存储键值对 If you have a relatively small collection of key-values that you ...

  6. 彻底了解android中的内部存储与外部存储

    我们先来考虑这样一个问题: 打开手机设置,选择应用管理,选择任意一个App,然后你会看到两个按钮,一个是清除缓存,另一个是清除数据,那么当我们点击清除缓存的时候清除的是哪里的数据?当我们点击清除数据的 ...

  7. 彻底理解android中的内部存储与外部存储

    我们先来考虑这样一个问题: 打开手机设置,选择应用管理,选择任意一个App,然后你会看到两个按钮,一个是清除缓存,另一个是清除数据,那么当我们点击清除缓存的时候清除的是哪里的数据?当我们点击清除数据的 ...

  8. 【转】彻底理解android中的内部存储与外部存储

    我们先来考虑这样一个问题: 打开手机设置,选择应用管理,选择任意一个App,然后你会看到两个按钮,一个是清除缓存,另一个是清除数据,那么当我们点击清除缓存的时候清除的是哪里的数据?当我们点击清除数据的 ...

  9. android中的内部存储与外部存储

    我们先来考虑这样一个问题: 打开手机设置,选择应用管理,选择任意一个App,然后你会看到两个按钮,一个是清除缓存,另一个是清除数据,那么当我们点击清除缓存的时候清除的是哪里的数据?当我们点击清除数据的 ...

随机推荐

  1. JavaScript--引用JS外部文件

    通过前面知识学习,我们知道使用<script>标签在HTML文件中添加JavaScript代码,如图: JavaScript代码只能写在HTML文件中吗?当然不是,我们可以把HTML文件和 ...

  2. MySQL的安装和启动

    一.MySQL各类安装方法的比较 在Linux系统下,MySQL有3种主要的安装方式,分别是:RPM安装.二进制安装.源码安装.三种安装方式的优缺点如下表所示:   RPM安装 二进制安装 源码安装 ...

  3. Redis 的简单运算

    Redis 的简单运算 命令 说明 备注 incr key 在原字段上加 1 只能对整数操作 incrby key increment 在原字段上加上整数 (increment) 只能对整数操作 de ...

  4. Cookie localStorage sessionStorage

    三者的异同 特性 Cookie localStorage sessionStorage 数据的生命期 可设置失效时间,默认是关闭浏览器后失效 除非被清除,否则永久保存 仅在当前会话下(tab标签页)有 ...

  5. DeltaFish 校园物资共享平台 第七次小组会议

    DeltaFish 校园物资共享平台 第七次小组会议 一.上周进度报告 前端 娄:和李一起建立前后端交互参数文档,和数据库文档,完成前端页面跳转和图片加载的 bug,Git 上去. 刘:优化前端 ab ...

  6. canves应用

    canves用得好可以有好多效果: html:<canvas id="myCanvas" width="700" height="300&quo ...

  7. GitHub代码托管平台搭建

    GitHub代码托管平台搭建 注册账户以及创建仓库 要想使用github第一步当然是注册github账号了, github官网地址:https://github.com/. 之后就可以创建仓库了(免费 ...

  8. Codeforces_738B

    B. Spotlights time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  9. c#符号含义

    属性:(带手型图标)方法:(紫红色菱形)事件:(闪电)字段:(蓝色菱形) 还有很多,具体图标不好描述命名空间,类,接口,值类,枚举,清单或类信息项等

  10. B+树知识点

    B+树介绍   目录 B+树 B+树的插入操作 B+树的删除操作 回到顶部 B+树 B+树和二叉树.平衡二叉树一样,都是经典的数据结构.B+树由B树和索引顺序访问方法(ISAM,是不是很熟悉?对,这也 ...