Android App Actions 的 WATCH_CONTENT 无法接收参数
结论
问题通常出在 Google Assistant 的路由阶段,与 MainActivity 读取参数的代码无关。如果 Assistant 转向网页搜索、YouTube 或 Spotify,说明 WATCH_CONTENT capability 未被识别或索引,或者语音命令没有匹配到该 BII。应用此时不会收到 Intent。
建议优先检查以下三处:
android:targetPackage与android:targetClass看起来没有指向同一个实际组件。- “play [channelName]”更容易匹配
PLAY_MEDIA,未必会匹配WATCH_CONTENT。 - 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 始终转向网页搜索,应继续检查:
- uploaded variant 是否确实包含 capability。
targetPackage和targetClass是否指向最终组件。- 测试语句是否符合该 BII 的查询语义。
- 当前 BII、参数、语言和地区是否仍受支持。
- internal track 是否属于当前 App Actions 流程支持的端到端测试渠道。
- capability 是否需要额外审核、资格或服务端启用。
第 4 至第 6 项取决于服务端条件。Play Console 没有报错,或者账号已加入开发者 Google Group,都不足以确认 capability 已经生效。
备注:内容仅供参考。
