找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 17|回复: 1

应用体重秤按App排缓存重量定向清缓存

[复制链接]
发表于 半小时前 | 显示全部楼层 |阅读模式
应用体重秤按App排缓存重量定向清缓存

QQ截图20261111085916.png

QQ截图20261111085905.png

QQ截图20261111085852.png

  1. /**
  2. * 案例40:应用体重秤按App排缓存重量定向清缓存
  3. *
  4. * 与案例32(按文件类型清垃圾)不同,本案例按【App】算账:
  5. *   谁在 /sdcard/Android/data 里吃得最胖、胖在缓存还是数据,一目了然;
  6. *   清理时只掏每个 App 的 cache 子目录(下次启动自动重建),数据文件一根不碰。
  7. * 用途:云手机农场定期瘦身 / 客户问"手机怎么满了"直接甩排行榜。
  8. *
  9. * 全走锤死通道(零新API):
  10. *   逐App大小 → adb.exec("du -sk /sdcard/Android/data/*")  (案例32锤死)
  11. *   缓存大小   → du -sk 包名/cache
  12. *   删除       → rm -rf 包名/cache                          (案例32锤死)
  13. *   前后对比   → df /sdcard                                 (案例32锤死)
  14. *   等待       → sleep.second(整秒)/ sleep.millisecond(毫秒),禁止裸 sleep()
  15. *
  16. * 写法合规:Rhino ES5,全 var、字符串拼接、函数先定义后调用、main() 末尾启动;
  17. * 节奏输出:关键动作前 3..2..1 倒计时,日志行间留白。
  18. *
  19. * 用法:默认 实清=false 只称重出报告;检查排行榜没冤枉的,改 true 再跑真瘦身。
  20. */

  21. // ========== 配置区 ==========
  22. var 实清 = false;              // false=演练只列清单,true=真删各App的cache目录
  23. var 上榜门槛MB = 1;            // 小于1MB的App不上秤
  24. var 大户门槛MB = 20;           // 超过20MB且缓存占比高的,列为"值得清"
  25. var 数据根 = "/sdcard/Android/data";
  26. var 资源根 = "/sdcard/Android/obb";

  27. // 包名 → 人话名(案例31锤死映射表,自己的App自己加)
  28. var 应用名 = {
  29.     "com.ss.android.ugc.aweme": "抖音",
  30.     "com.ss.android.ugc.aweme.lite": "抖音极速版",
  31.     "com.kuaishou.nebula": "快手极速版",
  32.     "com.smile.gifmaker": "快手",
  33.     "com.tencent.mm": "微信",
  34.     "com.dragon.read": "番茄小说",
  35.     "com.lizhi.fm": "荔枝FM",
  36.     "com.ss.android.article.lite": "头条极速版"
  37. };

  38. // ========== adb 通道(案例30锤死) ==========
  39. function adb跑(命令) {
  40.     try {
  41.         var 数据 = JSON.parse(adb.exec(命令, false));
  42.         var 成 = 数据.success == null ? "" : ("" + 数据.success);
  43.         var 错 = 数据.errorMsg == null ? "" : ("" + 数据.errorMsg).trim();
  44.         return { 成: 成, 错: 错 };
  45.     } catch (e) {
  46.         return { 成: "", 错: "exec异常 " + e };
  47.     }
  48. }

  49. // ========== 节奏倒计时 ==========
  50. function 节奏倒计时(秒数, 干什么) {
  51.     for (var i = 秒数; i > 0; i--) {
  52.         printl("⏰ " + i + " 秒后:" + 干什么);
  53.         sleep.second(1);
  54.     }
  55.     printl("🎬 " + 干什么 + " —— 开始");
  56.     sleep.millisecond(400);
  57. }

  58. // ========== df 已用MB(案例32解析姿势) ==========
  59. function 查已用MB() {
  60.     var r = adb跑("df /sdcard");
  61.     var 行 = ("" + r.成).split("\n");
  62.     for (var i = 1; i < 行.length; i++) {
  63.         var 列 = ("" + 行[i]).trim().split(/\s+/);
  64.         if (列.length >= 3) {
  65.             var kb = parseInt(列[2], 10);
  66.             if (kb > 0) return Math.floor(kb / 1024);
  67.         }
  68.     }
  69.     return -1;
  70. }

  71. // ========== du 单目录KB ==========
  72. function 查KB(路径) {
  73.     var r = adb跑("du -sk " + 路径);
  74.     var m = ("" + r.成).match(/(\d+)/);
  75.     return m == null ? -1 : parseInt(m[1], 10);
  76. }

  77. // ========== 逐App称重 ==========
  78. // du -sk 通配符输出:每行 "大小KB<TAB>/路径/包名"
  79. function 称重(根目录) {
  80.     var r = adb跑("du -sk " + 根目录 + "/*");
  81.     var 行 = ("" + r.成).split("\n");
  82.     var 结果 = [];
  83.     for (var i = 0; i < 行.length; i++) {
  84.         var 列 = ("" + 行[i]).trim().split(/\s+/);
  85.         if (列.length < 2) continue;
  86.         var kb = parseInt(列[0], 10);
  87.         if (!(kb > 0)) continue;
  88.         var 路径 = 列[1];
  89.         var 包名 = ("" + 路径).split("/");
  90.         结果.push({ 包: 包名[包名.length - 1], 路径: 路径, KB: kb });
  91.     }
  92.     return 结果;
  93. }

  94. // ========== 主流程 ==========
  95. function main() {
  96.     printl("=== 案例40 应用体重秤 启动:模式=" + (实清 ? "实删缓存" : "演练(只报不删)") + " ===");
  97.     sleep.millisecond(500);

  98.     var 已用前 = 查已用MB();
  99.     printl("💾 清理前已用: " + (已用前 < 0 ? "未知" : 已用前 + " MB"));
  100.     sleep.millisecond(400);

  101.     // ① 称重
  102.     节奏倒计时(3, "给 " + 数据根 + " 逐App上秤");
  103.     var 名单 = 称重(数据根);
  104.     var obb = 称重(资源根);
  105.     var i;
  106.     for (i = 0; i < obb.length; i++) 名单.push(obb[i]);   // obb 游戏大包也算进来
  107.     if (名单.length === 0) {
  108.         printl("ℹ 两个根目录都是空的(没装第三方App或du不通),到此为止");
  109.         return;
  110.     }
  111.     名单.sort(function (a, b) { return b.KB - a.KB; });

  112.     // ② 排行榜
  113.     printl("========== ⚖️ 应用体重排行榜(≥" + 上榜门槛MB + "MB) ==========");
  114.     var 上榜 = [];
  115.     for (i = 0; i < 名单.length; i++) {
  116.         var mb = Math.round(名单[i].KB / 1024 * 10) / 10;
  117.         if (mb < 上榜门槛MB) continue;
  118.         var 名 = 应用名[名单[i].包] || 名单[i].包;
  119.         printl("  第" + (上榜.length + 1) + "名 " + 名 + " : " + mb + " MB");
  120.         名单[i].MB = mb;
  121.         上榜.push(名单[i]);
  122.         sleep.millisecond(300);
  123.     }

  124.     // ③ 缓存细分:每个大户单独量 cache
  125.     节奏倒计时(3, "细分缓存与数据(只量 " + 大户门槛MB + "MB 以上大户)");
  126.     var 可清表 = [];
  127.     for (i = 0; i < 上榜.length; i++) {
  128.         var a = 上榜[i];
  129.         if (a.MB < 大户门槛MB) continue;
  130.         var cache路径 = a.路径 + "/cache";
  131.         var ckb = 查KB(cache路径);
  132.         if (ckb <= 0) {
  133.             printl("   " + (应用名[a.包] || a.包) + " : 胖在数据不在缓存,不动它");
  134.             sleep.millisecond(300);
  135.             continue;
  136.         }
  137.         var cmb = Math.round(ckb / 1024 * 10) / 10;
  138.         var 占 = Math.round(cmb / a.MB * 100);
  139.         printl("   " + (应用名[a.包] || a.包) + " : 总 " + a.MB + " MB,其中缓存 " + cmb + " MB(" + 占 + "%)");
  140.         可清表.push({ 包: a.包, cache: cache路径, MB: cmb });
  141.         sleep.millisecond(300);
  142.     }

  143.     // ④ 清理(或演练)
  144.     var 合计可清 = 0;
  145.     for (i = 0; i < 可清表.length; i++) 合计可清 += 可清表[i].MB;
  146.     合计可清 = Math.round(合计可清 * 10) / 10;

  147.     if (可清表.length === 0) {
  148.         printl("✅ 没有「缓存占大头」的App,不用清,收工");
  149.         return;
  150.     }

  151.     if (!实清) {
  152.         printl("📋 [演练] 可安全释放合计 " + 合计可清 + " MB(只删各App的cache目录,数据不碰)");
  153.         for (i = 0; i < 可清表.length; i++)
  154.             printl("      " + (应用名[可清表[i].包] || 可清表[i].包) + " → rm -rf " + 可清表[i].cache);
  155.         printl("💡 检查清单没冤枉 → 把 实清 改 true 再跑,真瘦身");
  156.     } else {
  157.         节奏倒计时(3, "真删 " + 可清表.length + " 个App的cache目录");
  158.         var 删成 = 0;
  159.         for (i = 0; i < 可清表.length; i++) {
  160.             var r = adb跑("rm -rf " + 可清表[i].cache);
  161.             if (r.错 === "") {
  162.                 删成++;
  163.                 printl("   🧹 已清 " + (应用名[可清表[i].包] || 可清表[i].包) + " 缓存 " + 可清表[i].MB + " MB");
  164.             } else {
  165.                 printl("   ⚠ 清 " + 可清表[i].包 + " 失败: " + r.错.slice(0, 50));
  166.             }
  167.             sleep.millisecond(300);
  168.         }
  169.         var 已用后 = 查已用MB();
  170.         var 释放 = (已用前 >= 0 && 已用后 >= 0) ? 已用前 - 已用后 : -1;
  171.         printl("========== 📋 瘦身战报 ==========");
  172.         printl("  清理 " + 删成 + "/" + 可清表.length + " 个App缓存,预计释放 " + 合计可清 + " MB" +
  173.                (释放 >= 0 ? ",df 实测释放 " + 释放 + " MB" : ""));
  174.     }

  175.     printl("💡 常驻玩法:每周跑一次演练清单发群里;云手机满了就 实清=true 跑一把");
  176.     printl("=== 案例40 收工 ===");
  177. }

  178. // ========== 启动(Rhino ES5:函数全部定义完才调用) ==========
  179. main();
复制代码


0

主题

1

回帖

2

积分

软件网站新手

积分
2
发表于 23 分钟前 | 显示全部楼层

应用体重秤按App排缓存重量定向清缓存

学习了,给关键流程留个手动兜底入口,自动化挂掉时人能接手比什么都强。数据先落原始文件再处理,中间出问题能回溯,内存里转两次格式出错就没救了。账号最好按任务稳定映射,不要随机轮换,新号一上来跑满负荷很容易被限。有没有能跟着做的例子?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|

GMT+8, 2026-11-12 07:24

安卓脚本软件 · 键鼠盒子 · HID · 机械臂

快速回复 返回顶部 返回列表

随机推荐 · 热帖 / 新帖 / 随便看看

社区会员(随机展示)