0


android 各种存储目录使用总结之Context#getExternalFilesDir

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(),这里返回的目录将会为你自动创建。

    这里有一个在应用程序共享存储中操作图片和增加图片到媒体数据库中的通用代码的例子private_picture。见链接http://androidxref.com/9.0.0_r3/xref/development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java

    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)

二、参考文章

都快写完了,还是没介绍函数返回的具体的路径是什么, 这里我补充一下吧:

  1. 该方法用于获得外部存储,地址为/storage/emulated/0/Android/data/packageName/files
  2. 该方法可传一个String类型的参数,表述为该路径下的文件夹,没有该文件夹会自动创建
  3. 使用方法 ​String path=context.getExternalFilesDir(null).getAbsolutePath();File file=new File(path);//输出:path:/storage/emulated/0/Android/data/backageName/filesString 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/DownloadString 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返回路径数组具体取值包含哪些内容:

** 参考文章:**

1、getExternalFilesDir到底是什么_BennuCTech的博客-CSDN博客_getexternalfilesdir

2、【Android】getExternalFilesDir()内部参数_聪明努力的积极向上的博客-CSDN博客_android getexternalfilesdir

3、Android 兼容系列文章五之存储卡 - 掘金

标签: android java

本文转载自: https://blog.csdn.net/liuqinhou/article/details/127177192
版权归原作者 小刘学安卓 所有, 如有侵权,请联系我们删除。

“android 各种存储目录使用总结之Context#getExternalFilesDir”的评论:

还没有评论