安卓修改大师智改工坊 · 实战笔记

一个人,一台 Windows 笔记本,一条改包流水线

客户签过字的授权说明、一个待改的 APK、一份说清楚的需求,这就是我全部的“产能”。智能修改电脑版把中间的脏活串了起来:导入、话术与附件、AI 修改、自动打包、装机预览、存档交付,一步接一步,不用我在六个窗口之间找刚才的思路。

只需说话,就能让应用变成你想要的样子。

了解智能修改电脑版与下载页 →

上周二晚上九点,一个做仓储的老客户发来消息:内部盘点工具要换新图标,应用名加上“内测”两个字,版本号从 1.4.2 提到 1.5.0,启动页底部加一行“仅限内部使用”。他补了一句:版权是我们的,开发团队也同意改,授权书明天盖章发你。

这种单子金额不大,但特别典型:改动点碎、沟通轮次多、交付标准还模糊。以前我接到这种消息,第一反应不是打开工程,而是先叹气——因为接下来两个小时,我要在五六个窗口之间来回跳,真正动手的时间可能只有二十分钟,剩下的都花在“找回刚才那一步”上。

改包这件事,难的从来不是某一个命令,而是命令之间的衔接:包在哪、图标放哪层、上次用的哪个签名、客户说的“内测”是全角还是半角。每一次窗口切换,都是一次上下文重建。

一个人接改包单,真正被吃掉的是上下文

我把以前接一单的固定动作写在便签上,数了数,一共十一步。每一步都不难,难的是它们分散在不同程序里,而且顺序不能乱。

  1. 打开存放 APK 的文件夹,确认客户发来的是不是最终包;
  2. 启动 apktool,敲反编译命令,等日志刷完;
  3. 去 res 下找 mipmap 的五六个密度目录,逐个替换图标;
  4. 改 strings 里的应用名,改 apktool 配置里的版本号;
  5. 回编、对齐、签名,三条命令一步都不能省;
  6. 签名口令从密码管理器里复制,粘错一次从头再来;
  7. adb 装包,再拉起启动页,看有没有闪退;
  8. 客户说桌面图标没变,再解释启动器缓存,卸载重装;
  9. 截图发群,等一句“可以了”;
  10. 把包、日志、说明整理进一个文件夹,命名、压缩;
  11. 发网盘链接,等客户下载,再补一句“装之前先卸载旧版”。

你看,没有一步需要高深技术,但每一步都在制造切换。反编译窗口、资源管理器、命令行、密码管理器、手机投屏、聊天窗口,六个地方来回看。真正让人累的不是手速,是每次切回来都要重新确认:我刚才改的是哪个包?这个 mipmap 目录是 xxhdpi 还是 xxxhdpi?上一次签的是哪个 keystore?

后来我把流程换成了智能修改电脑版的一条线:导入 → 话术与附件 → AI 修改 → 自动打包 → 装机预览 → 存档交付。注意,重点不是“每一步快了多少”,而是原来十一步里那些必须由人接力传递的状态,现在被放在同一个项目上下文里。包是同一个包,历史是同一份历史,日志是同一份日志。

环节 以前 现在的流水线 真正省掉的
确认包 解压看清单,翻聊天记录对版本 拖入即显示应用名、包名、版本、启动页 不用先反编译再确认
交代需求 写三段文字,再发一个图标压缩包 话术点选,附件逐条写用途 客户不用猜图放在哪
等修改 盯命令行,切窗口看进度 AI 工作区执行,完成留标记,主窗自动接打包 不用守着进度条
打包签名 三条命令加口令,顺序错了重来 四步自动执行,最后 verify 出证书信息 不会漏对齐,也不会签了个寂寞
装机验收 adb 两条命令,再手动截图 自动安装、自动拉起、复核前台应用 客户当场看到效果
归档 手动建文件夹、改名字、压缩 项目目录与 pack.log 原样保留 出问题能回查,不靠记忆
独立开发者的改包工作台

一台电脑、一个项目目录、一份授权说明,就能组成最小可交付的改包工作台。

把返工拆开看,原因无非三类:包拿错、需求理解错、签名或安装环境不对。流水线分别用 aapt、附件说明、verify 加装机预览去挡。它不能保证一次成功,但能让失败发生在你还在电脑前的时候,而不是客户已经装到手机上之后。

入口这一关:拖进 APK,aapt 先把底细说清楚

接单最怕的不是改不动,而是改错包。客户群里经常同时躺着“最终版”“最终版2”“最终版-真的最终”三个文件,文件名一样、大小差不多,打开才知道哪个是带新接口的。所以我把“确认包”放在流水线第一环,而且要在动手之前完成。

智能修改电脑版支持导入 APK、JAR、APKS、XAPK、APKM、CLASS 这几类文件。实际接单时格式比想象中杂:有人发 XAPK(带 OBB 数据),有人发 APKS(拆分包),还有人把 JAR 当 APK 发过来。以前要先回一句“你这个不是标准 APK”,再教对方怎么导出;现在直接拖进窗口,工具会按类型处理,少了一轮解释。

导入后第一眼看到的是 aapt 解析出来的信息:图标、应用名、包名、版本号、目标 SDK、启动页。别小看这一屏,它把“确认包”从反编译之后提前到了反编译之前。你不需要等 apktool 跑完、再去翻 AndroidManifest,拖进来的那一秒就能判断:这是不是客户说的 1.4.2,启动页是不是他截图里的那个 Activity。

图标解析有个容易踩的坑,值得单独说。APK 里的图标通常有 mdpi、hdpi、xhdpi、xxhdpi、xxxhdpi 好几套,换图标时如果只替换其中一套,在某些机型上桌面还是旧图。电脑版取最高密度那张原图作为展示和替换基准,这个逻辑听起来简单,但实现时有个陷阱:aapt 输出里的密度值 65534 表示“任意密度”(anydpi),它不是最高密度。如果按数值大小排序取最大,会把自适应图标的 XML 当成最高清位图,换完在 Android 8 以上还是旧样子。正确做法是先排除 65534,再比较真实密度。很多换图标教程就栽在这里,读者照做一遍,回来骂工具不行。

项目落盘的结构也值得知道。每个项目在 Project 下有一个 8 位随机目录,里面写 config.ini 和 history.ini,并复制一份 source.apk。反编译在 apktool 子目录里进行,输出 apktool.log。随机目录的好处是同一客户的多个版本不会互相覆盖;代价是不能靠目录名认项目,得看详情页的应用名和版本。我一般会在交付时把“项目目录 + 客户名 + 日期”记在台账里,后面找起来快。

反编译速度方面,12 MB 左右的包实测约 3 秒完成。这个数字不是重点,重点是与它配套的超时:超过 10 分钟会中断并报错。加固包、资源异常的包,apktool 有时会卡在某个循环里;以前我能盯着屏幕等半小时,现在十分钟就明确失败,可以去和客户沟通“这个包需要先脱壳或拿未加固版本”,而不是无限期地等。

接单检查清单

  • 应用名、包名与客户描述一致;
  • 版本号是客户要改的那一版,不是上一版;
  • 启动页 Activity 与截图对得上;
  • 授权说明与包名一一对应,避免拿错授权;
  • 原包另存一份,任何时候都能回到起点。
导入后查看应用信息

先看清包名、版本和启动页,再决定怎么改,能省掉一大半返工。

把需求说成人话:3000 条话术与“附件直给”

需求描述是改包流程里最容易被低估的一环。客户说“图标换一下”,到底换哪张、换几档、圆角要不要保留?客户说“名字改一下”,是改桌面显示名,还是连关于页面里的名字一起改?以前我靠追问,一个问题一个问题确认,客户烦,我也烦。

电脑版的详情页给了一个输入框,右侧是 3000 条话术,分成 6 类,每类 500 条:界面美化、弹窗引流、去除限制、常规修改、混淆去毒、插件添加。点一条,内容就填进输入框,然后你可以按自己的项目改。它的价值不是让你偷懒照抄,而是解决“对着空白框不知道从哪写”的问题。比如“把启动页背景换成附件里的图,底部加一行小字”,这句话我就是从“界面美化”里点了一条,再把附件编号补进去。

比话术更关键的是附件直给。图标、启动图、字体、配置文件都是二进制,文字描述再准也不如把文件递过去。附件区支持一次多选,但每个文件必须写用途,而且至少 10 个字;提交前会校验文件存在、不是目录、不是 0 字节、可读。拼装时按“序号 + 路径 + 说明”的格式跟需求一起发出去,history.ini 只保留用户原话,不保存拼装后的长文本。

为什么要强制写用途?因为同一个项目里可能同时有商店图、桌面图、启动页背景三张图,尺寸和用途完全不同。附件说明写“桌面图标源图,请生成五档密度”和“启动页背景,冷启动第一帧使用”,AI 才知道哪张该缩放、哪张该原样放。这个约束看起来是麻烦,实际上是把你脑子里的隐含信息显式化,减少来回。

附件写法示例

  1. 01_icon_1024.png:桌面图标源图,请生成 mdpi 到 xxxhdpi 五档,保留透明边;
  2. 02_splash_1080x1920.jpg:启动页背景,冷启动第一帧铺满,不裁切主体;
  3. 03_auth_scan.pdf:客户授权说明扫描件,仅用于本次内部版本,不随包分发。

历史记录的设计也在为“少切换”服务。详情页的历史最新在上,保留完整原文,右侧有“选择”可以回填到输入框。同一个需求要出第二版时,不用重新组织语言,点“选择”,改两个词,再补一张新图。改包接单里大量工作是“上一版再加一点”,这个回填动作省掉的是重新描述需求的十分钟,以及描述不一致带来的返工。

附件直给不只用于图片。给内部工具换 API 地址时,我把 config 文件作为附件挂上,用途写“内网正式环境地址配置,仅替换 host 与端口,不改其他字段”。这种需求用文字描述最容易出歧义:测试环境是 test 开头,正式环境是内网 IP,客户自己也说不清该换哪一行。文件递过去,再写清边界,AI 改完我对比一眼就能确认只动了该动的地方。

顺便说一句,项目列表能看历史、能删除项目,但删除只允许 Project 的直接子目录。这个限制看起来保守,实际是防止误删整个工作区或者把工具目录当项目删掉。接单的人最怕手滑,这种“只允许在边界内删除”的设计,比弹十个确认框都管用。

点下“立刻修改”:ai_done.flag 让打包自己发生

需求写完、附件挂好,接下来就是点“立刻修改”。这一下点击背后发生了三件事:你输入的原文连同日期写进 history.ini;需求被送进右侧的 AI 工作区执行;主窗口开始等一个信号。

这个信号不是弹窗,也不是接口回调,而是一个文件:AI 改完项目后,在项目目录里留下 ai_done.flag。主窗口每 2 秒轮询一次,读到这个文件就把它删掉,然后自动进入打包。等待上限是 1 小时,超时就不再干等。

第一次看到这个设计,我觉得土:都什么年代了,还用文件当信号?用久了才发现它解决的是真问题。AI 工作区负责改工程,主窗口负责打包装机,两边各管一段。它们之间如果靠内存共享或者私有接口,任何一方崩溃,另一方都可能永远等下去,或者收到一个半截的状态。文件信号简单、可观察、可恢复:AI 正常结束就留文件,主窗口读到就继续;AI 崩了就没有文件,主窗口一小时后超时;主窗口没开,文件就留在那里,下次打开还能看到。

一次点击之后的真实时序

  1. 原文与日期写入 history.ini,后面回填、对账都靠它;
  2. 需求送进右侧 AI 工作区,开始改 apktool 工程;
  3. AI 完成后在项目目录写入 ai_done.flag;
  4. 主窗口每 2 秒轮询,读到标记立即删除,避免重复触发;
  5. 自动执行四步打包,再走 adb 装机预览;
  6. 全过程写入 pack.log,交付时随包归档。

“读到即删”这个动作也很关键。如果只是检测文件存在,那么上一次的标记会一直留着,下一次点“立刻修改”可能还没改完就触发打包,打出一个半成品。删除之后,标记只代表“这一次刚完成”,状态是干净的。工程里这种小动作,比写一堆注释有用。

这一环真正省掉的是什么?是“守着”。以前我点完修改,要盯着命令行,看到反编译结束、看到回编成功,再手动敲打包命令。中间只要去回一条客户消息,回来就得翻日志找进度。现在我可以点完就去写另一单的报价、回另一个客户的问题,听到打包完成的提示再回来。时间没有被压缩多少,但注意力被释放了,这在一个人接单的场景里比速度值钱。

当然,异步也有代价:你得知道去哪看状态。我的习惯是点完之后瞄一眼项目目录,确认 ai_done.flag 还没出现;如果过了很久还没有,就去右侧工作区看它是不是卡在某个大资源上。超时 1 小时的设计也提醒我:这不是无限期的后台任务,遇到加固包或者异常资源,及时止损,换包或者换方案。

还有一个使用习惯:标记没出现时,先别急着重复点。看项目目录里 apktool 的时间戳有没有变化,翻一眼 apktool.log 的最后几行,再确认右侧工作区是不是还在跑。重复点会写两条历史,也可能让两个修改任务同时动同一份工程,反而更难查。流水线把等待变成可见状态,但判断仍然要人来做,这是我一直提醒自己的地方。

四步打包与 verify:签名不是按一下,是要能自证

自动打包听起来像“一个按钮”,实际是四步,顺序固定,少一步都不算完成。电脑版把它做成流水线,但每一步用的还是标准工具,日志里都能查到。

apktool b -f -o build\unsigned.apk
zipalign -f -p 4 build\unsigned.apk build\aligned.apk
apksigner sign --ks ... build\aligned.apk
apksigner verify --print-certs build\aligned.apk

第一步回编,-f 强制重建,-o 指定输出,产物先叫 unsigned.apk,名字就把状态说清楚了:还没签名,不能直接装。第二步对齐,4 字节对齐是 Android 加载未压缩资源的硬要求,-p 让共享库按页对齐,减少安装后的加载开销。第三步签名,按项目设置选择默认签名、JKS/keystore、PEM+PK8 或随机签名,签名方案支持 v1、v2、v3、v4,默认 v1+v2+v3。第四步 verify,打印证书信息,确认“到底签没签上”。

为什么非要多一步 verify?因为签名失败有时候不吵不闹。密钥格式不对、别名不对、口令不对,前面的步骤可能看起来跑完了,产物也在,但签名根本没写进去;还有些情况下签名块写了,证书链却不完整。apksigner verify --print-certs 会把证书主题、指纹、签名方案逐项打出来,格式错误也只有这一步会明确报出。没有 verify 的打包,等于闭着眼睛交付。

四步的顺序也不能乱。zipalign 必须放在签名之前,因为 v2 签名覆盖的是整个文件的字节;你先签名再对齐,对齐会改动文件内容,签名立刻失效。很多“装不上、提示未安装”的包,就是顺序错了。电脑版把顺序写死在流程里,不给人犯错的机会,这比在文档里写三行警告有效。

步骤 做什么 常见失败 怎么确认
回编 apktool 重建未签名包 资源引用缺失、smali 语法错 看 apktool.log 是否正常结束、build 目录是否生成产物
对齐 zipalign 4 字节对齐,共享库按页对齐 输入文件不存在、路径含空格未引号 命令返回 0,产物体积正常
签名 按四种密钥方式之一写入签名 别名错、口令错、PEM 与 PK8 不配对 verify 通过,证书指纹与预期一致
校验 verify --print-certs 打出证书 签名方案不兼容目标系统 v1/v2/v3 逐项显示,无 WARNING

签名方案的选择也要看交付对象。默认 v1+v2+v3 覆盖了从旧机型到新系统的大部分场景;v1 是 JAR 签名,兼容老系统;v2 是整文件签名,校验更快、防篡改更强;v3 支持密钥轮换,为将来换证书留余地;v4 主要用于增量安装,需要配套的安装方式,不是所有 adb 版本都吃。给客户交付内部工具时,我一般保持默认,除非客户明确要求只签某一种。

口令的处理是我最在意的细节之一。签名口令走环境变量,不拼进命令行,也不写进日志。原因很现实:命令行参数在进程列表里可见,日志文件会被打包发给客户。一个 keystore 的口令泄露,意味着别人可以签出和你一样的包,客户的内测渠道就可能被顶掉。工具把口令从日志里拿掉,是底线,不是加分项。

验收时我一定会看的三件事

  • verify 输出里的证书指纹,和客户归档的签名证书是否同源;
  • pack.log 里四步是否齐全,有没有跳过 verify;
  • 产物是不是 build 目录下最新时间戳的那个,别发错包。
打包与签名日志

打包日志不是给人看的仪式感,而是交付出问题时唯一能回查的证据链。

adb 装机预览:交付标准是“能在客户手机上打开”

改完包、签完名,还不算交付。客户不关心你的 verify 输出,他关心的是装到手机上,图标对不对、名字对不对、点开会不会闪退、启动页有没有换。所以电脑版在打包完成后会自动走一遍 adb:找设备、装包、拉起启动页,再用系统状态复核前台应用。

拉起用的是 am start -W -n 包名/Activity,-W 表示等待启动完成并返回结果,这样脚本能知道应用到底起没起来,而不是发完命令就当成功。这里最容易出问题的是 Activity 名字:应用名好改,启动页的类名却可能因为构建配置、别名 Activity、动态特性而变。电脑版用了三档查找:先读 config.ini 里记录的 LaunchableActivity;读不到就用 cmd package resolve-activity --brief 向设备的包管理器查询;再不行才用旧方式兜底。

这三档的顺序是有讲究的。config.ini 是导入时解析出来的,快,但可能因为改包而变化;设备查询是装包之后问系统“这个包的入口是谁”,最贴近真实;旧方式兜底是为了兼容老 adb 或特殊 ROM。以前我自己写脚本时只用第一档,结果有一次客户把启动页换成了别名 Activity,am start 直接报“Activity class does not exist”,包明明装上了,就是打不开。那种时候你会怀疑是改包改坏了,其实是启动入口找错了。

应用起来之后,还会用 dumpsys 复核前台应用。am start 返回成功不等于界面上真的是你的应用:有可能被权限弹窗挡住,有可能启动后立刻跳转到别的页面,也有可能旧版本还在后台。dumpsys 看的是系统当前聚焦的窗口和前台包名,这个复核动作能把“命令成功”和“用户看到”之间的差距补上。

手机连着的时候走 scrcpy 投屏,电脑上直接看到手机画面;模拟器则提到最前。对一个人接单来说,这个细节很重要:你不需要一边看电脑一边扭头看手机,也不需要截图发给自己再放大检查。改完的图标在桌面第几屏、应用名有没有被截断、启动页那行小字会不会被状态栏挡住,投屏里一眼就能看出来。

客户验收的语言从来不是“签名成功”,而是“我装上了,能打开,图标是我要的那个”。自动装机预览就是把这句话提前到交付之前,让你先替客户说一遍。

还有一个实际好处:装机预览会自动覆盖“卸载旧版”的沟通。Android 不允许同包名不同签名的应用直接覆盖安装,如果客户手机上装的是开发团队的正式签名版,而你用默认签名打了内测包,安装会失败。以前要解释半天,现在装的时候就能看到失败,及时改成用客户提供的 keystore,或者明确告诉客户“这个内测包需要先卸载正式版”。问题暴露在交付前,而不是客户在群里发一句“装不上”。

预览阶段我还会专门试三个动作:冷启动、按 Home 再回来、从最近任务划掉再打开。冷启动看启动页和首屏;Home 再回来看着色和状态恢复;划掉再打开看有没有残留的旧进程缓存。改启动页、改应用名这类需求,问题往往不在第一次打开,而在第二次、第三次。自动装机只负责把包装上去、拉起来,这三个动作还是要人来点,但至少不用再敲命令。

预览通过之后,我才会把包发出去。发之前会把应用名、版本号、图标、启动页四个点各截一张图,和 pack.log 一起放进交付文件夹。客户下次说“还是上一版好看”,我能立刻翻出当时那一版;客户说“版本号怎么没变”,我能指出设置里的版本号和构建时间。这些动作不产生直接收入,但能挡掉大量扯皮。

磁吸双窗口:效率来自不被打断,而不是手速

改包的时候,我需要同时看两样东西:左边是项目详情和需求,右边是 AI 工作区里正在发生的事。以前的做法是 Alt+Tab 来回切,或者把两个窗口手动拖成左右各一半。手动拖的问题是谁也对不齐:今天拖好了,明天换个分辨率又歪了;主窗口一最大化,AI 窗口被盖住;用完关掉,下次再拖一遍。

电脑版的做法是磁吸。AI 工作区打开后贴在主窗口旁边,两个窗口高度一致,看起来像同一块工作台被分成了两栏。它不是简单地把窗口挪过去,而是每次布局都重新算宽度:AI 工作区宽度等于屏幕工作区宽度乘以设定占比,再减去间隙和主窗口宽度。主窗口拉宽,AI 区域相应变窄;主窗口挪动,AI 区域跟着贴过去。屏幕分辨率变了,公式还是那一个,不会出现“右边露出一截桌面”的尴尬。

为了让吸附跟手,程序默认每 5 毫秒检查一次窗口位置。这个频率听起来夸张,但窗口拖动时的坐标变化就是这么快;如果按几百毫秒检查,用户会看到 AI 窗口一顿一顿地追。5 毫秒轮询加上轻量判断,开销很小,视觉上就是粘在一起。

难点不在“贴上去”,在“什么时候不该贴”。用户可能故意把窗口拖走,也可能只是程序自己在调整布局。如果分不清这两件事,就会出现“用户往左拖,程序往右吸”的打架。电脑版做了事件稳定判定:只有窗口静止超过设定的 SnapBackDelayMs,才算用户真的想挪动;被拖离约 260 毫秒后自动吸回。这个延迟短到几乎感觉不到,又长到不会误判一次正常拖动。

还有一个很小但很典型的坑:窗口最小化时,系统会把它挪到屏幕外,坐标可能是负几万。如果程序照着这个矩形去算布局,AI 窗口会被带到看不见的地方。电脑版对最小化产生的占位矩形整轮跳过,等窗口恢复再重新计算。dock.log 里记录的就是这些吸附和布局事件,出问题时不用猜,翻日志就能看到哪一轮算了什么。

双窗口在接单里的三个实际用法

  • 左边开着需求原文和附件说明,右边看 AI 改到哪一步,不用背需求;
  • 从资源管理器把新图标直接拖进主窗口,AI 区域不挡路、不闪;
  • 远程会议共享屏幕时,客户能同时看到“我提的要求”和“改完的结果”。
并排的改包工作区

需求、附件、执行状态同屏,减少的是来回切换,不是思考时间。

我自己的体感是,磁吸带来的不是“快”,而是“连续”。一次改包被打断三次,每次回来要花几十秒找回状态;两个窗口固定在那里,需求、附件、日志、结果都在视野里,思路不容易断。独立开发者一天要切换很多角色:接需求、改包、测试、交付、催款。能把其中一段固定成一个稳定画面,已经很有价值。

一个项目一个目录:pack.log 与可回滚的底气

接单久了,最怕的不是改不出来,而是“改出来了但说不清怎么改的”。客户三个月后说某个页面不对,你打开电脑,发现当时用的是哪个包、哪个签名、改过哪几处,全靠记忆。电脑版用最朴素的办法解决这个问题:一个项目一个目录,所有东西都留在里面。

Project\
  a1b2c3d4\            8 位随机项目目录
    source.apk         原始包,只读参照
    config.ini         项目配置、启动页记录
    history.ini        需求原文与日期
    apktool\           反编译工程
      apktool.log      反编译与回编日志
    build\             对齐、签名产物
  ...

source.apk 是我最看重的文件。它意味着任何一次修改都有起点:改坏了,重新导入 source.apk 开一个新项目;客户要对比,直接装原包;怀疑是原包就有问题,先用 source.apk 复现一遍。以前我把原包放在下载文件夹,改到第三版时经常找不到最初那个,只剩一堆“修改后”“修改后2”。

日志分得很细,各有各的用途。apktool.log 记反编译和回编的输出,资源缺失、smali 语法错都在这里;pack.log 记四步打包的全过程,对齐、签名、verify 的每一步和结果;error.log 记未处理异常;dock.log 记窗口吸附和布局。看起来是四个文件,实际是四条证据链:改包出错看 apktool.log,打包出错看 pack.log,程序崩了看 error.log,界面抽风看 dock.log。

pack.log 在交付时的作用尤其大。客户说“这个包签名怎么和上次不一样”,你把两次的 verify 输出并排一看,证书指纹不同,立刻能定位是换了签名方式;客户说“版本号没改”,你看回编时间和产物时间,能判断是打包用了旧产物还是安装没覆盖。没有日志,这些问题只能靠猜,猜错了就是一轮返工。

pack.log 里我重点看三样:zipalign 的返回码、apksigner sign 用了哪个证书别名、verify 打出的 v1/v2/v3 是否齐全。别名不对时,sign 可能报错也可能静默产出未签名包,verify 一跑就露馅。把这三样抄进交付说明,客户的技术对接人一看就懂,不用来回问。

工作目录的选择也考虑到了接单场景。程序会按 D → E → F → G → C 的顺序找盘,取第一个可读写且剩余空间不少于 1GB 的,然后在下面建 tools 和 Project 两个子目录。为什么是这个顺序?大多数 Windows 笔记本的 C 盘是系统盘,空间紧张;D 盘往后更可能是数据盘或移动硬盘。把反编译工程、构建产物、工具链放到数据盘,既不挤占系统盘,也方便整盘备份。

工具链的查找是递归的。你不用把 apktool、zipalign、apksigner、adb 摆成某个固定目录结构,程序会在工作目录里递归搜索。换电脑、换移动硬盘、把工具从旧目录搬到新目录,项目还能继续用。这个设计对经常在台式机和笔记本之间切换的人很友好:项目目录整个拷过去,工具路径重新指向即可。

项目多起来之后,我会在客户台账里记三列:项目目录的 8 位编号、客户与包名、最后一次交付日期。目录名是随机的,不能靠它认项目;但把编号和客户对上,找起来就很快。清理时也只删 Project 的直接子目录,一次一个,删之前先确认 source.apk 和最终包已经归档到交付盘。

参数设置里还有几项看着小、用起来顺的功能:工作目录、十套配色主题、工具链体检、首页提示条开关。主题有极夜蓝、深海蓝、紫罗兰、樱花粉、烈焰红、落日橙、古铜金、青柠绿、薄荷绿、石墨灰,长时间盯日志的人可以选低对比度的深色系;工具链体检在换机、升级系统之后先跑一遍,省得改到一半才发现 apksigner 找不到;首页提示条开关则是给熟练用户减少干扰。

顺便交代运行环境:Windows 10/11 64 位,.NET Framework 4.6.2 及以上,安装包约 6.86 MB。对一个人接单来说,这意味着不用为了改一个包专门换机器;装好之后先跑一遍工具链体检,确认 apktool、zipalign、apksigner、adb 都在,再开始接活。

我的交付归档习惯

  • 项目目录原样保留,不清理 build,方便客户回头要同一版;
  • pack.log 和 verify 输出单独抄一份到交付文件夹,客户不用解压项目;
  • 文件命名带日期和版本号,例如 20261021_盘点助手_1.5.0-rc1;
  • 授权说明与包名一起归档,下一次改动先核对授权范围;
  • 超过三个月的项目只留 source.apk、pack.log 和最终包,节省空间。

删除项目的限制也值得提一句:只允许删除 Project 的直接子目录。这个规则挡掉的是“手滑选中整个 Project 目录按删除”的灾难。接单电脑上往往堆着几十个项目,清理时最容易出事;把删除范围锁死在项目目录这一层,成本很低,收益很大。

两个实例:授权内部工具换图标,自家 App 换启动页

前面讲的是流程,这一节把两个真实单子拆开看。两个案例都满足一个前提:应用归客户或我自己所有,改动范围有书面授权。没有这个前提,后面的方法都不适用。

案例一 · 客户授权的内部工具

换图标、加“内测”、提版本号

客户是一家做仓储的小公司,盘点工具由外包团队开发,版权归客户,开发团队也同意为内测版本换标识。需求有四条:桌面图标换成新 CI;应用名从“盘点助手”改成“盘点助手(内测)”;版本号从 1.4.2 提到 1.5.0-rc1;启动页底部加一行“仅限内部使用”。

以前的做法:先用 apktool 反编译,去 res 下找 mipmap-mdpi 到 mipmap-xxxhdpi 五六个目录,逐个替换图标;这个包还带自适应图标,mipmap-anydpi-v26 下有一份 XML 引用前景和背景,如果只换位图不换引用,Android 8 以上还是旧图标。然后改应用名字符串、改 apktool 配置里的版本号,回编、对齐、签名,adb 装到测试机。装完发现桌面还是旧图标,再让客户卸载重装,一来一回半天。最后打包发网盘,日志留在自己电脑里,客户问“改了什么”只能凭记忆说。

现在的做法:把包拖进智能修改电脑版,aapt 先显示应用名、包名、版本 1.4.2、启动页 Activity,和客户描述对得上,确认没拿错包。附件里放三样东西:1024 的图标源图,说明写“桌面图标源图,生成五档密度并保留自适应结构”;启动页设计稿,说明写“冷启动第一帧背景,底部小字不要被裁切”;客户授权说明扫描件,说明写“仅限本次内部版本,不随包分发”。需求从“常规修改”里点一条话术,改成“替换图标与应用名,版本号提到 1.5.0-rc1,启动页加指定小字”。点“立刻修改”,AI 改完留标记,主窗口自动打包,verify 打出证书,adb 装到测试机并拉起。

这个单子还有一个签名上的插曲。客户手机里装着开发团队签的正式版,包名相同、证书不同,直接覆盖安装会被系统拒绝。以前我会先让客户卸载,客户又担心丢数据。这次在项目里直接选客户提供的 JKS,口令走环境变量,签完 verify 打出的证书指纹和客户归档的一致,安装时顺利覆盖,本地数据也保住了。签名一致这件事,只有在装之前确认,才有意义。

怎么验证:先看桌面图标是不是新 CI,长按看应用信息里的名称和版本号;再冷启动一次,看启动页底部小字有没有被状态栏遮住;然后看 verify 输出的证书指纹,确认和客户归档的签名一致;最后把 pack.log、最终包、三张验收截图放进交付文件夹。客户在群里只回了一句“这次不用教我怎么装了”。

版本号这里也有个容易忽略的点:应用信息里显示的是 versionName,系统判断能不能覆盖升级看的是 versionCode。只改显示名不改 versionCode,某些渠道会认为新包不比旧包新。电脑版的修改范围包含 apktool 工程里的版本配置,我在需求里会明确写“versionName 1.5.0-rc1,versionCode 从 14 提到 15”,交付前在应用信息里核对显示版本,再用 dumpsys package 看 versionCode,两个都对上才算完成。

第二版来得很快:客户要把“内测”改成“内测·仓储”,版本号提到 rc2。我打开详情页,历史里点“选择”回填上次原文,改两处文字,换一张新图标,其他附件不动。这一次连需求都没重新组织,因为上下文还在项目里。

案例二 · 自家应用

换启动页、去自家开屏广告、提版本号

我自己有一个记账 App,春节前想换一版启动页:背景换成红金配色,中间保留 logo,底部去掉去年那句活动文案;顺便把自家开屏广告关掉,版本号从 3.2.0 提到 3.2.1。应用是我自己写的,签名 keystore 在我手里,改起来没有授权障碍。

以前的做法:改启动页要回 Android Studio,换 drawable 里的图,改布局,重新构建 release 包,再用 Android Studio 的签名配置打包。只改一张图,也要等 Gradle 跑完;如果手上没有完整工程,还得走 apktool 那条路,两条工具链来回切。开屏广告是自家的一段启动逻辑,改完要重新测冷启动、热启动、从后台恢复三种情况,生怕改出白屏。

现在的做法:拖入线上 release 包,aapt 确认版本 3.2.0 和启动页;附件给两张启动图,一张 1080×1920、一张 1440×2560,说明写“冷启动第一屏背景,铺满不裁切,中间留出 logo 安全区”;需求写“替换启动页背景,去掉开屏活动文案与自家开屏广告,版本号改为 3.2.1”。签名选 JKS/keystore,用我自己的证书,方案保持 v1+v2+v3。点“立刻修改”,等标记出现,自动打包,verify 通过。

怎么验证:先杀掉进程冷启动两次,看第一帧是不是新背景、有没有先闪一下旧图;再从后台恢复一次,确认不会重新走启动页;然后去设置里看版本号 3.2.1;最后把包发给两个用旧手机的朋友,确认 Android 10 和 Android 14 上都能装、都能起。verify 输出的证书指纹和我本地归档的一致,说明还是同一把钥匙,老用户可以直接覆盖升级。

这个案例里有个小插曲。第一次附件说明我只写了“启动图”,提交时被拦下,因为用途不足 10 个字。当时觉得麻烦,后来认真写成“冷启动第一屏背景,铺满不裁切,中间留出 logo 安全区”,AI 给的图一次就对了。约束逼着我把“铺满还是留白、裁不裁、安全区在哪”想清楚,反而省了第二次返工。

交付时一个老用户问,能不能保留旧版启动页,春节后再切回来。我没有留两套工程,而是把 3.2.0 的 source.apk 和这次的最终包一起归档,交付说明里写清楚两个包的 versionCode。节后要回退,重新导入旧包、改版本号、用同一把钥匙签名即可。可回滚不是一句承诺,是 source.apk、签名证书和日志三样东西都在。

手机上的启动页预览

启动页改完要在真机上冷启动看第一帧,模拟器截图只能作为参考。

对比项 案例一 · 授权内部工具 案例二 · 自家记账 App
改动内容 图标、应用名、版本号、启动页小字 启动页背景、开屏广告、版本号
签名 客户提供的 JKS,保持证书一致 自有 JKS,默认 v1+v2+v3
关键附件 图标源图、启动页设计稿、授权扫描件 两档启动图、安全区说明
验证重点 桌面图标、应用信息、证书指纹 冷启动首帧、后台恢复、版本号
交付物 最终包、pack.log、三张截图、授权说明 最终包、pack.log、双机安装记录
改包项目的交付归档

交付不是发一个 APK,而是让客户能装、能看、能回查。

五个人怎么用它接单:用户评价与合规提醒

下面这些评价来自我熟悉的几个接单同行,身份和场景各不相同。他们说的不是“工具多神”,而是流程里哪一段被接住了。

“我最怕客户改到第三版才说‘还是第一版的图标好’。现在项目目录里 source.apk 一直在,历史也能回填,重开一版比解释半天快。授权书我每次都让客户先发,包名对不上不接。”

—— 老陈,独立开发者

“我们三个人做外包,最怕交接。现在每个项目都有 pack.log,签名、对齐、校验走到哪一步一目了然。客户半年后问当时怎么签的,直接翻日志,不用把离职同事的聊天记录找出来。”

—— 阿岚,外包负责人

“双窗口是我留下的原因。左边需求原文,右边 AI 工作区,改的时候不用背客户的原话。从资源管理器拖图进去也不会被挡,改完自动装到测试机,省了我来回按 Alt+Tab。”

—— 小周,小团队主理人

“企业内网工具经常要换 API 地址和版本号,签名的 keystore 又是客户保管。以前最怕签完装不上,现在 verify 会把证书打出来,装之前就知道对不对。口令走环境变量这点,做甲方的会懂。”

—— 林工,企业信息化外包

“我是兼职接单,晚上时间碎。点完修改可以去哄孩子,回来包已经打好了。附件必须写用途这条一开始嫌烦,后来发现写清楚一次,比返工三次省时间。”

—— 阿凯,兼职接单开发者

合规提醒:先有权,再谈改

本文所有方法只适用于你拥有自有版权的应用,或已拿到权利人明确授权的应用。接单前至少确认三件事:授权书覆盖目标包名;授权范围包含本次改动;授权期限覆盖交付与使用周期。客户说不清版权归属的包,不接。

请勿用于破解付费内容、绕过安全机制、去除他人应用的功能限制,也不要改来源不明的商业应用。话术库是表达工具,不是授权凭证;能不能改,取决于你有没有权利,而不是工具能不能做到。

把这条流水线跑顺之后,我做过一次很朴素的复盘:一单小改,原来要在六个程序之间切换十几次,现在固定在两个窗口里完成;原来要手动敲的命令,现在由四步流程接管;原来靠记忆回答的“当时怎么签的”,现在有 pack.log。省下来的不是某一个环节的几分钟,而是每次切换后重新进入状态的那段时间。对一个人接单来说,能连续工作两小时,比零散地快十次更值钱。

回到最开始那个问题:一个人接改包单,瓶颈到底是什么?我的答案是上下文,而不是技术。技术可以查文档,命令可以抄,唯独“这个包改到哪了、上次客户怎么说的、签名用的哪把钥匙、装上去有没有问题”这些状态,一旦散落在六个窗口里,就会不断把人拉回起点。

流水线的意义,是把这些状态收进同一个项目:aapt 先把包说清楚,话术和附件把需求说清楚,ai_done.flag 把“改完了”变成可等待的信号,四步打包和 verify 把“能装”变成可验证的事实,adb 把“客户能看到”提前到交付之前,pack.log 把“当时怎么做的”留下来。人负责判断和沟通,程序负责衔接和复现。

安卓修改大师智改工坊

把重复的衔接交给流水线,把判断留给自己

如果你也在一个人接改包单,不妨从一个真实的小需求开始:拖进包,写清需求,挂上附件,点一次“立刻修改”。只需说话,就能让应用变成你想要的样子。

前往 www.apkeditor.cn 查看智能修改电脑版 →

下载卡 · 手机端也能改

智能修改安卓版

不用开电脑,在 Android 10 及以上的 ARM64 手机或平板上导入 APK,本地完成反编译、修改、回编、对齐、签名,成品可以直接安装或分享。第一次使用会按需下载运行环境,之后不用重复下载。

  • 支持 APK、JAR、APKS、XAPK、APKM 导入;
  • AI 改包、自动回编、v1+v2+v3 签名;
  • 项目文件、日志可查,成品可安装可分享。

立即下载

请仅修改自有版权或已获授权的应用;请勿用于破解。电脑版与安卓版都可在 www.apkeditor.cn 了解。