編輯:關於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
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應用開發實例方法,文章步驟如下所示:1 獲取應用所需的數據源數據源一般來源於互聯網、個人搜集或者其他方式2 應用UI設計每個應用軟件都需要
效果圖知識點分析效果圖來看不復雜內容並沒多少,值得介紹一下的知識點也就下面幾個吧- 列表標題懸停- 左右列表滑動時聯動- 添加商品時的拋物線動畫- 底部彈出購物車清單-
了解Android繪圖或者自定義View的同學,都知道Canvas類、Paint類等。今天就來看看Paint的有關描述。首先看看官網的定義:The Paint class
一、數據綁定框架DataBinding介紹:Android的新框架DataBinding給我們帶來了很大的方便,以前可能需要在每個Activity裡寫很多的findVie