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上面的访问没有进行验证。