转载自:https://blog.csdn.net/wl724120268/article/details/78275686
应用程序在运行的过程中如果需要向手机上保存数据,一般是把数据保存在SDcard中的。
大部分应用是直接在SDCard的根目录下创建一个文件夹,然后把数据保存在该文件夹中。
这样当该应用被卸载后,这些数据还保留在SDCard中,留下了垃圾数据。
如果你想让你的应用被卸载后,与该应用相关的数据也清除掉,该怎么办呢?
通过Context.getExternalFilesDir()方法可以获取到 SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据
通过Context.getExternalCacheDir()方法可以获取到 SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
如果使用上面的方法,当你的应用在被用户卸载后,SDCard/Android/data/你的应用的包名/ 这个目录下的所有文件都会被删除,不会留下垃圾信息。
而且上面二个目录分别对应 设置->应用->应用详情里面的”清除数据“与”清除缓存“选项
/data/data/package_name/ 目录
对应的目录名字为 /data/data/com.android.framework/。
该目录是只对应用可见的,而且如果手机没有 root,用普通权限的 adb 也看不了这个目录,该目录用来存储和应用周期相关的文件,会随着应用的卸载一起删除,相关的子目录如下所示:
/data/data/com.android.framework/shared_prefs/
用来存储 SharedPreference,对应函数为:getSharedPreferences(String fileName, int mode);
/data/data/com.android.framework/databases/
用来存储数据库 DB,相关函数还有 getDatabasePath();
/data/data/com.android.framework/app_webview 和 /data/data/com.android.framework/xxxwebviewcachexxx
来存储应用内置 webview 所产生的 cache 和 cookies 等,该目录由于 android 版本不同名字和位置也可能不同;
/data/data/com.android.framework/lib
用来存储该应用的 .so 静态库文件;
/data/data/com.android.framework/cache
该目录可以使用函数 getCacheDir() 获取;
/data/data/com.android.framework/files
该目录可以使用函数 getFilesDir() 获取,openFileInput() 和 openFileOutput() 函数也是在该目录下操作文件, fileList() 函数是用来列出该 files 目录下的所有文件,deleteFile(String name) 用来删除该 files 目录下的文件;
/data/data/com.android.framework/XXXX
这个目录下面当然也能够创建子集的目录,使用的方法就是 getDir(String name, int mode),参数中的 name 就是需要在该目录下创建的子目录名字。
如果能够打开应用的该目录,一般会在该目录下看到很多子目录。
PS:还有一个特别奇怪的函数,无意中看见的 getCodeCacheDir() 函数,该函数的解释为 This location is optimal for storing compiled or optimized code generated by your application at runtime,该目录适合在运行时存放应用产生的编译或者优化的代码,但是我调用就报了 NoSuchMethodError,不知道为什么,知道的可以告诉我。
另外还有其他两个相关函数:
getPackageCodePath() = /data/app/com.android.framework-1.apk;
getPackageResourcePath() = /data/app/com.android.framework-1.apk。
注:以上函数没有明确指定的都是使用 Context 调用。
SD 卡下的目录
SD 卡下的目录,顾名思义就是需要插入 SD 卡,当 SD 卡不可用时这两个目录都是无效的,SD 卡下面也分为应用的私有目录和共有目录,私有目录的生命周期也是和应用挂钩的,卸载之后就会被删除,共有目录不会随着应用的卸载而删除。
可以通过 Environment.getExternalStorageState() 函数来获取 SD 卡的挂载状态,当该函数返回 mounted 的时候,代表 SD 卡可用。
注意 SD 卡使用时需要注册相关权限:<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>。
SD 卡私有目录
该目录下的文件卸载应用之后会自动删除。
/sdcard/Android/data/package_name/
对应为 /sdcard/Android/data/com.android.framework/。
Android/data/com.android.framework/files/
该目录可用 getExternalFilesDir(String type) 和 getExternalFilesDirs(String type) 获取,参数 type 为子目录名字,null 则为根目录,后者调用之后会自动生成该目录,并且后者返回的是一个数组,如果插入外置存储卡,外置存储卡目录也会一并返回,具体区别可以查看后面的源码和结果;
Android/data/com.android.framework/cache/
该目录可用 getExternalCacheDir() 和 getExternalCacheDirs() 获取,后者调用之后自动生成该目录,和上面一样,后者返回的是一个数组,如果插入外置存储卡,外置存储卡目录也会一并返回,具体区别可以查看后面的源码和结果。
/sdcard/Android/obb/package_name/
对应为 /sdcard/Android/obb/com.android.framework/。
需要注意的是,obb 目录也可能不存在,原文:Note if the application does not have any OBB files, this directory may not exist,一般游戏 APP 会将游戏相关的数据包放到这个目录下。
该目录的的相关函数简单只有两个:getObbDirs() 和 getObbDir(),前者调用之后会自动生成该目录,后者在插入外置存储卡之后会在前者的基础上另外返回外置存储卡的 obb 目录,具体的结果可以查看后面的源码和结果。
SD 卡共有目录
该目录下的文件卸载应用之后还会留存,所以为了 SD 卡的整洁度,不要随便在 SD 卡的根目录下面创建文件,最好以应用名字创建一个目录,所有的需要卸载之后留存或者需要给其他应用共享的文件都放到该目录下,不要在根目录下创建文件,还有一个公司的多个应用最好共享一个目录,特别讨厌 360 ,恨不得把 360XXX 式的目录全部创建完才行,极其讨厌和反对。
/sdcard/(any_folder_name)
对应为 /sdcard/XXX。
Environment.getExternalStorageState()
这个函数用来获取 SD 卡的挂载状态,如果传入参数 path 则是获取该路径的的挂载状态,比如这个目录被用户的 PC 挂载,或者从设备中移除,或者其他问题发生,状态的返回是不一样的;
Environment.getExternalStorageDirectory()
该函数用来返回 SD 卡的根目录,即 /storage/emulated/0,注意不要在根目录下创建文件,强烈建立创建一个子目录去操作,要不然会污染 SD 卡的主目录,该目录所有应用都可操作,为共享目录;
Environment.getDownloadCacheDirectory()
该函数用来返回 SD 卡下面的下载缓存目录;
Environment.getDataDirectory()
该函数用来获取用户的数据目录;
Environment.getExternalStoragePublicDirectory(String type)
该函数用来根据类型返回相关目录,类型为 Environment 的一些变量,传入的类型参数不能是 null,返回的目录路径有可能不存在,所以必须在使用之前确认一下,没有就创建该目录;
Environment.getRootDirectory()
该函数用来返回根 System 目录,只挂载为只读;
源码及结果
注意:手机如果还能够SD卡扩展,就相当于能挂载两张SD卡,下面的测试结果也是两张SD卡的结果:
L.e("getDatabasePath():"+getDatabasePath("student.db"));L.e("getCacheDir():" + getCacheDir());L.e("getFilesDir():" + getFilesDir());String[] strings = fileList();for (String path : strings){//为空 L.e("fileList():---" + path);} L.e("getDir(\"zhao\"):" + getDir("zhao", MODE_PRIVATE));// L.e("getCodeCacheDir():" + getCodeCacheDir()); //java.lang.NoSuchMethodErrorL.e("getPackageCodePath():" + getPackageCodePath());L.e("getPackageResourcePath():" + getPackageResourcePath());L.e("getExternalFilesDir():" + getExternalFilesDir(null));File[] paths = getExternalFilesDirs(null);for (File path : paths){ L.e("getExternalFilesDirs():---" + path.getPath());} L.e("getExternalCacheDir():" + getExternalCacheDir());paths = getExternalCacheDirs();for (File path : paths){ L.e("getExternalCacheDirs():---" + path.getPath());} L.e("getObbDir():" + getObbDir());paths = getObbDirs();for (File path : paths){ L.e("getObbDirs():---" + path.getPath());} L.e("Environment.getExternalStorageState():"+ Environment.getExternalStorageState());L.e("Environment.getExternalStorageDirectory():"+Environment.getExternalStorageDirectory());L.e("Environment.getDownloadCacheDirectory():"+Environment.getDownloadCacheDirectory());L.e("Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC):"+Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC));L.e("Environment.getRootDirectory():"+Environment.getRootDirectory());12345678910111213141516171819202122232425262728293031
对应的结果为,注意看外部存储卡的路径:
E/com.android.framework﹕ getDatabasePath():/data/data/com.android.framework/databases/student.dbE/com.android.framework﹕ getCacheDir():/data/data/com.android.framework/cacheE/com.android.framework﹕ getFilesDir():/data/data/com.android.framework/filesE/com.android.framework﹕ getDir("zhao"):/data/data/com.android.framework/app_zhaoE/com.android.framework﹕ getPackageCodePath():/data/app/com.android.framework-1.apkE/com.android.framework﹕ getPackageResourcePath():/data/app/com.android.framework-1.apkE/com.android.framework﹕ getExternalFilesDir():/storage/emulated/0/Android/data/com.android.framework/filesE/com.android.framework﹕ getExternalFilesDirs():---/storage/emulated/0/Android/data/com.android.framework/filesE/com.android.framework﹕ getExternalFilesDirs():---/storage/ext_sd/Android/data/com.android.framework/files*******E/com.android.framework﹕ getExternalCacheDir():/storage/emulated/0/Android/data/com.android.framework/cacheE/com.android.framework﹕ getExternalCacheDirs():---/storage/emulated/0/Android/data/com.android.framework/cacheE/com.android.framework﹕ getExternalCacheDirs():---/storage/ext_sd/Android/data/com.android.framework/cache*******E/com.android.framework﹕ getObbDir():/storage/emulated/0/Android/obb/com.android.frameworkE/com.android.framework﹕ getObbDirs():---/storage/emulated/0/Android/obb/com.android.frameworkE/com.android.framework﹕ getObbDirs():---/storage/ext_sd/Android/obb/com.android.framework*******E/com.android.framework﹕ Environment.getExternalStorageState():mountedE/com.android.framework﹕ Environment.getExternalStorageDirectory():/storage/emulated/0E/com.android.framework﹕ Environment.getDownloadCacheDirectory():/cacheE/com.android.framework﹕ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC):/storage/emulated/0/MusicE/com.android.framework﹕ Environment.getRootDirectory():/system