Android系统中的目录结构和App缓存管理

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缓存的思路,具体获取目录大小和删除目录的功能实现在网上应该可以找到很多,大家有兴趣可以自己研究,我就不在赘叙了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,424评论 25 707
  • 0. 前言 前面有被用户投诉 APP 流量消耗厉害: 于是乎考虑了流量方面的问题。暂时 APP 中涉及流量的几个方...
    zyl06阅读 23,914评论 5 62
  • 2016.12.22 在使用图片加载库Glide时,要让磁盘缓存到指定的目录用 DiskLruCacheFacto...
    小野酱鸭阅读 1,180评论 0 4
  • 一周课程结束啦~读书班人气最旺 看看大家的发圈~ 再看看群里的互动~ 周二言值班参与度爆棚,我点评了一整天~ 第二...
    蔡亿阅读 548评论 3 4
  • 先生是一种尊称,我喜欢的作家里绝对有鲁迅先生。从小在农村长大的我接触的书籍有限,没有课外读物的年代,最喜欢的是语文...
    赵慧姿阅读 307评论 0 0