PAYATHON 2026

Android App Actions 的 WATCH_CONTENT 无法接收参数

排障赵师傅

结论

问题通常出在 Google Assistant 的路由阶段,与 MainActivity 读取参数的代码无关。如果 Assistant 转向网页搜索、YouTube 或 Spotify,说明 WATCH_CONTENT capability 未被识别或索引,或者语音命令没有匹配到该 BII。应用此时不会收到 Intent。

建议优先检查以下三处:

  1. android:targetPackage 与 android:targetClass 看起来没有指向同一个实际组件。
  2. “play [channelName]”更容易匹配 PLAY_MEDIA,未必会匹配 WATCH_CONTENT。
  3. internal track 上传成功只说明安装包通过了 Play 的构建检查,无法证明 Assistant 已经解析并索引 App Actions 配置。

App Actions Test Tool 弃用后,仍可验证 APK、组件和参数处理代码。本地工具无法完整模拟 Assistant 的语义识别和服务端路由。

先修正目标组件

示例中的配置是:

android:targetPackage="com.awesome.app"
android:targetClass="com.something.else.MainActivity"

如果这就是实际配置,而非脱敏后的示例,那么 Assistant 即使识别了 capability,也可能无法启动目标组件。

targetPackage 必须填写上传变体最终生成的 applicationId,不能填写源码中的 namespace。targetClass 必须填写合并 Manifest 后 Activity 的完整类名。

假设最终组件是 com.awesome.app.MainActivity,可以先将配置简化为:

<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">

    <capability android:name="actions.intent.WATCH_CONTENT">
        <intent
            android:action="android.intent.action.VIEW"
            android:targetPackage="com.awesome.app"
            android:targetClass="com.awesome.app.MainActivity">

            <parameter
                android:name="content.name"
                android:key="feature" />
        </intent>
    </capability>

</shortcuts>

除非当前 BII 文档明确要求,否则先移除:

android:mimeType="text/*"

传递普通字符串参数不需要这个属性。保留不需要或不受支持的属性,会给排查增加干扰。

如果 flavor 设置了不同的 applicationIdSuffix,例如:

applicationIdSuffix = ".flavorA"

targetPackage 也要改成最终包名,例如:

android:targetPackage="com.awesome.app.flavorA"

最终值应在构建后的 merged manifest 或 APK Analyzer 中确认,不要根据源码目录推测。

确认 shortcuts.xml 已进入上传构建

shortcuts.xml 位于:

app/src/flavorA/res/xml/shortcuts.xml

只有构建 flavorA 对应的变体时,这个文件才会进入产物。因此,需要检查上传的 APK,或者 App Bundle 生成的 APK,不能只检查源码。

使用 Android Studio 的 APK Analyzer 确认:

  • 产物中存在 res/xml/shortcuts.xml。
  • Manifest 包含 android.app.shortcuts 元数据。
  • 该元数据位于带有 MAIN 和 LAUNCHER 的 Activity 内。
  • Activity 的最终名称、包名和 android:exported 值正确。
  • 当前构建的 applicationId 与 targetPackage 完全一致。

Manifest 可以保持以下基本结构:

<activity
    android:name=".MainActivity"
    android:exported="true">

    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

    <meta-data
        android:name="android.app.shortcuts"
        android:resource="@xml/shortcuts" />
</activity>

Play Console 没有报错,只能说明它没有发现相应的构建问题,不能据此确认 shortcuts.xml 中的 BII 名称、参数映射和 Assistant 可用性都已通过完整校验。

用 ADB 单独验证应用侧处理

先绕过 Assistant,直接向同一个组件发送 Intent:

adb shell am force-stop com.awesome.app

adb shell am start -W \
  -a android.intent.action.VIEW \
  -n com.awesome.app/com.awesome.app.MainActivity \
  --es feature "News 24"

然后查看日志:

adb logcat -s AppActions

如果 Activity 能正常启动,并输出:

Received channel: News 24

就可以确认目标组件能够启动,应用可以处理 ACTION_VIEW 并读取 feature 字符串,onCreate() 或 onNewIntent() 中的处理逻辑也能正常运行。

这项测试无法证明 Assistant 已识别 capability,但可以排除应用侧的问题。

调试期间可以输出全部 extras,避免应用收到 Intent 后因参数名称等问题而看不到有效信息:

private fun handleIntent(intent: Intent?) {
    if (intent == null) return

    Log.d(
        "AppActions",
        "action=${intent.action}, component=${intent.component}, data=${intent.data}"
    )

    intent.extras?.keySet()?.forEach { key ->
        Log.d("AppActions", "extra[$key]=${intent.extras?.get(key)}")
    }

    if (intent.action == Intent.ACTION_VIEW) {
        val channelName = intent.getStringExtra("feature")
        if (!channelName.isNullOrBlank()) {
            Log.d("AppActions", "Received channel: $channelName")
            Toast.makeText(
                this,
                "Channel: $channelName",
                Toast.LENGTH_LONG
            ).show()
        }
    }
}

如果 Activity 使用了会复用实例的启动模式,还要在 onNewIntent() 中更新当前 Intent:

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
    handleIntent(intent)
}

语音命令要符合 BII 语义

WATCH_CONTENT 和 PLAY_MEDIA 对应不同的语义入口,不能随意替换。

测试 WATCH_CONTENT 时,应先使用明确包含 “watch” 语义的命令,例如:

Hey Google, watch News 24 on MyAwesomeApp

如果使用:

Hey Google, play News 24 on MyAwesomeApp

Assistant 很可能会将其理解为媒体播放请求,并转交给 PLAY_MEDIA、YouTube、Spotify 或默认媒体提供方。

Assistant 还需要能够识别应用名称。建议使用 Play 商店实际显示的名称,分别测试:

Open MyAwesomeApp
Watch News 24 on MyAwesomeApp

第一条命令成功,只能证明 Assistant 知道如何启动该应用,无法证明 WATCH_CONTENT 已注册。

同时确认设备上的 Assistant 账号、Play 测试账号,以及安装 internal track 应用时使用的账号一致。当前语言和地区也必须在该 BII 的支持范围内。BII 支持的语言、参数和查询样式可能发生调整,应以当前发布的对应 BII 文档为准。

自由文本参数未必能被抽取

content.name 虽然看起来是普通字符串,但 Assistant 能否从任意口语内容中识别出该参数,取决于 BII 的参数定义、语言支持、查询模式和服务端排序。

News 24、频道简称、同音词或自定义频道名,都可能被 Assistant 识别为网页搜索词,或其他媒体服务中的内容。android:key="feature" 只规定识别成功后如何把参数写入 Intent extra,无法要求 Assistant 将任意文本识别成 content.name。

如果当前 WATCH_CONTENT 文档允许为 content.name 提供 inventory,可以为频道配置 inline inventory 或动态 inventory,并添加常用别名。必须先确认该参数支持 inventory,不能直接套用其他 BII 的示例。

Test Tool 弃用后的调试范围

目前可以稳定验证的内容包括:

  • 检查 merged manifest。
  • 检查 APK 中的 shortcuts.xml。
  • 使用 ADB 验证组件启动和 extras 读取。
  • 使用 APK Analyzer 核对最终包名、类名和资源。
  • 通过日志记录应用实际收到的 action、component、data 和 extras。

这些检查无法解释 Assistant 为什么没有选择该 capability。internal track 是否已被服务端索引、该 BII 是否对当前账号和地区开放,以及命令最终命中了哪条语义路由,通常都不会在 Logcat 或 Play Console 中显示详细错误。

如果 ADB 测试成功,而 Assistant 始终转向网页搜索,应继续检查:

  1. uploaded variant 是否确实包含 capability。
  2. targetPackage 和 targetClass 是否指向最终组件。
  3. 测试语句是否符合该 BII 的查询语义。
  4. 当前 BII、参数、语言和地区是否仍受支持。
  5. internal track 是否属于当前 App Actions 流程支持的端到端测试渠道。
  6. capability 是否需要额外审核、资格或服务端启用。

第 4 至第 6 项取决于服务端条件。Play Console 没有报错,或者账号已加入开发者 Google Group,都不足以确认 capability 已经生效。

备注:内容仅供参考。