日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android7.1获取存储权限,Android外部存储

發布時間:2023/12/20 Android 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android7.1获取存储权限,Android外部存储 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原標題:Android外部存儲

作者:莊燦杰,騰訊移動客戶端開發 工程師

商業轉載請聯系騰訊WeTest獲得授權,非商業轉載請注明出處。

原文鏈接:http://wetest.qq.com/lab/view/368.html

WeTest 導讀

外部存儲作為開發中經常接觸的一個重要系統組成,在Android歷代版本中,有過許許多多重要的變更。我也曾疑惑過,為什么一個簡簡單單外部存儲,會存在存在這么多奇奇怪怪的路徑:/sdcard、/mnt/sdacrd、/storage/extSdCard、/mnt/shell/emulated/0、/storage/emulated/0、/mnt/shell/runtime/default/emulated/0…其實,這背后代表了一項項技術的成熟與發布:模擬外部存儲、多用戶、運行時權限…

一、各版本外部存儲特性

1、Android 4.0

● 支持模擬外部存儲(通過FUSE實現)

● 出現了主外部存儲,以及二級外部存儲(沒有接口對外暴露)

● 支持MTP(Media Transfer Protocol)、PTP協議(Picture Transfer Protocol)

2、Android 4.1

● 開發者選項出現”強制應用聲明讀權限才可以進行讀操作”的開關

3、Android 4.2

● 支持多用戶,每個用戶擁有獨立的外部存儲

4、Android 4.4

● 讀操作需要聲明READ_EXTERNAL_STORAGE權限

● 應用讀寫在外部存儲的應用目錄(/sdcard/Android//)不需要聲明權限

● 增加了Context.getExternalFilesDirs() 接口,可以獲取應用在主外部存儲和其他二級外部存儲下的files路徑

● 引入存儲訪問框架(SAF,Storage Access Framework)

5、Android 6.0

● 外部存儲支持動態權限管理

● Adoptable Storage特性

6、Android 7.0

● 引入作用域目錄訪問

補充一個點:

如果應用的minSdkVersion和targetSdkVersion設置成<=3,系統會默認授予READ_EXTERNAL_STORAGE權限。

二、部分特性講解

1.模擬外部存儲

a. 必要性

● FAT32 屬于微軟專利,可能存在許可和法律問題(相關文章);

● 可以定制Android自己的外部存儲訪問規則;

● 為多用戶做鋪墊;

b. 實現原理

系統/system/bin/sdcard守護進程,使用FUSE實現類FAT格式SD卡文件系統的模擬,也就是我們經常說的內置SD卡。(詳細代碼可以參考:/xref/system/core/sdcard/sdcard.c)

用戶空間文件系統(Filesystem in

Userspace,簡稱FUSE)是一個面向類Unix計算機操作系統的軟件接口,它使無特權的用戶能夠無需編輯內核代碼而創建自己的文件系統。目前Linux通過內核模塊對此進行支持。

sdcard守護進程模擬外部存儲大致流程(Android 4.0為例):

● 首先,指定/data/media目錄用于模擬外部存儲。該路徑的owner和group一般為media_rw,這樣保證只有sdcard程序或root進程能夠訪問該目錄。

● sdcard守護進程啟動后,打開/dev/fuse設備。

● 在/mnt/sdcard目錄掛載fuse文件系統。

● 開線程,在線程中處理文件系統事件,并將結果寫回。

經過上面一系列步驟,sdcard進程在/mnt/sdcard路徑上創建了一個FUSE文件系統,所有對/mnt/sdcard將轉為事件由sdcard守護進程處理,并對應到/data/media目錄。

例如,應用創建/mnt/sdcard/a文件,實際是創建/data/media/a文件。

c. 優點

● 模擬外部存儲容量和/data分區是共享的,用戶數據在內外存儲的分配更加自由;

● 模擬外部存儲本身不可卸載,不會因為卸載導致應用訪問出現問題,也減少了外部因素導致被破壞的情況;

● 所有的訪問都經過sdcard守護進程,Android可以定制訪問規則;

d. 劣勢

● 性能上存在一定損失

e. 影響

● Android 6.0以后,由于動態權限管理的需要,會存在多個fuse掛載點,這導致inotify/FileObserver對外部存儲進行文件事件監控時,會丟失事件。

inotify是Linux核心子系統之一,做為文件系統的附加功能,它可監控文件系統并將異動通知應用程序。 ——

維基百科(https://zh.wikipedia.org/wiki/Inotify)

2、多用戶

a. 支持版本

● Android 4.2開始支持多用戶,但僅限平板;

● Android 5.0開始,設備制造商可以在編譯時候開啟多用戶模塊;

b. 背景知識

● 綁定掛載——mount —bind

MS_BIND (Linux 2.4 onward)

Perform a bind mount, making a file or a directory subtree visible at

another point within a file system. Bind mounts may cross file system

boundaries and span chroot(2) jails. The filesystemtype and

dataarguments are ignored. Up until Linux 2.6.26, mountflagswas also

ignored (the bind mount has the same mount options as the underlying

mount point). —— **mount(2) - Linux man page

圖例(來自https://xionchen.github.io/2016/08/25/linux-bind-mount):

1) 將/home目錄樹bind到/mnt/backup:

2) bind完成之后,對/mnt/backup的訪問將等同于對/home的訪問,原/mnt/backup變為不可見。

● 掛載命名空間

Mount namespaces provide isolation of the list of mount points seen by

the processes in each namespace instance. Thus, the processes in each

of the mount namespace instances will see distinct single-directory

hierarchies. ——mount_namespaces(7) - Linux manual page - man7.org

通俗的講,掛載命名空間實現了掛載點的隔離,在不同掛載命名空間的進程,看到的目錄層次不同。

● 掛載傳播之共享掛載、從屬掛載、私有掛載

掛載命名空間實現了完全的隔離,但對于有些情況并不適用。例如在Linux系統上,進程A在命名空間1掛載了一張CD-ROM,這時候命名空間2因為隔離無法看到這張CD-ROM。

為了解決這個問題,引入了掛載傳播(mount propagation)。傳播掛載定義了掛載點的傳播類型:

1)共享掛載,此類型的掛載點會加入一個peer group,并會在group內傳播和接收掛載事件;

2)從屬掛載,此類型的掛載點會加入一個peer group,并會接收group內的掛載事件,但不傳播;

3)共享/從屬掛載,上面兩種類型的共存體。可以從一個peer group(此時類型為從屬掛載)接收掛載事件,再傳播到另一個peer group;

4)私有掛載,此類型的掛載點沒有peer group,既不傳播也不接收掛載事件;

5)不可綁定掛載,不展開講;

peer group的形成條件為,一個掛載點被設置成共享掛載,并滿足以下任意一種情況:

1)掛載點在創建新的命名空間時被復制

2)從該掛載點創建了一個綁定掛載

另外再補充下傳播類型的轉換:

1)如果一個共享掛載是peer group中僅存的掛載點,那么對它應用從屬掛載將會導致它變為私有掛載。

2)對一個非共享掛載類型的掛載點,應用從屬掛載是無效的。

背景知識講到這里,其中掛載點的傳播類型比較不好理解,但很重要,可以參考上面mount namespace的Linux Programmer’s Manual里面的例子(搜索MS_XXX example)進行學習:http://man7.org/linux/man-pages/man7/mount_namespaces.7.html

c. 實現原理

概括多用戶的外部存儲隔離實現:應用進程在創建時,創建了新的掛載命名空間,然后通過綁定掛載對應用暴露當前用戶的外部存儲空間。

以Android 4.2代碼為例【mountEmulatedStorage(dalvik_system_Zygote.cpp)】:

● 首先獲取用戶id。在多用戶下,用戶id為應用uid/100000。

● 通過unshare方法創建新的掛載命名空間。

● 獲取外部存儲相關的環境變量。EXTERNAL_STORAGE環境變量是從舊版本沿襲下來的環境變量,記錄了外部存儲的傳統路徑。EMULATED_STORAGE_SOURCE環境變量,記錄綁定掛載的源路徑,注意應用是沒有權限進入這個目錄的。EMULATED_STORAGE_TARGET記錄綁定掛載的目標路徑,應用獲取的外部存儲路徑就在這個目錄下。

● 準備掛載路徑并進行綁定掛載。這里看mountMode為MOUNT_EXTERNAL_MULTIUSER時的執行分支,/mnt/shell/emulated/0將被綁定到/storage/emulated/0。如果是第二個用戶,則是/mnt/shell/emulated/1綁定到/storage/emulated/1,數字就是用戶id。注意這里是新的掛載命名空間,所以只有該應用看得到/storage/emulated/0下的綁定掛載,從adb shell下是看到的只能是個空目錄。

● 為了兼容以前的版本,將用戶的外部存儲路徑綁定到EXTERNAL_STORAGE環境變量指定的路徑。

3. 動態權限管理

a.背景

Android 6.0引入了運行時權限,允許用戶對危險權限進行動態授權,這部分權限包含外部存儲訪問權限。

b.實現原理

外部存儲訪問權限的動態授權,是利用FUSE和掛載命名空間這兩個技術配合實現。

通過下面這個提交記錄(https://android.googlesource.com/platform/system/core/+/f38f29c87d97cea45d04b783bddbd969234b1030%5E%21/#F1),我們可以很清楚的了解整個實現。

為了達到不殺死進程,就能夠賦予進程讀/寫外置存儲的目的,Android利用FUSE對/data/media模擬了三種訪問視圖,分別是default、read、write。

當應用被授予讀/寫權限時,vold子進程會切換到應用的掛載命名空間,將對應的視圖重新綁定到應用的外部存儲路徑上。

切換進程的掛載命名空間,需要內核版本在3.8及以上,切換函數為setns,ndk貌似沒有對開發者暴露,但可以在源碼里找到arm的實現,有需要直接編入就可以了,也就一個sys call。

c. 代碼分析

● 源碼版本:Android 6.0.0_r1

● 首先從/xref/system/core/sdcard/sdcard.c開始分析,僅摘取部分代碼,并加了些注釋:

● 應用進程創建時,大致流程如下(/xref/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp):

1)創建新的掛載命名空間;

2)將之前的掛載命名空間在/storage下的掛載全部去除,排除影響;

3)根據mount_mode,選擇一個路徑;

4)將選擇的路徑綁定到/storage下。

● 進程在運行時,當外部存儲的訪問許可發生改變(用戶授權)時,基本流程如下(/xref/system/vold/VolumeManager.cpp):

1)獲取init的掛載命名空間,為了對之后進程的掛載命2)名空間進行對比,如果一致,不重新綁定;

3)遍歷/proc下各個進程目錄,根據uid進行篩選;

找到對應的pid后,fork子進程進行重新掛載,這里用到setns進行掛載命名空間的切換;

重新掛載部分的邏輯和應用進程創建時基本一致,不難理解。

騰訊WeTest提供上千臺真實手機,隨時隨地進行測試,保障應用/手游品質。節省百萬硬件費用,加速敏捷研發流程。

同時騰訊WeTest兼容性測試團隊積累了10年的手游測試經驗,旨在通過制定針對性的測試方案,精準選取目標機型,執行專業、完整的測試用例,來提前發現游戲版本的兼容性問題,針對性地做出修正和優化,來保障手游產品的質量。目前該團隊已經支持所有騰訊在研和運營的手游項目

歡迎進入:http://wetest.qq.com/product/cloudphone 體驗安卓真機

歡迎進入:http://wetest.qq.com/product/expert-compatibility-testing 使用專家兼容測試服務。WeTest兼容性測試團隊期待與您交流!You Create,We Test!

如果對使用當中有任何疑問,歡迎聯系騰訊WeTest企業QQ:800024531返回搜狐,查看更多

責任編輯:

總結

以上是生活随笔為你收集整理的android7.1获取存储权限,Android外部存储的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。