Context类中定义了获取手机系统目录的一些api。这里做一个总结:
一、api 注释翻译
1、File getExternalFilesDir(@Nullable String type)
@Nullable
public abstract File getExternalFilesDir(@Nullable String type);
/**
* Returns the absolute path to the directory on the primary shared/external
* storage device where the application can place persistent files it owns.
* These files are internal to the applications, and not typically visible
* to the user as media.
* <p>
* This is like {@link #getFilesDir()} in that these files will be deleted
* when the application is uninstalled, however there are some important
* differences:
* <ul>
* <li>Shared storage may not always be available, since removable media can
* be ejected by the user. Media state can be checked using
* {@link Environment#getExternalStorageState(File)}.
* <li>There is no security enforced with these files. For example, any
* application holding
* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to
* these files.
* </ul>
* <p>
* If a shared storage device is emulated (as determined by
* {@link Environment#isExternalStorageEmulated(File)}), it's contents are
* backed by a private user data partition, which means there is little
* benefit to storing data here instead of the private directories returned
* by {@link #getFilesDir()}, etc.
* <p>
* Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
* are required to read or write to the returned path; it's always
* accessible to the calling app. This only applies to paths generated for
* package name of the calling application. To access paths belonging to
* other packages,
* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} and/or
* {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required.
* <p>
* On devices with multiple users (as described by {@link UserManager}),
* each user has their own isolated shared storage. Applications only have
* access to the shared storage for the user they're running as.
* <p>
* The returned path may change over time if different shared storage media
* is inserted, so only relative paths should be persisted.
* <p>
* Here is an example of typical code to manipulate a file in an
* application's shared storage:
* </p>
* {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
* private_file}
* <p>
* If you supply a non-null <var>type</var> to this function, the returned
* file will be a path to a sub-directory of the given type. Though these
* files are not automatically scanned by the media scanner, you can
* explicitly add them to the media database with
* {@link android.media.MediaScannerConnection#scanFile(Context, String[], String[], android.media.MediaScannerConnection.OnScanCompletedListener)
* MediaScannerConnection.scanFile}. Note that this is not the same as
* {@link android.os.Environment#getExternalStoragePublicDirectory
* Environment.getExternalStoragePublicDirectory()}, which provides
* directories of media shared by all applications. The directories returned
* here are owned by the application, and their contents will be removed
* when the application is uninstalled. Unlike
* {@link android.os.Environment#getExternalStoragePublicDirectory
* Environment.getExternalStoragePublicDirectory()}, the directory returned
* here will be automatically created for you.
* <p>
* Here is an example of typical code to manipulate a picture in an
* application's shared storage and add it to the media database:
* </p>
* {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
* private_picture}
*
* @param type The type of files directory to return. May be {@code null}
* for the root of the files directory or one of the following
* constants for a subdirectory:
* {@link android.os.Environment#DIRECTORY_MUSIC},
* {@link android.os.Environment#DIRECTORY_PODCASTS},
* {@link android.os.Environment#DIRECTORY_RINGTONES},
* {@link android.os.Environment#DIRECTORY_ALARMS},
* {@link android.os.Environment#DIRECTORY_NOTIFICATIONS},
* {@link android.os.Environment#DIRECTORY_PICTURES}, or
* {@link android.os.Environment#DIRECTORY_MOVIES}.
* @return the absolute path to application-specific directory. May return
* {@code null} if shared storage is not currently available.
* @see #getFilesDir
* @see #getExternalFilesDirs(String)
* @see Environment#getExternalStorageState(File)
* @see Environment#isExternalStorageEmulated(File)
* @see Environment#isExternalStorageRemovable(File)
*/
函数api描述信息翻译如下:
getExternalFilesDir函数返回主要的共享/外部存储设备的目录的绝对路径,在这些路径上应用程序可以存放应用程序自身的持久性文件。这些持久性文件是程序内部的,通常不会作为媒体对用户可见。
当应用被卸载后,这些文件也会被删除掉,这有点类似于getFilesDir()函数。然而它们之间也有一些重要的不同点,如下:
- 共享存储可能不总是可用的,因为用户可以弹出可移动媒体设备。可以使用 Environment#getExternalStorageState(File)来检查媒体状态;
- 这些文件没有安全强制,比如,任何应用具有android.Manifest.permission#WRITE_EXTERNAL_STORAGE权限都可以更改这些文件;
如果共享存储设备是被模拟的(由Environment#isExternalStorageEmulated(File)决定),那么它的内容被私有用户数据分区支持,这意味着在这里存储数据是有一点好处的,而不是使用getFilesDir()返回的私有目录。
从android.os.Build.VERSION_CODES#KITKAT (sdk19,即android 4.4)开始,读取和写人这些返回的目录都不再需要任何权限。这些目录总是可被当前正在调用该函数的app访问的。这仅适用于为调用应用程序的包名称生成的路径。要访问属于其他包名的路径,需要获取android.Manifest.permission#WRITE_EXTERNAL_STORAGE和READ_EXTERNAL_STORAGE权限。
在多用户的设备上,每一个用户拥有自己独立的共享存储目录。应用程序仅仅可以访问当前正在运行用户的共享目录。
如果插入不同的共享存储介质,返回的路径可能会随着时间而改变,因此只应保留相对路径。
这里有一个在应用程序共享存储上操作文件通用代码的例子private_file,见链接:http://androidxref.com/9.0.0_r3/xref/development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
如果你传入了一个非空类型的参数到该函数中,返回的路径将会是给定目录的子目录。尽管媒体扫描仪不会自动扫描这些文件,但你可以使用MediaScannerConnection.scanFile明确地把它们添加到媒体数据库中。
需要注意它不同于Environment.getExternalStoragePublicDirectory(),后者提供被所有应用程序共享的媒体目录。这里返回的目录仅仅被应用程序自己拥有,并且当应用程序被卸载时这些目录也被删除。不同于Environment.getExternalStoragePublicDirectory(),这里返回的目录将会为你自动创建。
type参数说明:
type代表要返回的文件目录的类型,有可能为null或其他值。null代表文件目录的根目录,其他取值代表根目录的子目录,分别为:
Environment#DIRECTORY_MUSIC
Environment#DIRECTORY_PODCASTS
Environment#DIRECTORY_RINGTONES
Environment#DIRECTORY_ALARMS
Environment#DIRECTORY_NOTIFICATIONS
Environment#DIRECTORY_PICTURES
Environment#DIRECTORY_MOVIES
返回值说明:应用程序指定目录的绝对路径,如果共享存储当前不可用可能返回null。
参考:
Context#getFilesDir
Context#getExternalFilesDirs(String)
Environment#getExternalStorageState(File)
Environment#isExternalStorageEmulated(File)
Environment#isExternalStorageRemovable(File)
二、参考文章
都快写完了,还是没介绍函数返回的具体的路径是什么, 这里我补充一下吧:
- 该方法用于获得外部存储,地址为/storage/emulated/0/Android/data/packageName/files
- 该方法可传一个String类型的参数,表述为该路径下的文件夹,没有该文件夹会自动创建
- 使用方法
String path=context.getExternalFilesDir(null).getAbsolutePath();
File file=new File(path);
//输出:path:/storage/emulated/0/Android/data/backageName/files
String path2=context.getExternalFilesDir("UniApp").getAbsolutePath();
File file2=new File(path2);
//path:/storage/emulated/0/Android/data/packageName/files/UniApp
//如uniapp文件夹没有,则会自动创建
String path3=context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
File file3=new File(path3);
//path:/storage/emulated/0/Android/data/packageName/files/Download
String path4=context.getExternalFilesDir("").getAbsolutePath()+"/hhhhhh";
File file4=new File(path4);
//path:storage/emulated/0/Android/data/packageName/files/hhhhhh
//如果没有“hhhhhh”文件夹,则file4.exists()==false;
4.该目录主要是用来存放应用私有的一些文件。这个目录有几个特性:
自动删除
当应用卸载的时候,这些文件会被删除。当然前提是sd卡可用。其他应用访问
这些文件可以被其他应用访问,但是前提是其他应用有外部存储权限。但是注意在Android 11以后即使有存储权限,其他应用也不允许访问这些文件了。
存储权限
在Android api 19(即4.4)之后,本应用即使没有存储权限,也可以访问这些文件,虽然它们是在sd卡上。官方文档如下:Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
are required to read or write to the returned path; it’s always
accessible to the calling app. This only applies to paths generated for
package name of the calling application. To access paths belonging to
other packages,鉴于目前大部分App的minSdkVersion都是19或以上,所以当使用这个目录的时候,是没必要再请求存储权限的。
三、与getExternalFilesDirs的区别
我们来看看getExternalFilesDirs的注释:
* @return the absolute paths to application-specific directories. Some
* individual paths may be {@code null} if that shared storage is
* not currently available. The first path returned is the same as
* {@link #getExternalFilesDir(String)}.
getExternalFilesDirs函数返回的是:应用程序指定目录集合的绝对路径。如果共享存储当前不可用,一些独立路径集合可能为null。返回的第一个路径和getExternalFilesDir(String)是一样的。
下面我通过打断点调试查看下getExternalFilesDirs返回路径数组具体取值包含哪些内容: