Android应用获取外部盘符时,默认创建Android/data/包名/files目录
16lz
2021-01-26
在应用App的代码中调用如下代码:
context.getExternalFilesDir("");
这段代码,会在主动创建目录:./Android/data/包名/files;
我们来一下这个调用栈:
buildPaths:934, Environment (android.os)buildExternalStorageAppFilesDirs:131, Environment$UserEnvironment (android.os)buildExternalStorageAppFilesDirs:686, Environment (android.os)getExternalFilesDirs:633, ContextImpl (android.app)getExternalFilesDir:626, ContextImpl (android.app)getExternalFilesDir:242, ContextWrapper (android.content)getFile:98, MainActivity (cn.rocky)access$100:25, MainActivity (cn.rocky)handleMessage:83, MainActivity$1 (cn.rocky)dispatchMessage:106, Handler (android.os)loop:164, Looper (android.os)main:6548, ActivityThread (android.app)invoke:-1, Method (java.lang.reflect)run:438, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)main:857, ZygoteInit (com.android.internal.os)
这些代码一个来分析一下:
frameworks/base/core/java/android/content/Context.java
public abstract File getExternalFilesDir(@Nullable String type);
上面的实现代码:frameworks/base/core/java/android/app/ContextImpl.java
@Override public File getExternalFilesDir(String type) { // Operates on primary external storage final File[] dirs = getExternalFilesDirs(type); return (dirs != null && dirs.length > 0) ? dirs[0] : null; } @Override public File[] getExternalFilesDirs(String type) { synchronized (mSync) { File[] dirs = Environment.buildExternalStorageAppFilesDirs(getPackageName()); if (type != null) { dirs = Environment.buildPaths(dirs, type); } return ensureExternalDirsExistOrFilter(dirs); } } /** * Ensure that given directories exist, trying to create them if missing. If * unable to create, they are filtered by replacing with {@code null}. */ private File[] ensureExternalDirsExistOrFilter(File[] dirs) { File[] result = new File[dirs.length]; for (int i = 0; i < dirs.length; i++) { File dir = dirs[i]; if (!dir.exists()) {//判断目录是否存在,如果不存在,走if if (!dir.mkdirs()) {//创建目录,创建目录失败,走if,否则走else // recheck existence in case of cross-process race if (!dir.exists()) {//再次判断目录是否存在,不存在,走if,通过binder服务来创建目录,因为可能是权限不够导致 // Failing to mkdir() may be okay, since we might not have // enough permissions; ask vold to create on our behalf. final IStorageManager storageManager = IStorageManager.Stub.asInterface( ServiceManager.getService("mount")); try { final int res = storageManager.mkdirs( getPackageName(), dir.getAbsolutePath()); if (res != 0) { Log.w(TAG, "Failed to ensure " + dir + ": " + res); dir = null; } } catch (Exception e) { Log.w(TAG, "Failed to ensure " + dir + ": " + e); dir = null; } } } } result[i] = dir; } return result; }
frameworks/base/core/java/android/os/Environment.java
public static final String DIR_ANDROID = "Android"; private static final String DIR_DATA = "data"; private static final String DIR_OBB = "obb"; private static final String DIR_FILES = "files"; /** * Generates the path to an application's files. * @hide */ public static File[] buildExternalStorageAppFilesDirs(String packageName) { throwIfUserRequired(); return sCurrentUser.buildExternalStorageAppFilesDirs(packageName); } /** * Append path segments to each given base path, returning result. * * @hide */ public static File[] buildPaths(File[] base, String... segments) { File[] result = new File[base.length]; for (int i = 0; i < base.length; i++) { result[i] = buildPath(base[i], segments); } return result; } /** * Append path segments to given base path, returning result. * 循环创建目录结构 * @hide */ public static File buildPath(File base, String... segments) { File cur = base; for (String segment : segments) { if (cur == null) { cur = new File(segment); } else { cur = new File(cur, segment); } } return cur; } /** {@hide} */ public static class UserEnvironment { //获取外部的盘符根目录 public File[] getExternalDirs() { final StorageVolume[] volumes = StorageManager.getVolumeList(mUserId, StorageManager.FLAG_FOR_WRITE); final File[] files = new File[volumes.length]; for (int i = 0; i < volumes.length; i++) { files[i] = volumes[i].getPathFile(); } return files; } //构造目录结构 public File[] buildExternalStorageAppFilesDirs(String packageName) { return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName, DIR_FILES); } }
这里的代码比较简单,至此,所有挂载的盘符都已经了对应用的Android/data/包名/files目录;
更多相关文章
- SVN问题之——org.apache.subversion.javahl.ClientException: A
- Android(安卓)proguard -applymapping 导致编译错误
- android JNI入门 之helloworld
- Android(安卓)逐帧动画创建实例详解
- android 目录下三种尺寸的 drawable 文件夹
- Android安装常见错误解决办法
- 《第一行代码》学习笔记 第 3 章
- Android(安卓)失去焦点,关闭弹出的软键盘
- Android(安卓)Studio中的跨进程访问(aidl)