WebToApp App Modifier 深度指南:重打包已安装应用,实现快捷方式伪装与完整克隆
【免费下载链接】web-to-appThe most full featured web-to-app toolkit on Android, a complete APK workshop that runs entirely on your phone项目地址: https://gitcode.com/GitHub_Trending/web/web-to-app
App Modifier(应用修改器)是 WebToApp 提供的"重打包已安装应用"工具:它不依赖任何模板,直接以设备上已安装的 APK 为原料,要么生成一个指向原应用的新快捷方式入口,要么在二进制层面修改清单与资源后重签名,产出一个拥有全新身份、可独立安装的克隆 APK。读完本文你将掌握两种模式的区别与适用场景、完整的界面操作流程、克隆背后的 AXML/ARSC 二进制补丁与注入原理,以及"启动页 + 激活 + 公告"三类增强能力是如何被注入到克隆包中的。
App Modifier 是什么
App Modifier 位于主界面⋮(更多)菜单中,入口文档见 docs/guide/main-screen/more.md。它的定位与项目核心的"Web 转应用"(web-to-app)管线互补:后者从零构建 APK,而 App Modifier 负责改造已经安装的应用。
从源码结构看,该功能由以下模块支撑:
| 模块 | 路径 | 职责 |
|---|---|---|
| AppCloner | app/src/main/java/com/webtoapp/core/appmodifier/AppCloner.kt | 两种模式的核心执行器:创建快捷方式 / 克隆并安装 |
| AppListProvider | app/src/main/java/com/webtoapp/core/appmodifier/AppListProvider.kt | 枚举可启动应用,提供过滤、搜索、统计 |
| InstalledAppInfo | app/src/main/java/com/webtoapp/core/appmodifier/InstalledAppInfo.kt | 已安装应用的信息模型与结果类型定义 |
| AppModifyPayload / CloneConfigBuilder | AppModifyPayload.kt、CloneConfigBuilder.kt | 增强配置的载体与clone_config.json生成 |
| CloneManifestRewriter | app/src/main/java/com/webtoapp/core/appmodifier/CloneManifestRewriter.kt | 二进制 AXML 清单重写器 |
| CloneLauncherActivity | clone-host/src/main/java/com/webtoapp/clone/CloneLauncherActivity.kt | 注入到克隆包中的宿主启动器 |
| 界面 | app/src/main/java/com/webtoapp/ui/screens/AppModifierScreen.kt | 应用库、身份编辑、输出模式、预览等全部 UI |
两种工作模式:Shortcut Disguise 与 Clone
App Modifier 提供两种本质不同的输出方式,理解其差异是正确选型的前提:
- 快捷方式伪装(Shortcut disguise):为已存在的应用创建一个伪装快捷方式入口。快捷方式使用你设定的新名称与新图标,点击后通过
Intent启动目标应用。它不复制 APK、不产生新安装包,体积开销几乎为零,适合"换个名字换个图标"的轻量需求。 - 克隆(Clone):对已安装应用做真正的二进制克隆——修改 AndroidManifest.xml 与 resources.arsc、替换图标、注入宿主 DEX 与配置、再重新签名,产出一个拥有新身份(新包名)的可安装 APK。适合图标/名称/包名实验与重打包研究。
快捷方式模式的实现原理
在 AppCloner.kt 的createModifiedShortcut中,流程如下:
- 准备图标:优先使用用户选择的图片,否则回退到原应用图标,最后兜底生成纯色默认图标(
prepareIcon,见 AppCloner.kt); - 构造启动 Intent:若开启了启动页/激活/公告等增强(
AppModifyPayload.needsLauncher()判定),则指向项目内的SplashLauncherActivity并携带 JSON 载荷;否则直接使用getLaunchIntentForPackage获取原应用启动 Intent(见 AppCloner.kt); - 调用
ShortcutManagerCompat.requestPinShortcut请求桌面固定快捷方式;若当前启动器不支持,则返回错误(AppCloner.kt)。
快捷方式的短标签截取新名称前 10 字符,长标签截取前 25 字符,这一限制由ShortcutInfoCompat.Builder的 setShortLabel/setLongLabel 体现(AppCloner.kt)。
克隆模式的完整执行链
cloneAndInstall(AppCloner.kt)按阶段推进,界面上的进度条即对应这些阶段:
- 校验源 APK:读取
InstalledAppInfo.apkPath,文件不存在则报错; - 生成新包名:基于原包名加时间戳/随机数生成形如
c.<uniqueId>的新包名(generateClonePackageName,AppCloner.kt); - 注入判断:若启用了启动页/激活/公告增强,则需要从 assets 加载
clone_host/clone_host.dex,缺失时给出明确错误(AppCloner.kt); - 二进制修补:
modifyApk遍历原 APK 的 ZIP 条目,逐个处理(详见下一节); - 重签名:调用
JarSigner.sign对未签名包签名; - 安装:通过 FileProvider 以
application/vnd.android.package-archive触发系统安装器(AppCloner.kt)。
克隆成功后,AppCloner 还会用PackageManager.getPackageArchiveInfo解析产物并打印包名、版本、Activity/Service/Provider 数量及 debuggable/testOnly 标志,用于自检(debugApkStructure,AppCloner.kt)。
应用库:浏览、过滤与搜索
App Modifier 的第一步是从"应用库"选择目标应用。AppListProvider.getInstalledApps(AppListProvider.kt)的实现要点:
- 枚举范围:通过
Intent.ACTION_MAIN + CATEGORY_LAUNCHER查询可启动应用(getLaunchablePackageNames,AppListProvider.kt),保证列出的都是带桌面入口的应用; - 应用信息:每个条目包含包名、应用名、版本名/版本号、图标、APK 路径、是否系统应用、安装/更新时间、APK 大小(
InstalledAppInfo,InstalledAppInfo.kt);其中isSystemApp通过ApplicationInfo.FLAG_SYSTEM判定; - 过滤:
AppFilterType枚举(ALL / USER / SYSTEM)控制过滤,界面以三个 Chip 展示并附带计数(用户应用、系统应用、全部); - 搜索:同时匹配应用名与包名(忽略大小写);
- 排序:按名称、大小(APK 字节数)或更新时间三种方式,对应界面上的排序 Chip(见 AppModifierScreen.kt 与 AppModifierScreen.kt)。
系统应用同样可被选择,因此"系统/用户"过滤在克隆系统预装应用时尤其有用。
身份设置:新名称与新图标
选定应用后进入编辑页(AppModifyContent,AppModifierScreen.kt),身份设置包含两项:
- 新名称:即桌面显示名与克隆包的应用名;
- 新图标:支持从系统相册/文件选择(
ActivityResultContracts.GetContent),也支持从内置图标库选取(IconPickerWithLibrary组件)。
编辑状态由AppModifierEditState统一管理(AppModifierEditState.kt),最终通过toConfig转成AppModifyConfig交给 AppCloner。
在克隆模式下,图标替换并非简单覆盖:AppCloner.replaceIconEntry(AppCloner.kt)会针对不同图标条目标识出round、foreground、background等变体分别处理——圆形图标用 DST_IN 蒙版裁圆,自适应图标前景按 72/108 安全区等比缩放,背景层则从图标主色推导纯色(createSolidBackgroundIcon,ApkTemplate.kt),避免启动器合成时图片被绘制两次。
输出模式与预览
编辑页底部提供"输出模式"卡片(OutputModeCard),在 Shortcut 与 Clone 之间切换(AppModifierScreen.kt)。需要特别注意的是克隆模式的可用性约束(cloneBlockedReason,AppModifierScreen.kt):
- 克隆需要原始图标:如果设置了自定义图标,克隆会被禁用(原因见下一节注意事项);
- 克隆默认不携带增强:开启启动页/激活/公告中的任何一项时,克隆同样被禁用,只能走快捷方式模式。
当不满足克隆条件时,输出模式会自动回退为快捷方式。
预览(IdentityPreviewCard,AppModifierScreen.kt)在构建前以"原应用 → 新应用"的并排形式展示修改结果:左侧为原始名称/包名/图标,右侧为修改后的名称与图标,中间用箭头连接,确认无误后再点底部按钮执行。执行期间底部栏会展示实时进度百分比与阶段文案。
克隆的二进制修补:AXML 与 ARSC
克隆的核心在modifyApk(AppCloner.kt),它逐条重写原 APK 的 ZIP 内容:
- 剥离旧签名:跳过
META-INF/*.SF、*.RSA、*.DSA及MANIFEST.MF,为后续重签名腾出空间; - 重写 AndroidManifest.xml:
- 启用增强注入时使用
CloneManifestRewriter.rewrite(CloneManifestRewriter.kt); - 目标为本项目自身时用轻量
AxmlEditor; - 其他应用走
AxmlRebuilder.expandAndModify全量展开重写;
- 启用增强注入时使用
- 重写 resources.arsc:
ArscEditor将字符串池中的应用名替换为新名称,并把图标路径统一修正为 PNG 格式; - 替换图标条目:命中
ic_launcher*.png/mipmap*/drawable*规则时替换为按密度缩放的位图(48/72/96/144/192 等); - 注入增强内容:追加新 DEX(编号取现有 classesN.dex 最大值 +1)、写入
assets/clone_config.json、写入assets/splash_media.png或.mp4。
CloneManifestRewriter:二进制级清单重写
CloneManifestRewriter.kt 不依赖 aapt,直接在二进制 AXML 层面工作:
- 解析 AXML 头、字符串池、资源映射与元素 chunk(支持 UTF-8/UTF-16 两种字符串池编码);
- 将清单中所有相对类名(
.开头或裸类名)展开为原包名的全限定名,防止包名替换时误伤组件类; - 替换包名字符串(跳过疑似类名的段);
- 找到原启动 Activity(含 MAIN + LAUNCHER 的 intent-filter);
- 移除原启动 intent-filter,避免克隆包出现两个桌面入口;
- 在
</application>前注入com.webtoapp.clone.CloneLauncherActivity(带 MAIN/LAUNCHER intent-filter、exported=true); - 重建字符串池与资源映射,输出新的 AXML 字节流。
重写后得到的原始启动 Activity 名会被写回clone_config.json的originalLauncherActivity字段,供宿主启动器直接跳转原界面(见 AppCloner.kt)。
注入的宿主:CloneLauncherActivity
CloneLauncherActivity.kt 是注入进克隆包的入口 Activity,运行时读取assets/clone_config.json,按序完成:
- 激活校验:本地激活码匹配(支持去除
-/空格的归一化、SHA-256 哈希比对、常量时间比较防时序攻击),或远程激活(https://POST 校验,支持ALLOW/ALLOW_CACHED/ 拒绝三种离线策略); - 公告展示:支持纯文本或 HTML 内容、可选跳转链接按钮;
- 启动页:图片启动页(CENTER_CROP/FIT_CENTER + 倒计时)或视频启动页(MediaPlayer + 起止时间裁剪 + 可静音);
- 跳转原应用:优先用
originalLauncherActivity直启克隆包内原 Activity,失败则回退getLaunchIntentForPackage(CloneLauncherActivity.kt)。
CloneConfigBuilder.buildJson(CloneConfigBuilder.kt)负责把界面配置序列化为该 JSON,字段包括splashEnabled、splashType、splashDuration、splashClickToSkip、splashOrientation、splashFillScreen、splashEnableAudio、splashVideoStartMs/EndMs,以及激活相关的activationCodes、activationRequireEveryTime、activationDialog、remoteActivationEnabled、remoteVerifyUrl、remoteOfflinePolicy和公告相关的announcementTitle/Content/ContentIsHtml/LinkUrl/LinkText。
重签名:JarSigner 自生成密钥
克隆包必须重签名才能安装。JarSigner(app/src/main/java/com/webtoapp/core/apkbuilder/JarSigner.kt)使用SHA256withRSA算法,密钥对在首次使用时通过 Android Keystore 或纯 RSA 生成器自举创建,并持久化为 PKCS#12(webtoapp_keystore.p12,见 JarSigner.kt)。签名入口sign(inputApk, outputApk)(JarSigner.kt)会做输入校验、失败自动重建密钥并带重试。由于签名密钥是本地自生成的,克隆包与原应用签名不同,因而可与之共存安装,这也正是"克隆"能形成独立新身份的根基。
注意事项与使用边界
原文档明确列出以下几点,源码也给出了对应印证:
- 克隆模式可能需要原始图标:界面层在设置了自定义图标时直接禁用克隆(
Strings.appModifierCloneNeedsOriginalIcon),因为图标替换涉及 AXML/ARSC 中引用关系的联动重写,原始图标路径是重写资源表时的稳定锚点; - 默认不应用任何增强:开启启动页/激活/公告后克隆不可用(
Strings.appModifierCloneNoEnhancements),必须依赖注入clone_host.dex才能工作,缺少该资源时会明确报错; - 产物是二进制级修补并重签名的 APK:clone 输出位于应用外部存储目录的
cloned_apks/,文件名形如<新名称>_clone.APK(文件名经过清洗与截断,AppCloner.kt); - 合法使用:该功能定位是图标/名称/包名实验与重打包技术研究,仅应在拥有相应权利的应用上使用。请遵守目标应用的许可协议与当地法律法规,切勿用于绕过授权或盗版分发。
小结
App Modifier 为 WebToApp 补齐了"改造既有应用"的能力闭环:快捷方式模式以极低代价实现桌面入口伪装;克隆模式则在纯 Android 端完成 AXML/ARSC 二进制修补、DEX 注入与 RSA 重签名,产出拥有全新包名的可安装 APK。配合启动页、激活与公告三类注入增强,它构成了一套完整的重打包研究工具箱。理解其二进制补丁管线与注入宿主的工作方式,是正确使用、排查问题和做进一步实验的基础。
【免费下载链接】web-to-appThe most full featured web-to-app toolkit on Android, a complete APK workshop that runs entirely on your phone项目地址: https://gitcode.com/GitHub_Trending/web/web-to-app
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考