Dir 是我在 2017年元旦搞的项目,专门治理Android上流氓软件/不规范的软件在存储卡乱存储文件,还你一个整洁的存储空间。这篇文章介绍我开发它的经历和初衷。Dir:https://dir.trumeet.top
本文同步发表于我的博客:https://blog.trumeet.top/2017/07/29/begin-dir/
(顶部图片:atony)

初衷

开发它的初心,还要从一次随意浏览手机开始说起。

某一天,我浏览手机里的文件,发现存储卡里面有许多APP乱创建的内容,它们肆无忌惮地把自己的 缓存日志 甚至 广告用户标识 存储在用户的 SD 卡里面。这也就像你的电脑硬盘里本应该是放你的文档、照片的地方,却杂乱无章地堆放了各种垃圾、小广告 还有你的隐私。甚至有些 APP 把临时图片/视频也丢进存储卡,还不忘及时删除或者加上 .nomedia 文件,这就导致我的 Google 相册 总提示我 要不要备份xx缓存目录.. 我很生气,这是我的个人目录,你们这样子随意丢垃圾肯定是不规范的。

Android 目录规范

Android 文件系统有如下目录区分:

  • 私有目录(内部)

    位于 /data/data/<包名>/ 下,存放应用的私有内容,其他应用没有授权是无法访问的。它被设计为 私有,也就是说 一般不和其他人共享,比较私密的内容,用户需要访问也需要 ROOT

    在这个目录中,我们通常这样安排,如果你去随意打开一个应用的私有目录,它一般也是这样的:

    cache :缓存。里面的文件大小会在 应用详情 -> 缓存大小 里面显示,用户可以通过 清除缓存 删掉它的内容,所以不能放如 设置 等重要内容。

    databases: 数据库目录,里面存放数据库。

    files : 文件目录,随意安排。

    shared_prefs : 设置(SP)目录。

    以上是常用的目录形式,当然,应用不按照规定也无伤大雅。因为这是放在私有目录中的,其他人(包括用户)都是无法访问的。

  • 私有目录(外部)

    位于 SD卡/Android/data/<包名>/ 下,由于是 外部,就放在 SD 卡里,用户可以访问。自身程序可以无需存储权限访问,其他应用或用户需要存储卡权限。

    由于任何人都可以访问,它一般放置一些不太重要、不太保密的内容。里面一般有:

    files : 同上面 files

    cache : 同上面 cache

不规范的猥琐做法

也就是说,应用如果要存放缓存、广告、日志 都可以无需存储权限,放进自身目录,既保护了数据安全、方便系统统一管理(如用户 清除缓存),还保持存储卡简洁。最重要的,还能无需存储权限。但是就有一些应用,不知道是开发人员吔屎了、应用间分享数据(可以用 FileProvider)、需要应用间分享用户ID(非常恶心的做法,详见下文),还是怎么着.. 不管怎么说,他们都带来了很多副作用。

插话:应用间分享用户ID

许多流氓软件都为了统计或者追踪用户,把自己获取到的用户硬件ID(隐私信息,如 IMEI、Mac地址) 存放到存储卡,多个应用共享。比如说,有 10 个应用带有XX会读取隐私的SDK,它们只要有一个获取了手机权限,就会把拿到的隐私存到存储卡,这样其他9个只需存储权限就可以获取到用户ID,从而追踪用户、共享情报了。这是非常侵害用户隐私的行为,因为这个ID是终身的,和硬件绑定的,且唯一的。有一次,我在存储卡根目录发现了一个叫 .imei 的文件,打开看里面写着一串东西,应该就是某毒瘤获取到的隐私(IMEI)吧。

不忍受,不认怼

见过一句话:

要么忍受,要么改变。

作为强迫症,我无法忍受自己的手机被肆意丢垃圾。我想起了酷安常见的一种拦截创建目录的方法:使用同名文件替换文件夹。这是由于 Unix 文件系统所致,替换后再操作会抛出 Not a dictionary 异常,这也就阻止瞎**创建了。Dir 有了雏形——专治随意创建。 Dir 也就是 目录 的简写(搞过 CMD 的童鞋应该知道)。

还有一些原因

还有一些原因,让我上了 Dir 的大船:

  • 市面上某些垃圾清理大师 广告太多,见过酷安某评论,清理完弹出女尸广告。我想找一款 简单,无杂质 的清理。
  • 还有些比较良心的清理需要 ROOT。
  • 大多数清理工具对小众APP、个人作品支持较差。

为此,Dir 基本已定型,可以开始开发了。

让我们开始吧

(原谅这节没写多少东西,因为许多 Bug 修完就忘了 ><)

规则的概念

由于 Dir 不是针对规范路径的清理,也就无法根据通配符、表达式等方式进行匹配垃圾。所以我想到了 规则数据库 的方式,由客户端下载安装最新云端规则,然后根据规则进行清理。每一条规则有一个路径,对应一个APP,一个标题,还有其他属性。

设计 APP

有了目标,我开始开发 Dir。最初就准备做一个 Activity,两个卡片——同步规则扫描。但最后,放弃了这个想法。

很快地,第一个 Beta 发布了。我在酷安邀请大家来参与公测,测试中,也发现了许多问题。

逐一修复后,觉得差不多了,便发布了正式版。反响很好,用户都表示 【神器】.. 也鼓励我继续开发它。

人多力量大。后来,我还加入了 规则贡献 等功能,通过给我提交垃圾文件规则,可以拿到完整版的兑换码,鼓励大家一起来建设这个项目。

许多用户反馈 界面太丑,我在5月份更新了 UI,全面的 Material 风格,让 Dir 用着更舒服..

许多热心用户来反馈问题,更有帮我 设计、画图、制作官网的热心基佬,他们很大地帮助了 Dir 的进步。

以下是我遇到的一些问题:

第一个问题:同步规则

如何同步?由于我不懂数据库,最初,我是每次同步时删除所有本地规则,然后再下载、保存.. 后来发布一段时间,觉得这样太慢。所以换成了 增量 的方案,先将本地规则路径存入 Set,然后在下载云端数据后每次保存前使用 contains 判断是否本地已有,如果有就跳过。这样大幅度提高了效率。

在这样发布一段时间后,又遇到了新的问题:

本地重复。由于规则没有一个固定格式,就导致一旦云端的路径修改(ABC 变成了 /ABC),实际效果相同,但是在contains 的时候就被认为两条,最终多次存储,导致重复。最终,我将每条路径都进行了处理,统一为 /XXX 的形式,保证了本地无重复。

本地现有规则不会更新 如果某规则在云端进行了更新(如标题变更),本地在判断时就会跳过,从而不会更新。为此,我更换了思路,使用SQL的 unique 功能,然后每次不进行本地判断,使用目录作为唯一列,直接存储。这样就会在本地已有这个路径的时候更新这条规则的详情,从而不创建新的项。这样做好处就在于解决了这两个问题,但是速度会变慢。

规则太少

最初只有几十条规则,有些热心用户邮件发来了一些,我需要每次都手动加入后台,数量少还很累。于是,用户贡献规则 的想法便萌生了。起初,我准备允许用户 提交修改下架 这三个操作,但是觉得工作量太大,最终只保留了 提交,用户手机上编辑规则后,提交管理员审核,随后再存入数据库。最终规则已过千条,支持许多软件。

后端程序

Telegram 群里大佬说,要尽可能地少把数据放到客户端。所以按照正常做法,规则提交等功能都是调用后台程序完成的。最初为了图省事,直接用的 LeanCloud 云函数(如同 FireBase Function),但简直天价,最低 6RMB/天,价格感人。然后,我借着组VPS的机会自己琢磨了后端,写了 RestFul API (也没有读过什么规范,反正自己够用就行 大雾),这样就能节省很多开支,而且程序完全由自己做主,自由、安全。

详见:https://blog.trumeet.top/2017/06/14/webservlet-jetty-appserver/

结语和感谢

开发中还遇到了许多问题,我都在尝试一一解决,在这个项目中,我也涨了不少姿势。这个项目也受到了大家的好评。开发它7个月了,我没有停下,努力把它做得更好,回报各位的支持。

以下是 Dir 比较重要版本的截图和历史,留作纪念:

  • 1.0 Beta 最初版 (1月12日)

    1.0.png
    1.0.png
    1.0-1.png
    1.0-1.png

  • 1.5 第一个正式版(1月18日)

    界面和最初一样

  • 规则提交工具 发布首个测试版,开始接受贡献规则(4月17日)

  • v1.31_build38-beta 界面大改,全面 Material 设计 (5月1日)

    1.31.png
    1.31.png

    1.31-1.png
    1.31-1.png
    1.31-2.png
    1.31-2.png

非常感谢这个项目,让我学到了很多东西,也感谢所有为Dir做出贡献的人,它仍在继续,会做得更好!


硬广时间:文章看完了,带走一只Dir (这个主页也是热心用户 neoFelhz 帮忙设计的 ><)