Android系统中的目录结构
首先通过工具Android Device Monitor中中的File Explorer直观的看一下Android系统的目录结构:
可以看到有很多很常见的目录,比如cache、data、mnt、sdcard、storage和system目录,下面我们就来看看这些常见的子目录?
1> cache目录
用来保存下载或者缓存的内容。
获取cache目录路径的方式如下:
Log.d("chenyang", "Environment.getDownloadCacheDirectory() = " + Environment.getDownloadCacheDirectory().getAbsolutePath());
运行结果:
03-21 04:57:22.831 1828-1828/? D/chenyang: Environment.getDownloadCacheDirectory() = /cache
2> data目录:
用来保存用户数据的目录
1> data目录路径的获取方式如下:
Log.d("chenyang", "Environment.getDataDirectory() = " + Environment.getDataDirectory().getAbsolutePath());
运行结果:
03-21 04:57:22.831 1828-1828/? D/chenyang: Environment.getDataDirectory() = /data
2> 子目录/data/user/0/com.cytmxk.test/files:
使用openFileOutput方法创建的文件在文件系统上保存位置的绝对路径。
获取绝对路径的方式:
Log.d("chenyang", "Context.getFilesDir() = " + getContext().getFilesDir().getAbsolutePath());
Log.d("chenyang", "Context.getFileStreamPath(\"\") = " + getContext().getFileStreamPath("").getAbsolutePath());
运行结果:
03-21 04:57:22.836 1828-1828/? D/chenyang: Context.getFilesDir() = /data/user/0/com.cytmxk.test/files
03-21 04:57:22.836 1828-1828/? D/chenyang: Context.getFileStreamPath("") = /data/user/0/com.cytmxk.test/files
如果想要快速的获取/data/user/0/com.cytmxk.test/files目录下指定名称的目录/文件,可以通过下面的方式:
Log.d("chenyang", "Context.getFileStreamPath(\"file1\") = " + getContext().getFileStreamPath("file1").getAbsolutePath());
运行结果:
03-21 04:57:22.836 1828-1828/? D/chenyang: Context.getFileStreamPath("file1") = /data/user/0/com.cytmxk.test/files/file1
注意:上面的两个方法的返回路径会发生改变,如果调用上面两个方法的app被移动到adopted storage device,
那么返回路径可能会随时间变化。
3> 子目录 /data/user/0/com.cytmxk.test/cache:
app缓存目录在文件系统上的绝对路径。缓存目录下的文件将是设备在存储空间不足时首先被删除的文件。
不能保证缓存目录下的文件何时被删除。
不应该依赖系统为你删除缓存目录下的文件; 应该设置一个合理的最大值,
例如1 MB,当超过1 MB时你应该修剪缓存目录下的文件,如果您的应用需要更大的缓存(大于1 MB),
则应该使用getExternalCacheDir()方法。
获取绝对路径的方式:
Log.d("chenyang", "Context.getCacheDir() = " + getContext().getCacheDir().getAbsolutePath());
运行结果:
03-21 04:57:22.836 1828-1828/? D/chenyang: Context.getCacheDir() = /data/user/0/com.cytmxk.test/cache
注意:上面的方法的返回路径会发生改变,如果调用上面方法的app被移动到adopted storage device,
那么返回路径可能会随时间变化。
4> 子文件 /data/user/0/com.cytmxk.test/databases/hhsh:
使用openOrCreateDatabase方法创建的名称为"hhsh"的数据库文件在文件系统上保存位置的绝对路径。
获取绝对路径的方式:
Log.d("chenyang", "Context.getDatabasePath(\"hhsh\") = " + getContext().getDatabasePath("hhsh"));
运行结果:
03-21 04:57:22.838 1828-1828/? D/chenyang: Context.getDatabasePath("hhsh") = /data/user/0/com.cytmxk.test/databases/hhsh
注意:上面的方法的返回路径会发生改变,如果调用上面方法的app被移动到adopted storage device,
那么返回路径可能会随时间变化。
5> 子文件/data/app/com.cytmxk.folder-1/base.apk:
当前apk的主Android包的完整路径。 Android包是一个ZIP文件,其中包含应用程序的主要代码、assets和主要resources。
获取绝对路径的方式:
Log.d("chenyang", "Context.getPackageCodePath() = " + getContext().getPackageCodePath());
Log.d("chenyang", "Context.getPackageResourcePath() = " + getContext().getPackageResourcePath());
运行结果:
03-21 04:57:22.838 1828-1828/? D/chenyang: Context.getPackageCodePath() = /data/app/com.cytmxk.test-1/base.apk
03-21 04:57:22.838 1828-1828/? D/chenyang: Context.getPackageResourcePath() = /data/app/com.cytmxk.test-1/base.apk
6> 子目录/data/user/0/com.cytmxk.test/app_svcv:
通过getDir("svcv", Context.MODE_PRIVATE)方法在/data/user/0/com.cytmxk.test/app_svcv目录
不存在的情况下创建该新目录,app可以在其中放置自己的自定义数据文件。
可以使用该方法返回的File对象来创建和访问此目录中的文件。
请注意,通过返回的File对象创建的文件只能由该app访问; 你只能设置整个目录的模式(只能是MODE_PRIVATE模式),而不是单个文件。
获取绝对路径的方式:
Log.d("chenyang", "getContext().getDir(\"svcv\", Context.MODE_PRIVATE) = " + getContext().getDir("svcv", Context.MODE_PRIVATE).getAbsolutePath());
运行结果:
03-21 04:57:22.837 1828-1828/? D/chenyang: getContext().getDir("svcv", Context.MODE_PRIVATE) = /data/user/0/com.cytmxk.test/app_svcv
注意:上面的方法的返回路径会发生改变,如果调用上面方法的app被移动到adopted storage device,
那么返回路径可能会随时间变化。
7> 子目录/data/user/0:
从上图中可以看到该目录被链接到/data/data目录,
因此上面的2>、3>、4>和6>对应的绝对路径也就是/data/data目录下对应的路径。
3> system目录
对于这个文件夹下常用的子目录解释如下:
/system/app
在这个目录下的程序为系统默认程序(如:信息、音乐播放器、相机等),自己安装的apk将不会出现在这里,
而是在/data/app目录中。
/system/bin
从bin目录名称可以看出都是二进制的可执行文件,里面主要是Linux系统自带的组件(命令)
/system/etc
从目录名称来看保存的都是系统的配置文件,比如APN、GPS配置等核心配置。
/system/fonts
存放系统字体的目录。
/system/framework
从后缀名为jar可以看出主要是用来保存系统Application Framework层框架的目录。具体可以对照下图:
/system/lib
该目录中存放的是Libraries和Android RunTime中对应的so库文件。具体可以对照下图:
/system/media/audio
该目录用来保存系统提示音、闹铃声对应的ogg文件。
4> mnt、sdcard和storage目录:
由图一可以知道如下关系:
上图中的/storage/emulated/0目录就是Android中的主要外部存储目录(可以手动在设置中设置内置sdcard或者外置sdacrd作为主要外部存储目录),当app的缓存比较大时,可以在该目录下(例如 /storage/emulated/0/Android/data/com.cytmxk.test/cache)保存缓存。
下面我们来看看Android中的主要外部存储目录:
1> /storage/emulated/0目录:
主要的外部存储目录
获取绝对路径的方式:
Log.d("chenyang", "Environment.getExternalStoragePublicDirectory(\"\") = " + Environment.getExternalStoragePublicDirectory("").getAbsolutePath());
Log.d("chenyang", "Environment.getExternalStorageDirectory() = " + Environment.getExternalStorageDirectory().getAbsolutePath());
运行结果:
04-02 02:25:54.449 24108-24108/? D/chenyang: Environment.getExternalStoragePublicDirectory("") = /storage/emulated/0
04-02 02:25:54.451 24108-24108/? D/chenyang: Environment.getExternalStorageDirectory() = /storage/emulated/0
2> 子目录/storage/emulated/0/xxx:
主要的外部存储目录下放置特定类型文件的目录。 用户放置和管理自己文件的目录。
获取绝对路径的方式:
Log.d("chenyang", "Environment.getExternalStoragePublicDirectory(\"dir1\") = " + Environment.getExternalStoragePublicDirectory("dir1").getAbsolutePath());
Log.d("chenyang", "Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath());
运行结果:
04-02 02:25:54.449 24108-24108/? D/chenyang: Environment.getExternalStoragePublicDirectory("dir1") = /storage/emulated/0/dir1
04-02 02:25:54.450 24108-24108/? D/chenyang: Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) = /storage/emulated/0/Music
3> 子目录/storage/emulated/0/Android/data/com.cytmxk.test/cache:
主要的外部存储目录下应用程序放置其缓存文件的目录。
获取绝对路径的方式:
Log.d("chenyang", "Context.getExternalCacheDir() = " + getContext().getExternalCacheDir().getAbsolutePath());
运行结果:
04-02 02:25:54.452 24108-24108/? D/chenyang: Context.getExternalCacheDir() = /storage/emulated/0/Android/data/com.cytmxk.test/cache
4> 子目录/storage/emulated/0/Android/data/com.cytmxk.test/files:
主要的外部存储目录下应用程序放置其持有的文件的目录。
获取绝对路径的方式:
Log.d("chenyang", "Context.getExternalFilesDir(\"\") = " + getContext().getExternalFilesDir("").getAbsolutePath());
Log.d("chenyang", "Context.getExternalFilesDir(\"file1\") = " + getContext().getExternalFilesDir("file1").getAbsolutePath());
Log.d("chenyang", "Context.getExternalFilesDir(Environment.DIRECTORY_MUSIC) = " + getContext().getExternalFilesDir(Environment.DIRECTORY_MUSIC).getAbsolutePath());
运行结果:
04-02 02:25:54.453 24108-24108/? D/chenyang: Context.getExternalFilesDir("") = /storage/emulated/0/Android/data/com.cytmxk.test/files
04-02 02:25:54.454 24108-24108/? D/chenyang: Context.getExternalFilesDir("file1") = /storage/emulated/0/Android/data/com.cytmxk.test/files/file1
04-02 02:25:54.455 24108-24108/? D/chenyang: Context.getExternalFilesDir(Environment.DIRECTORY_MUSIC) = /storage/emulated/0/Android/data/com.cytmxk.test/files/Music
App的缓存管理
对于现在Android App而言,获取缓存的大小和清除缓存是App的缓存管理的主要功能。下面我们就来实现这两个功能。
通过上面的分析可知,App缓存主要保存在两个地方:
1> /data/data/应用包名/com.cytmxk.test/cache
2> /storage/emulated/0/Android/data/应用包名/cache
所以App缓存大小就是这两个目录大小的和,清除App缓存实际上就是删除这两个目录,实现代码如下:
/**
* 获取App的缓存大小(单位 byte)
*/
private long getCacheSize() {
if (null == context) {
return -1;
}
int result = 0;
File cacheFile1 = context.getCacheDir();
if (cacheFile1.exists()) {
result += FileUtils.getFolderSize(cacheFile1.getAbsolutePath());
}
File cacheFile2 = context.getExternalCacheDir();
if (null != cacheFile2 && cacheFile2.exists()) {
result += FileUtils.getFolderSize(cacheFile2.getAbsolutePath());
}
return result;
}
/**
* 清空App缓存
*/
private void clearCache() {
if (null == context) {
return;
}
ArrayList<String> cacheFilePathList = new ArrayList<>();
this.fileOperationsManager = FileOperateManager.getInstance(context, "CacheManager", this);
File cacheFile1 = context.getCacheDir();
if (cacheFile1.exists()) {
cacheFilePathList.add(cacheFile1.getAbsolutePath());
}
File cacheFile2 = context.getExternalCacheDir();
if (null != cacheFile2 && cacheFile2.exists()) {
cacheFilePathList.add(cacheFile2.getAbsolutePath());
}
fileOperationsManager.delete(cacheFilePathList);
}
通过上面的代码可知我对于获取App 缓存大小和清除App缓存的思路,具体获取目录大小和删除目录的功能实现在网上应该可以找到很多,大家有兴趣可以自己研究,我就不在赘叙了。