Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 外部存儲權限分析

Android 外部存儲權限分析

編輯:關於Android編程

不知道你有麼有發現,來自菜鳥的成長史: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喎?/kf/ware/vc/" target="_blank" class="keylink">vc2RjYXJkLmM8YnI+CjwvcD4KPHA+PGJyPgo8L3A+CjxwPjwvcD4KPHA+1No0LjTWrsewo6xmcmFtZXdvcmsgYXBpttS05rSivu0oc3RvcmFnZSB2b2x1bWVzKbXEstnX97Kiw7vT0LrctPO1xLjEseSjrMnosbjWxtTsycy/ydLUtLS9qLWluPahsHByaW1hcnmhsb7tu/LV37bguPahsHNlY29uZGFyeaGxPC9wPgo8cD6+7aOstvjV4tCpsrvNrLXEvu22vMTcsbvPtc2zt/7O8VN0b3JhZ2VNYW5hZ2Vyus1Nb3VudFNlcnZpY2W53MDto6zV4tbQx+m/9s/Ct8POyqGwcHJpbWFyeaGxsr+31r7Nz/G3w87KtaW49mV4dGVybmFsIHN0b3JhZ2XSu9H5oaM8L3A+CjxwPrrctuDJ6LG409BTZL+oo6y1q8rHtrzDu9PQsNHL/LWx1/dleHRlcm5hbCBzdG9yYWdlo6zKtbzKyc/V4r7NysfV4tCpyeixuLXEobBzZWNvbmRhcnkgdm9sdW1lobGho8D9yOejrMj90Me1xEdhbGF4ec+1wdC+zcrHyvTT2tXiPC9wPgo8cD7Su8Dgo6y008ioz963vcPmwLTLtaOsc2S/qMbkyrXP8c3isr+05rSivu3Su9H5sbu53MDto6y1q8rH1/fOqsnosbi1xKGwc2Vjb25kYXJ5IGV4dGVybmFsIHN0b3JhZ2U=",是沒有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的開發者。





  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved