Android应用文件系统的管理与维护

距离上一篇文章发布已经快 三个月了,本来早就想再发一篇比较干货点的文章搞个大新闻,但是无奈上个月各种事情缠身,实在是忙不过来。不过拖着也不是办法,最近在改之前公司的程序员留下的烂摊子,把底层的文件操作框架算是扔掉之后重新完完整整的理了一遍。也发现了很多以前没注意或者没有在意的问题,于是就有了这篇文章。

这篇文章并不是偏向问题解决的文章,更多的是分享一下在android应用开发过程中的文件系统的一些思路和需要注意的地方;另外,虽然说是文件系统,其实不过是因为我找不到合适的词来描述了,这里并不会去讲android自身的文件系统,而是讲如何维护自身应用的文件夹和文件操作。所以想看文件系统的同学赶紧右上角或者左上角。

  • 应用的文件如何保存在android手机中

    应用在android手机中有两个与自己应用先关的包名文件夹,这两个文件夹的名称就是你自己应用的包名,在文章后面统一称为包名文件夹

     1. /data/data/{packageName}
    

    这是应用在android内部存储的文件夹,在app启动后回自动创建。这个文件夹主要存储数据库文件,SharedPreference文件等其他需要较高安全级别的文件,这个文件在一般状态下是无法通过手机的文件浏览器查看的,只有在root之后可以查看。因此我们可以在这儿文件夹下面存放一些我们不希望用户能轻易修改的文件。

     2. /storage/emulated/0/Android/data/{packageName}
    

    SD卡目录,早期的android手机由于内部存储比较小,因此不适合存储较大的媒体文件和缓存,因此有了SD卡这个东西。这个路径主要是存储一些媒体缓存文件,安全级别要求不高,我们可以利用手机的文件浏览器进行查看,同时也可以对文件进行操作。这个目录同样会在应用启动时创建。

    这两个文件夹都会随着应用的卸载而自动删除掉。对于应用开发,不建议在根目录下直接创建自定义的文件夹来保存数据,因为这样很流氓并且不符合开发规范,除非是一些设计本身就需要长期保存在本地并且不受应用自身限制的数据,比如说用户主动保存到手机的图片等。

  • /data/data/{packageName}的介绍

    这个包名文件一般从文件使用的角度来说,我们应用的非常的少,所以只做简要介绍。注意不同的手机路径可能不一定完全相同。

    1. 路径获取
      我们可以调用Environment.getDataDirectory()方法获取到第一级/data/的路径。这时,一定要注意,很多同学喜欢直接用字符串拼接的方式来拼接路径, 但这种方式不规范代码健壮性也不够完全。但是相应的,谷歌爸爸也没有给我们能够获取应用本身包名路径的API(这不是坑爹么),我们能用的只有Context.getDir(String name, int mode)这个方法。所以,我们可以调用这个方法在这个路径下创建一个子目录,然后获取该目录的父级目录就得到了包名文件夹的完整路径。
    2. 多用户的路径区别
      上文中说道了不要手动拼接路径更重要的原因,就在于/data/data/不是绝对的。在android4.2之后开始加入了多用户的支持,这使得/data/data/这个路径发生了变化。
      在单用户系统下,包名文件夹路径一般为:/data/data/{packageName}
      在多用户系统下,包名文件夹路径一般为:/data/user/0/{packageName},其中/0表示的时第一个用户。
  • /storage/emulated/0/Android/data/{packageName} SD卡路径的介绍

    到了比较重要的SD卡路径的介绍了。回想当时,作者也是个什么都不懂的低端码农,而和我搭档的哥们儿一上来对着文件浏览器一阵乱点,然后告诉我这个就是SD卡路径。当时我就想,这都什么年代了,手机出厂还自带SD卡的?还有,这特么为什么有两个包名文件夹啊?然而这哥们儿也是似懂非懂,一个劲儿得给重复我解释这是SD卡,这是数据路径...
    对于两个包名路径的问题,相信大家读到这儿基本上已经明白两者的区别了。下面解答一下为什么现在的手机还有SD卡路径这个问题。
    其实这也是一个历史遗留问题了。当初的android手机内部存储都非常的小,因此很依赖外部SD卡来存储媒体文件,这也是这个目录的由来。后来的手机内部存储空间越做越大,可是这些手机没有SD卡,如何兼容以前旧手机数据下生成的SD卡路径呢?因此,在后续的android手机中,就在手机内部存储中模拟出了一个SD卡路径,这也就是为什么手机明明没有SD卡,却依然有SD卡的路径。我们可以调用Environment.getExternalStorageState()这个方法来查看SD卡的状态,只要返回的状态与Environment.MEDIA_MOUNTED的值相同,就代表SD卡当前状态是可用的。

    1. Environment.getExternalStorageState()
      无论在有真实物理SD卡或者只有模拟SD卡的状态下,只要处于可用状态,Environment.getExternalStorageState()理论上都会返回Environment.MEDIA_MOUNTED
    2. Environment.isExternalStorageEmulated()
      上文说了,我们是无法通过SD卡的状态值来判断是否真的有SD卡的。那么,怎么判断到底有没有真实的物理SD卡呢?这就需要用到Environment.isExternalStorageEmulated()这个方法了,相信一看到方法名大家就知道这是干嘛的了。这里顺便多扯一句,emulated这个单词很可能在你的SD卡路径里面也会出现,是模拟的意思,当你看到你的SD卡路径出现这个词时,说明这个路径很大概率是模拟的SD卡路径。

    需要注意这个路径在不同的手机路径也可能不一定完全相同。

  • 包名文件夹何时创建

    上文已经提到,我们在应用启动时会自行创建,因此这两个文件夹不需要我们手动去创建。同时,需要注意的时,在Application生命周期中,这个两个文件夹就会自动创建,而这时我们如果开始在包名文件夹内创建目录,则有可能造成父级目录不存在的情况。在我的应用场景中,之前的程序员在Application一开始的onCrate中,就把包名文件夹下需要用到的目录一股脑门的创建了出来,这样在低版本手机上经常出现包名文件夹创建不成功的情况,这时就算手动去创建包名文件夹仍然会创建失败,但在文件浏览器中也看不到。所以建议在底层的文件方法中统一采取不信任原则,即当我们要使用文件路径时都假设改路径可能不存在,需要进行路径合法性验证。如果是文件,要判断文件的父级目录和文件本身是否存在;如果是文件夹,则只需要判断文件夹本身是否存在。

  • �应用包名文件夹无法成功创建的问题

    这是上文提到的我在自身的应用场景中遇到的问题,在低版本手机(Android4.4及以下)中出现的概率更高,表现就是在应用安装后,SD卡目录下没有创建对应的应用包名文件夹,而自己手动创建也是返回文件夹创建失败,进而后续的所有文件操作都会失败从而造成严重的bug。目前尚未找到是什么原因,不负责任的猜测可能是由什么东西占用了文件读写资源而由得不到释放,因为只要重启手机这个问题就没了。所以我的解决方案是在一进入应用时就对文件系统进行验证,判断手机的SD卡可用状态以及SD卡路径下包名文件夹是否存在,如果不存在则弹窗强制提醒用户退出应用并重启手机。

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

推荐阅读更多精彩内容