WebToApp 导出(Export)功能全解:将 Web 应用导出为可跨设备复用的项目模板
【免费下载链接】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
导读
WebToApp 的Export(导出)功能可以把一个已创建的 Web 应用,从"运行中的配置"打包成可在另一台设备上重新导入的项目模板(project template),实现应用"定义"(配置与内容)的跨设备迁移。本文以docs/guide/app-actions/export-apk.md为骨架,结合app/src/main/java/com/webtoapp/core/export/AppExporter.kt的源码实现,完整讲解导出入口、两种导出形态、模板目录结构与生成参数,并厘清 Export / Build / Share 三种动作的差异,帮助你正确选择"搬家"还是"分发"。
一、Export 是什么:导出的是"可复用的项目模板"
与直觉不同,WebToApp 中的Export并不产出 APK 安装包,而是把应用的配置(以及内容)打包成一个便携模板(portable template)。文档的原始定义如下:
Exports the app as areusable project templateyou can import on another device. Tap ⋮ on an app card, thenExport.
也就是说:
- 导出物:一份可以在另一台设备上再次导入、继续编辑或重新构建的应用"定义";
- 入口:应用卡片右上角的
⋮(更多)菜单 →Export; - 产出位置:成功后界面(Snackbar)会直接报告导出文件的输出路径(
ExportResult.Success(path)中的path)。
从源码看,导出功能由 AppExporter.kt 承担,对外暴露两类导出方法(AppExporter.kt):
| 方法 | 产出 | 用途 |
|---|---|---|
exportAsTemplate(webApp) | 完整 Gradle Android 工程目录 | 拿到源码工程,可在任意设备/电脑上重新编译 |
exportConfig(webApp) | 单个配置 JSON 文件 | 仅迁移"应用定义",体积最小、最轻量 |
二、两种导出形态:完整工程模板 vs 配置 JSON
原文档仅笼统描述"打包配置(和内容)为便携模板",而源码揭示了两种截然不同的导出粒度,这也是理解 Export 能力的关键。
1. 形态 A:exportAsTemplate—— 生成完整 Gradle 工程
这是卡片菜单上Export按钮(HomeScreen.kt 的onExport回调)实际调用的方法。它会在导出目录下创建一个以**应用名(已清洗)**命名的子目录,写入一整套可以直接用 Android Studio 打开的工程:
<导出目录>/<应用名>/ ├── build.gradle.kts # 根构建脚本(AGP 8.2.0 + Kotlin 1.9.20) ├── settings.gradle.kts # rootProject.name = 清洗后的应用名 ├── README.md # 自动生成的工程说明与编译步骤 └── app/ ├── build.gradle.kts # 应用构建脚本(含 applicationId、签名、依赖) └── src/main/ ├── AndroidManifest.xml ├── java/com/webtoapp/generated/AppConfig.kt # 核心配置常量类 └── res/ ├── values/strings.xml # app_name ├── xml/network_security_config.xml # 网络信任配置 ├── raw/*.cer # 自定义 CA 证书(如有) └── mipmap-xxxhdpi/ic_launcher.png # 应用图标(192px 及以上)(目录结构依据 AppExporter.kt 的createTemplateProject生成逻辑整理)
生成的 Gradle 参数(generateAppBuildGradle):
| 参数 | 值 | 说明 |
|---|---|---|
namespace/applicationId | com.webtoapp.<清洗后的应用名> | 由应用名转换而来(见下文命名规则) |
compileSdk/targetSdk | 34 | 模板固定采用 |
minSdk | 24 | 覆盖 Android 7.0 及以上 |
versionCode/versionName | 1/1.0.0 | 首次生成默认值 |
release.isMinifyEnabled | true | 开启 R8 混淆(使用 proguard-android-optimize) |
| Java / Kotlin 目标 | 17 | 需要 JDK 17 |
| 依赖 | androidx.core:core-ktx:1.12.0、androidx.appcompat:appcompat:1.6.1、androidx.webkit:webkit:1.9.0 | 模板自带的最小 WebView 应用依赖集 |
核心配置类AppConfig.kt的字段映射(generateAppConfig)——它把应用编辑器中设置的开关与规则直接编译为 Kotlin 常量,让模板脱离 WebToApp 也能独立运行:
| 常量 | 来源字段 | 说明 |
|---|---|---|
APP_NAME/TARGET_URL | name/url | 应用名与目标网址 |
ACTIVATION_ENABLED/ACTIVATION_CODES | activationEnabled/ 激活码列表 | 激活验证开关与授权码 |
AD_BLOCK_ENABLED/AD_BLOCK_RULES | adBlockEnabled/adBlockRules | 广告拦截开关与规则列表 |
ANNOUNCEMENT_* | announcement | 公告弹窗的启用、标题、内容、链接与"仅显示一次" |
JAVASCRIPT_ENABLED/DOM_STORAGE_ENABLED/ZOOM_ENABLED/DESKTOP_MODE | webViewConfig | WebView 行为开关 |
此外,模板还会同步生成network_security_config.xml(由NetworkSecurityConfigBuilder构建):当开启**防截屏(antiCapture)**时,模板会自动把trustUserCa置为false,并同步复制用户配置的自定义 CA 证书到res/raw/(AppExporter.kt)。
命名清洗规则(sanitizeFileName / sanitizePackageName):
- 目录名:仅保留
a-z、A-Z、0-9、_、-及中文字符,其余替换为_; - 包名:小写化后仅保留
a-z0-9,最长截取 20 字符;若结果为空则回退为app。
模板自带 README.md记录了标准编译流程(generateReadme):使用Android Studio Hedgehog 或更高版本、JDK 17+,同步 Gradle 后执行Build > Build Bundle(s) / APK(s) > Build APK(s),产物位于app/build/outputs/apk/。这意味着一张卡片导出的是一份完整的可编译源码工程,而不仅是配置文件。
2. 形态 B:exportConfig—— 生成配置 JSON
exportConfig(AppExporter.kt)仅导出应用定义本身,输出一个文件名为<应用名>_config_<时间戳>.json的单文件,外层结构为:
{ "version": 1, "exportTime": 1720000000000, "app": { "id": 1, "name": "MyApp", "url": "https://example.com", "activationEnabled": true, "activationCodeList": [], "adBlockEnabled": false, "adBlockRules": [], "announcementEnabled": false, "announcement": null, "webViewConfig": { } } }其中version = 1是导出格式的版本号,exportTime为导出时间戳,app字段集合由WebApp.toExportFormat()决定(AppExporter.kt),JSON 通过GsonBuilder().setPrettyPrinting()美化输出。配置 JSON 适合在"仅需迁移设置、体积最小时"使用——例如通过 Agent 的ExportApp工具按需生成。
三、导出路径与文件名规则
导出目录由 getExportDirectory 决定,并且随系统版本分叉:
- Android 10(API 29)及以上:
context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)/WebToApp(应用专属目录,无需存储权限); - Android 10 以下:
Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS)/WebToApp(公共 Documents 目录)。
时间戳采用yyyyMMdd_HHmmss格式(dateFormat),保证同应用重复导出时文件不会互相覆盖。导出成功后,ExportResult.Success(path)中的绝对路径会通过 Snackbar 反馈给用户(HomeScreen.kt),界面文案来自 Strings.kt 的projectExportedTo。
四、Export vs Build vs Share:三种动作的本质区别
原文档用一张对比表区分三种动作,这里结合源码再深化一层:
| 动作 | 产出 | 代码路径 | 适用场景 |
|---|---|---|---|
| Export | 可复用项目模板 / 配置 JSON(可再次导入) | AppExporter.kt 的exportAsTemplate/exportConfig | 把应用"定义"迁往另一台设备,或交给开发者在电脑上继续编译 |
| Build APK | 可安装、已签名的 APK | ApkBuilder.kt(组装 + 签名,V1/V2/V3) | 本地产出安装包,直接安装 |
| Share APK | 通过系统分享面板发送的已构建 APK | HomeScreen.kt中apkBuilder.buildApk(...)后唤起系统分享 | 把安装包发给他人安装 |
简言之:Export 移动"应用的定义"(definition),产物是给人/给 IDE 用的工程或 JSON;Build/Share 分发"可安装的 APK",产物是给设备安装的二进制。这也是原文档 Notes 中"用 Export 在设备间搬运定义、用 Build/Share 分发安装包"的最佳实践。
需要提醒的是:导出的是模板工程而非 WebToApp 的完整构建管线。WebToApp 本身在手机上完成"一键构建签名 APK"的能力由 export-pipeline.md 描述的core/apkbuilder/(约 24 个文件)支撑——包括ApkConfig主配置结构、ApkConfigJsonFactory序列化、AXML/ARSC 二进制补丁、JarSigner签名与 16KB 对齐等;而 Export 产出的模板则是把配置"翻译"成标准 Android 工程,交由 Android Studio/Gradle 构建。两者定位互补。
五、在 Agent 中触发导出:ExportApp 工具
除卡片菜单外,内置 Agent 也可以通过ExportApp工具程序化触发导出(AppLifecycleTools.kt)。其参数 schema 为:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
appId | integer | 是 | 目标应用 id |
format | enum(template|config) | 否 | 导出格式,默认template |
实现上有两个值得注意的工程细节:
- 未知值直接报错:
format只接受"template"或"config",其余值返回ExportApp: unknown format ...错误,防止拼写错误导致误触发重量级的工程导出; - 结果透传路径:成功后返回
Exported to: <绝对路径>,与 UI 层 Snackbar 展示的路径同源(均来自ExportResult.Success.path)。
该工具同时被注册进 Agent 的工具注册表(ToolRegistryFactory.kt),意味着用户可以用自然语言让 Agent 完成"把这个应用导出成工程模板"这类操作。
六、注意事项与最佳实践
- 按迁移粒度选择形态:只想带走设置 → 导出配置 JSON(单文件、体积最小);想要源码级工程、便于二次开发或离线编译 → 导出工程模板。
- 模板是独立工程:导出的 Gradle 工程包含自己的
applicationId、签名配置与依赖声明,编译环境需满足Android Studio Hedgehog+ 与 JDK 17+,首次编译需联网拉取依赖(模板 README 已注明)。 - 防截屏联动:开启防截屏的应用导出后,其网络安全配置会自动禁用用户 CA 信任,这是安全策略在模板中的延续,改回前请注意影响面。
- 命名会经过清洗:应用名中的特殊字符会在目录/包名中被替换或截断(包名最长 20 字符),若发现导出目录名与原始应用名略有出入,属于预期行为。
- Export 不等于 Share:导出模板用于"迁移定义",若目标是让最终用户直接安装,请走 Build APK / Share APK(构建与分享管线见 export-pipeline.md)。
- 重复导出不覆盖:配置 JSON 文件名带
yyyyMMdd_HHmmss时间戳,多次导出会各自保留;而工程模板目录会先删除同名旧目录再重建,确保产出始终是最新配置。
参考与延伸阅读
- 功能入口与 UI 回调:HomeScreen.kt
- 导出核心实现:AppExporter.kt
- Agent 工具层:AppLifecycleTools.kt
- APK 构建/签名管线(与 Export 互补):docs/developer/export-pipeline.md
- 界面文案定义:Strings.kt
【免费下载链接】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),仅供参考