167 lines
6.6 KiB
Markdown
167 lines
6.6 KiB
Markdown
|
|
# 语音协议广播测试脚本
|
|||
|
|
|
|||
|
|
`adb shell am broadcast` 形式的联调脚本集合,覆盖 [可行性评估文档](../../../docs/2026-08-22-语音影视接入可行性评估.md) §6.1 中定义的统一协议(`action=com.pukka.jiecheng.action.VOICE_COMMAND`),用于在没有第三方语音 App 时手工驱动 voice 模块。
|
|||
|
|
|
|||
|
|
> 适用范围:`bash`(Git Bash 即可)。脚本里所有路径用 Unix 风格。
|
|||
|
|
|
|||
|
|
## 1. 目录结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
test/voice_helper/
|
|||
|
|
├── lib/
|
|||
|
|
│ └── common.sh # 公共函数:payload 构造 / 广播发送 / 应用级操作
|
|||
|
|
├── jump_film.sh # 单片跳转 JUMP/FILM
|
|||
|
|
├── jump_category.sh # 分类跳转 JUMP/CATEGORY
|
|||
|
|
├── search.sh # 语音搜索 SEARCH
|
|||
|
|
├── control.sh # 播放控制 CONTROL/<action>
|
|||
|
|
├── cold_start.sh # 冷启动单片跳转(force-stop + 投递 + 拉起)
|
|||
|
|
├── throttle_test.sh # 2 秒内连续投递同类命令(验证节流)
|
|||
|
|
├── security_test.sh # 非白名单 sourceApp 投递(验证签名校验)
|
|||
|
|
├── listen_callback.sh # 反向广播回调监听(adb logcat)
|
|||
|
|
├── run_all.sh # 顺序执行全部用例
|
|||
|
|
└── README.md
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 2. 协议约定(与文档 §6.1 一致)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
action: com.pukka.jiecheng.action.VOICE_COMMAND
|
|||
|
|
permission: com.pukka.jiecheng.permission.VOICE_COMMAND
|
|||
|
|
component: com.pukka.jiecheng/.voice.receiver.VoiceCommandReceiver
|
|||
|
|
|
|||
|
|
extras:
|
|||
|
|
requestId string 第三方生成的请求 ID,回传时带回
|
|||
|
|
sourceApp string 第三方包名
|
|||
|
|
sourcePlatform string 第三方平台标识(用于选择 VendorAParser/BParser)
|
|||
|
|
commandType string JUMP / SEARCH / CONTROL
|
|||
|
|
payload string JSON,业务字段
|
|||
|
|
callbackAction string 反向广播 action,由第三方传入
|
|||
|
|
timestamp long 毫秒
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`payload` 按 `commandType` 分支:
|
|||
|
|
|
|||
|
|
| commandType | payload 字段 |
|
|||
|
|
|---|---|
|
|||
|
|
| `JUMP` | `jumpType` (`FILM`/`CATEGORY`/`ACTOR`/`DIRECTOR`) + 对应 `*Id`/`*Name`,可带 `autoPlay` |
|
|||
|
|
| `SEARCH` | `filmName` / `actorName` / `directorName` / `category` / `unionStyle` / `region` / `releaseDate` |
|
|||
|
|
| `CONTROL`| `action` (`PLAY`/`PAUSE`/`FULLSCREEN_ENTER`/`FULLSCREEN_EXIT`/`SEEK_FORWARD`/`SEEK_BACKWARD`/`SEEK_TO`/`PREV`/`NEXT`/`SELECT_INDEX`/`PAGE_NEXT`/`PAGE_PREV`/`GOTO_PAGE`) + `seconds` / `index` / `page` |
|
|||
|
|
|
|||
|
|
## 3. 快速开始
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 设备已连接 adb 后:
|
|||
|
|
cd test/voice_helper
|
|||
|
|
|
|||
|
|
# 单片跳转(默认 filmId=film-demo-001 / autoPlay=true)
|
|||
|
|
./jump_film.sh
|
|||
|
|
|
|||
|
|
# 自定义参数
|
|||
|
|
./jump_film.sh film-12345 "我的影片" true
|
|||
|
|
|
|||
|
|
# 分类跳转
|
|||
|
|
./jump_category.sh cat-action "动作片"
|
|||
|
|
|
|||
|
|
# 语音搜索
|
|||
|
|
./search.sh "流浪地球"
|
|||
|
|
./search.sh "流浪地球" "吴京"
|
|||
|
|
|
|||
|
|
# 播放控制
|
|||
|
|
./control.sh PAUSE
|
|||
|
|
./control.sh SEEK_FORWARD seconds=10
|
|||
|
|
./control.sh SEEK_TO seconds=300
|
|||
|
|
./control.sh SELECT_INDEX index=3
|
|||
|
|
./control.sh GOTO_PAGE page=2
|
|||
|
|
|
|||
|
|
# 冷启动(force-stop → 投递 → 拉起 MainActivity)
|
|||
|
|
./cold_start.sh
|
|||
|
|
|
|||
|
|
# 2 秒内连续 5 次 PAUSE,验证节流
|
|||
|
|
./throttle_test.sh PAUSE 5
|
|||
|
|
|
|||
|
|
# 非白名单 sourceApp 投递(验证拦截)
|
|||
|
|
./security_test.sh com.attacker.malicious
|
|||
|
|
|
|||
|
|
# 反向广播监听(需 voice 模块按 tag 打印回调日志,tag 默认 VoiceCommand)
|
|||
|
|
./listen_callback.sh # 监听全部
|
|||
|
|
./listen_callback.sh vt-1756000000-12345 # 只过滤指定 requestId
|
|||
|
|
|
|||
|
|
# 一键全量
|
|||
|
|
./run_all.sh
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 4. 环境变量
|
|||
|
|
|
|||
|
|
| 变量 | 默认值 | 说明 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| `ACTION_VOICE_COMMAND` | `com.pukka.jiecheng.action.VOICE_COMMAND` | 广播 action |
|
|||
|
|
| `PERMISSION_VOICE` | `com.pukka.jiecheng.permission.VOICE_COMMAND` | 协议权限 |
|
|||
|
|
| `RECEIVER_COMPONENT` | `com.pukka.jiecheng/.voice.receiver.VoiceCommandReceiver` | 显式组件 |
|
|||
|
|
| `MAIN_ACTIVITY_COMPONENT` | `com.pukka.jiecheng/.MainActivity` | 冷启动入口 |
|
|||
|
|
| `TEST_APP_PKG` | `com.pukka.jiecheng` | 应用包名 |
|
|||
|
|
| `DEFAULT_SOURCE_APP` | `com.test.voicehelper` | 模拟第三方包名 |
|
|||
|
|
| `DEFAULT_PLATFORM` | `vendorA` | 模拟平台 |
|
|||
|
|
| `DEFAULT_CALLBACK_ACTION`| `com.test.voicehelper.action.VOICE_CALLBACK` | 反向广播 action |
|
|||
|
|
| `TEST_REQUEST_PREFIX` | `vt-` | requestId 前缀 |
|
|||
|
|
| `SKIP_PERMISSION_CHECK` | `0` | 开发期临时绕开 signature-level permission 校验时置 1 |
|
|||
|
|
| `LOG_TAG` | `VoiceCommand` | `listen_callback.sh` 监听的 logcat tag |
|
|||
|
|
|
|||
|
|
示例:自定义第三方包名
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
TEST_REQUEST_PREFIX=demo- DEFAULT_SOURCE_APP=com.xiaomi.voice ./jump_film.sh
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 5. 关于 `signature-level permission`
|
|||
|
|
|
|||
|
|
文档 §6.2 规定 Receiver 使用自定义 `signature-level permission`(`com.pukka.jiecheng.permission.VOICE_COMMAND`)。`adb shell` 默认以 `shell` 用户身份投递,**不持有第三方签名权限**,广播会被系统直接丢弃。
|
|||
|
|
|
|||
|
|
联调期三种处理方式:
|
|||
|
|
|
|||
|
|
1. **临时降级(推荐)**:在 `app/build.gradle` 给 `debug` flavor 注入 `manifestPlaceholder`:
|
|||
|
|
```groovy
|
|||
|
|
debug {
|
|||
|
|
manifestPlaceholders = [voiceProtectionLevel: "normal"]
|
|||
|
|
}
|
|||
|
|
release {
|
|||
|
|
manifestPlaceholders = [voiceProtectionLevel: "signature"]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
然后在 `AndroidManifest.xml`:
|
|||
|
|
```xml
|
|||
|
|
<permission
|
|||
|
|
android:name="com.pukka.jiecheng.permission.VOICE_COMMAND"
|
|||
|
|
android:protectionLevel="${voiceProtectionLevel}" />
|
|||
|
|
```
|
|||
|
|
2. **拷贝脚本到端内**:在应用内临时放一个 `BroadcastSender` Activity 直接发广播,绕过 shell 权限。
|
|||
|
|
3. **改 adb 用户**:通过 `adb root` 切到 root 身份,仅在 userdebug 镜像生效。
|
|||
|
|
|
|||
|
|
脚本本身不强制任何一种处理,遇到权限拦截请按上面方式放开。
|
|||
|
|
|
|||
|
|
## 6. 验证 checklist(对应文档 §12)
|
|||
|
|
|
|||
|
|
联调完成后逐项打勾:
|
|||
|
|
|
|||
|
|
- [ ] 应用未启动时第三方冷启动并执行命令(`cold_start.sh`)
|
|||
|
|
- [ ] 应用未激活时被守卫拦截,回传 `DEVICE_NOT_ACTIVATED`
|
|||
|
|
- [ ] 正在播放时收到搜索 / 分类命令先退出再跳转
|
|||
|
|
- [ ] 2 秒内连续多次控制命令只保留最后一条(`throttle_test.sh`)
|
|||
|
|
- [ ] 第三方收到成功 / 失败回传(`listen_callback.sh` 配合 logcat)
|
|||
|
|
- [ ] `SELECT_INDEX` / `GOTO_PAGE` 在播放页列表中正确选中
|
|||
|
|
- [ ] 白名单外的 `sourceApp` 被拦截、不回传(`security_test.sh`)
|
|||
|
|
|
|||
|
|
## 7. 调试技巧
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 查看应用包内注册的 Receiver
|
|||
|
|
adb shell dumpsys package com.pukka.jiecheng | grep -i receiver
|
|||
|
|
|
|||
|
|
# 查看设备上所有待发广播
|
|||
|
|
adb shell dumpsys activity broadcasts
|
|||
|
|
|
|||
|
|
# 查看最近一次 am broadcast 的返回结果(带 requestId 过滤)
|
|||
|
|
adb shell am broadcast -a com.pukka.jiecheng.action.VOICE_COMMAND -n ... --es requestId probe
|
|||
|
|
|
|||
|
|
# 实时过滤 voice 模块日志
|
|||
|
|
adb logcat -v threadtime VoiceCommand:V VoiceCommandLogger:V "*:S"
|
|||
|
|
```
|