SAF是通过何种方式访问文件系统的 , MediaStore API ? File API ? Native Code ?SAF为何能访问Android/data目录存储访问框架(SAF)简介
为方便后续讲解,先简单回顾下SAF

文章插图
SAF架构
APP:
com.example.photos就是我们自己的APP
System UI:
com.google.android.documentsui,一般称作DoucmentUI,就是上文中启动的授权界面APP,它只是个UI壳子
DocumentProvider:
DocumentUI中数据的提供者,这个Provider可以有很多 com.android.externalstorage,是本地文件系统的Provider
关于SAF更详细介绍,请参考官方存储访问框架 经过SAF的简单介绍 , 分析目标很明确,那就是com.android.externalstorage
SAF是通过何种方式访问文件系统的
先安利几个AOSP源码查看网址:
https://cs.android.com/android/platform/superproject/http://aospxref.com/PS:后文源码链接都用的是XREF,方便国内查看
从DocumentFile#listFile入手,经过源码跟踪会发现最终会调用 DocumentsProvider#queryChildDocuments方法
public abstract class DocumentsProvider extends ContentProvider { ....... @Overridepublic final Cursor query(Uri uri, String[] projection, Bundle queryArgs, CancellationSignal cancellationSignal) {switch (mMatcher.match(uri)) {......case MATCH_CHILDREN:case MATCH_CHILDREN_TREE:.......return queryChildDocuments(getDocumentId(uri), projection, queryArgs);......default:throw new UnsupportedOperationException("Unsupported Uri "uri);}} catch (FileNotFoundException e) {Log.w(TAG, "Failed during query", e);return null;}} ......}接下来看看com.android.externalstorage中DocumentProvider的实现类 ExternalStorageProvider:frameworks/base/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
import com.android.internal.content.FileSystemProvider;public class ExternalStorageProvider extends FileSystemProvider queryChildDocuments的实现位于其父类 FileSystemProvider
public abstract class FileSystemProvider extends DocumentsProvider {......private Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder,@NonNull Predicate filter) throws FileNotFoundException {final File parent = getFileForDocId(parentDocumentId);final MatrixCursor result = new DirectoryCursor(resolveProjection(projection), parentDocumentId, parent);if (parent.isDirectory()) {//重点是这行for (File file : FileUtils.listFilesOrEmpty(parent)) {if (filter.test(file)) {includeFile(result, null, file);}}} else {Log.w(TAG, "parentDocumentId '"parentDocumentId"' is not Directory");}return result;} ......}FileUtils#listFilesOrEmpty
/** {@hide} */public static @NonNull File[] listFilesOrEmpty(@Nullable File dir) {return (dir != null) ? ArrayUtils.defeatNullable(dir.listFiles()): ArrayUtils.EMPTY_FILE;}至此 , 第一个问题,已经理清:SAF的ExternalStorageProvider最终也是通过File API来访问文件系统的
那么第二个问题,就很自然地来了,都是File API操作,为何我们的APP就不能访问呢?
SAF为何能访问Android/data目录
既然,SAF和我们的APP都是File API操作,那我们就去看看com.android.externalstorage属于哪些用户组 。adb shell 查查com.android.externalstorage进程的用户组
#查进程ID generic_x86_arm:/ $ ps -A|grep com.android.external u0_a64 16233 296 1256792 85960 0 0 S com.android.externalstorage #查进程所属的用户组
generic_x86_arm:/ $ cat /proc/16233/statusName:externalstorageUmask:0077State:S (sleeping)Tgid:16233Ngid:0Pid:16233PPid:296TracerPid:0Uid:10064100641006410064Gid:10064100641006410064FDSize: 64#重点关注这行输出Groups: 1015 1077 1078 1079 9997 20064 50064拿着这些神秘的GID在前面介绍的网址中一搜,就会很容易地发现GID的定义类 android_filesystem_config.h
#define AID_SDCARD_RW 1015/* external storage write access */#define AID_EXTERNAL_STORAGE 1077 /* Full external storage access including USB OTG volumes */#define AID_EXT_DATA_RW 1078/* GID for app-private data directories on external storage */#define AID_EXT_OBB_RW 1079/* GID for OBB directories on external storage */#define AID_EVERYBODY 9997/* shared between all apps in the same profile */其中1078和1079分别对应Android/data和Android/obb的访问权限 如果我们APP能通过某种方式获取到1078和1079的用户组权限,岂不妙哉?遗憾的是,对于三方APP这是不可能的,除非是手机厂商的预置的系统APP
- 手机连接u盘怎么看电影,怎么用手机看u盘里的电影
- 如何在手机上查看cad图纸,手机怎么看cad的图纸
- 手机序列号怎么查看,手机序列号在哪边查询
- 手机上怎么查公积金有多少钱,手机查公积金怎么查
- 通用k宝最高可转多少,通用k宝怎么用
- mate40怎么连接耳机「Mate50系接有线耳塞/耳机的方法」
- 华为p20pro自动重启怎么解决,华为p20pro老是重启
- 华为荣耀手机怎么检测声音设备音质,华为扬声器突然没声音
- 手机流畅度怎么测用远控1s测系统有诀窍华为小米都好用
- 鲫鱼用高压锅怎么做 高压锅酱焖鲫鱼的做法
