P90訪問SDCard
之前的文章說過,SDCard在O到P上有重大改動。在P上必須使用storageVolume.createAccessIntent
if (storageVolume!=null&&canFindPath){
Intent intent = storageVolume.createAccessIntent(getDirectoryName("DCIM"));//
permissionPath=storagePath + File.separator+"DCIM";
startActivityForResult(intent, OPEN_DIRECTORY_REQUEST_CODE);
}
Q100上的改動
在Q上又有了一些改動,storageVolume.createAccessIntent一些action被禁用
* @deprecated Callers should migrate to using {@link Intent#ACTION_OPEN_DOCUMENT_TREE} instead.
* Launching this {@link Intent} on devices running
* {@link android.os.Build.VERSION_CODES#Q} or higher, will immediately finish
* with a result code of {@link android.app.Activity#RESULT_CANCELED}.
P90上的frameworks層啓動log
實際上,P上通過storageVolume.createAccessIntent獲得intent,請求權限,啓動的是system.ui下面的ScopedAccessActivity
10-05 14:22:56.073 6246-6246/? D/GrantPermissionHelper: getSdCardPermission startActivityForResult intent Intent { act=android.os.storage.action.OPEN_EXTERNAL_DIRECTORY (has extras) }
10-05 14:22:56.077 1520-2111/system_process I/ActivityTaskManager: START u0 {act=android.os.storage.action.OPEN_EXTERNAL_DIRECTORY cmp=com.android.documentsui/.ScopedAccessActivity (has extras)} from uid 10147 pid 6246
10-05 14:22:56.080 1520-2111/system_process D/BoostFramework: perfHint : hint: 0x1081 pkg_name(userDataStr): android duration(userData1): -1 type(userData2): 1
10-05 14:22:56.080 1520-1606/system_process I/system_server: Compiler filter for /data/app/com.htc.zero-V5KQqHfsFhUeIDCLbDnbRA==/oat/arm64/base.odex is quicken
10-05 14:22:56.080 1520-1606/system_process I/system_server: Compiler filter for /data/app/com.htc.zero-V5KQqHfsFhUeIDCLbDnbRA==/oat/arm64/base.odex is quicken
10-05 14:22:56.084 1520-1606/system_process I/ActivityTaskManager: Displayed com.htc.zero/.activity.GrantPermissionActivity: +514ms
Q100上frameworks一些類被禁用
但是在Q上ScopedAccessActivity被廢棄,禁止通過代碼StorageVolume#createAccessIntent(String)直接申請某個目錄的讀寫權限
建議使用Callers should migrate to using {@link Intent#ACTION_OPEN_DOCUMENT_TREE} instead
這個intent會打開一個文件目錄讓用戶自己選擇授權的目錄,給了用戶更多的選擇權,禁止了應用私自申請目錄權限創建文件。
相當於進一步規範了SDCard目錄
26/**
27 * Activity responsible for handling {@link StorageVolume#createAccessIntent(String)}.
28 *
29 * @deprecated This class handles the deprecated {@link StorageVolume#createAccessIntent(String)}.
30 */
31@Deprecated
32public class ScopedAccessActivity extends Activity {
33 @Override
34 public void onCreate(Bundle savedInstanceState) {
35 super.onCreate(savedInstanceState);
36 logInvalidScopedAccessRequest(SCOPED_DIRECTORY_ACCESS_DEPRECATED);
37 setResult(RESULT_CANCELED);
38 finish();
39 }
40}
==================----------------------------------------======================
三方應用Android 4.4之後不能直接對外置SD卡通過FileOutputStream寫數據,只能通過DocumentFile這個接口來實現
Android 6.0 運行時權限
系統應用Android 9.0之後不能直接對外置SD卡通過FileOutputStream寫數據,只能通過DocumentFile這個接口來實現
AndroidQ上禁止通過代碼StorageVolume#createAccessIntent(String)直接申請某個目錄的讀寫權限
只能使用Intent#ACTION_OPEN_DOCUMENT_TREE讓用戶選擇某個目錄
Android R上 對ACTION_OPEN_DOCUMENT_TREE 或 ACTION_OPEN_DOCUMENT也進行了限制
改爲使用MANAGE_EXTERNAL_STORAGE進行大量的文件操作
==================----------------------------------------======================
Android 4.4(API 19 級)引入了存儲訪問框架 (SAF)
尾註:
- 從4.4開始google開始規範SDCard卡讀寫問題,旨在保護用戶空間和規範空間使用。
- 讓程序員更不容易操作存儲空間目錄。
- P90上強制執行,刪除了SDCard寫權限,必須使用DocumentFile進行存儲訪問。
- Q上對DocumentFile的訪問方式也進行了限制,讓程序員無法直接申請想要讀寫的路徑,改爲用戶去選擇給app的訪問路徑。
- R上進一步對ACTION_OPEN_DOCUMENT_TREE 或 ACTION_OPEN_DOCUMENT進行限制,
無法再使用 ACTION_OPEN_DOCUMENT_TREE intent 操作來請求訪問以下目錄:
1.Downloads 根目錄。
2.設備製造商認爲可靠的各個 SD 卡卷的根目錄,無論該卡是模擬卡還是可移除的卡。
無法再使用 ACTION_OPEN_DOCUMENT_TREE 或 ACTION_OPEN_DOCUMENT intent 操作來請求用戶從以下目錄中選擇單獨的文件:
3.Android/data/ 目錄及其所有子目錄。
4.Android/obb/ 目錄及其所有子目錄。
以上 是各個版本對存儲進行的限制訪問。
由於公司項目只做到Q,P上面的方式已經驗證可行,Q上被棄用的方式也跟蹤了源碼進行驗證。讓用戶選擇路徑不符合app設計,也由底層frameworks那邊直接授權,所以不需要使用DocumentFile,R上面的訪問沒有進行驗證。