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/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系統做出更好的該進。

在此感謝一下FX 文件管理工具的開發人員Tod Liebeck 在G+對我問題的及時解答及幫助。同一時候也感謝一下給

Tod Liebeck解決Kitkat外置sd文件操作方案的X-plore的開發人員。






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM