安装 · 平台
Trusted Web Activity
发布于
Trusted Web Activity(TWA)是一个 Android activity,在 Digital Asset Links 证明 APK 的签名密钥与网站属于同一方之后,用用户的 Chrome 全屏显示一个 web 源,不带地址栏。它是 PWA 上架 Google Play 的途径;Chrome 72 在 Android 上引入了它,该协议对其他浏览器开放,但 Chrome 的文档只记录了 Chrome 自身的支持。
Android 应用本身不包含任何 web 内容。它的启动 activity(来自 android-browser-helper 库的 com.google.androidbrowserhelper.trusted.LauncherActivity)通过 Custom Tabs 服务绑定到用户的默认浏览器,请求以受信任模式打开 PWA 的 start_url,浏览器在自己的进程中渲染站点,使用的是用户的 Cookie、service worker 与存储。
信任在每次启动时建立一次:
- 网站在
/.well-known/assetlinks.json中以关系delegate_permission/common.handle_all_urls列出应用的包名与签名证书的 SHA-256 指纹。 - APK 在
asset_statements字符串资源中声明同一个源。 - 启动时浏览器抓取 assetlinks 文件(以
application/json提供、不经重定向即可访问)并比对指纹。匹配则隐藏地址栏;不匹配、文件缺失或发生重定向则回退为带地址栏的普通 Custom Tab,这是设计中的降级,而不是错误。
由于 Play 在 Play App Signing 下用自己的密钥为上传的应用签名,assetlinks.json 中的指纹必须是 Play 托管的签名密钥,而不是本地的上传密钥;这是生产环境中出现地址栏最常见的原因。
Android 上其他安装路径的区别在于由谁构建产物、能触达什么:
| TWA | WebAPK(Chrome 安装) | 主屏幕快捷方式 | |
|---|---|---|---|
| 分发方 | Google Play(也可 Galaxy Store、F-Droid) | Chrome 在安装时生成 | 任意浏览器 |
| 需要自己构建 Android 项目 | 是(Bubblewrap 或 Android Studio) | 否 | 否 |
| Digital Asset Links | 必需 | 不使用 | 不使用 |
| Play Billing | 是,通过 Digital Goods API | 否 | 否 |
| 更新 | web 内容即时生效;外壳需发布 Play 新版本 | 由 Chrome 重新检查 manifest | 无 |
| 运行于 | 用户的默认浏览器(若支持 TWA) | Chrome | 执行安装的浏览器 |
Play Billing 由网页通过 Digital Goods API(window.getDigitalGoodsService('https://play.google.com/billing'))配合 Payment Request 访问,仅在通过验证的 TWA 内可用;Play 政策要求应用内销售的数字商品走这条路。
下面三个产物就是整个集成:站点上的 assetlinks 文件、由 manifest 生成的外壳,以及页面侧的检测。
发布 Digital Asset Links 声明
Section titled “发布 Digital Asset Links 声明”文件位于源的根目录;每个包名、每个签名密钥各一个数组项(调试密钥与发布密钥需要各自的指纹)。
[{ "relation": ["delegate_permission/common.handle_all_urls"], "target": { "namespace": "android_app", "package_name": "com.example.app", "sha256_cert_fingerprints": [ "14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5" ] }}]Play Console 在“发布 › 设置 › 应用签名 › 应用签名密钥证书”下显示正确的指纹;用 keytool 对上传密钥生成的声明在本地通过,在 Play 分发的构建上失败。
用 Bubblewrap 生成并构建外壳
Section titled “用 Bubblewrap 生成并构建外壳”Bubblewrap 读取 web 应用 manifest,生成一个已填好包名、图标、颜色与 asset_statements 的 Android 项目。
npm i -g @bubblewrap/clibubblewrap init --manifest https://example.com/manifest.webmanifestbubblewrap build # 产出 app-release-signed.apk 与 app-release-bundle.aabbubblewrap validate --url https://example.com/ # 基于 Lighthouse 的 PWA 检查生成的项目锁定了 android-browser-helper 的版本;manifest 变化后用 bubblewrap update 重新生成。把 .aab 交付 Play 意味着 assetlinks.json 中的指纹必须如上所述使用 Play 的签名密钥。
检测页面是否运行在 TWA 内
Section titled “检测页面是否运行在 TWA 内”浏览器会把文档的 referrer 设为启动它的 Android 包,这就是开启 Play 专属功能、隐藏 web 安装提示的信号。
const fromTwa = document.referrer.startsWith('android-app://com.example.app/');
if (fromTwa && 'getDigitalGoodsService' in window) { enablePlayBilling(); // 此处可用 Digital Goods API} else { enableWebCheckout(); // 其他地方走常规 web 支付}installButton.hidden = fromTwa || matchMedia('(display-mode: standalone)').matches;referrer 只在会话的第一次导航中存在,所以要在应用内第一次导航把它清掉之前保存结果(例如存入 sessionStorage);TWA 内 display-mode: standalone 同样为 true,但它无法区分 TWA 与 WebAPK。
- Trusted Web Activities overview(developer.chrome.com)
- Verify Android App Links(developer.android.com)
- Bubblewrap(github.com)
- Trusted Web Activity 浏览器支持
- WebAPK
- getInstalledRelatedApps()
- 分发与商店政策
规范
| 规范 | 状态 |
|---|---|
| Trusted Web Activity 可用性 | 厂商文档 |