# APP 操作
在设备开发过程中,你可能想要通过第三方APP来为用户提供服务。我们提供了app_action
来支持这样的场景。
消息类型 | 名称 | 必须实现 |
---|---|---|
response | execute | 否,设备需要支持app行为才需实现 |
check | 否,设备需要支持app行为才需实现 | |
request | check_result | 否,设备需要支持app行为才需实现 |
execute_succeed | 否,设备需要支持app行为才需实现 | |
execute_failed | 否,设备需要支持app行为才需实现 |
# context
"iflyos_context": {
...
"app_action": {
"version": "1.2", //升级一个版本
"supported_execute": ["activity","broadcast","service","exit"],//支持的操作,数组。如果该字段不出现则代表全部支持。
"foreground_app": "com.qiyi.video.speaker",
"activity": "com.qiyi.video.speaker.activitiy.SearchActivityNew"
},
...
}
参数 | 类型 | 说明 | 必填 |
---|---|---|---|
version | String | 模块版本,现在是1.2 | 是 |
supported_exetute | Array | 设备支持的操作,如果该项不出现,代表支持全部类型的操作。可取值: activity ,broadcast ,service ,exit | 否 |
foreground_app | String | 当前前景运行的app的包名。如果前景未运行第三方app(运行的是launcher),该字段取值为DEFAULT 。若该字段不出现,默认取值为DEFAULT 。 | 否 |
activity | String | 当前正在前景运行的页面名称。Android设备请传输当前运行的类名。如果没有第三方app在运行,该项可不出现。 | 否 |
版本说明
版本 | 说明 | 更新日期 |
---|---|---|
1.0 | 基础实现 | 2019-08-13 |
1.1 | 增加execute 的类型 | 2019-09-12 |
1.2 | 增加exit 相关,增加supported_execute | 2019-12-12 |
# response
# 执行操作
在用户请求命中语料后,云端会返回一类(针对不同版本的APP的)APP的操作数据。该执行列表中,有可能部分执行不成功,部分执行成功。设备需要按照返回顺序执行,若一项执行失败则执行下一项,只要有一项操作执行成功,就无需执行剩下的操作。
标准协议如下
{
"iflyos_responses": [
...,
{
"header": {
"name": "app_action.execute"
},
"payload": {
"execution_id": "xxx",
"actions": [
{
"execution_id": "",
"data": {
"type": "activity",
"uri": "",
"package_name": "",
"category_name": "",
"friendly_name": "",
"class_name": "",
"action_name": "",
"extras": {
"key": "value",
}
},
"version": {
"start": 0,
"end": 11304,
}
},
{
"execution_id": "",
"data": {
"type": "activity",
"uri": "",
"package_name": "",
"category_name": "",
"friendly_name": "",
"class_name": "",
"action_name": "",
"extras": {
"key": "value",
}
},
"version": {
"start": 0,
"end": 11304,
}
}
]
}
}
}
}
参数 | 类型 | 说明 | 必有 |
---|---|---|---|
execution_id | String | 代表这一组执行的 id | 是 |
actions | List | action 列表,按顺序执行。执行成功一个 action 后,其他的 action 无需执行。 | 是 |
actions.[i].execution_id | String | 代表这个 action 的唯一标识 | 是 |
actions.[i].data | Object | 执行 app_action 时需要的 data。 | 是 |
actions.[i].data.package_name | String | 应用包名,,只有 Android 设备的执行返回才会出现这个字段 | 否 |
actions.[i].data.category_name | String | category 数据,只有 Android 设备的执行返回才会出现这个字段 | 否 |
actions.[i].data.type | String | action 的类型,取值:activity,service,broadcast,exit。当不出现的时候,默认取值 activity。只有 Android 设备的执行返回才会出现这个字段 | 否 |
actions.[i].data.friendly_name | String | 应用显示的名称,一般为中文 | 否 |
actions.[i].data.uri | String | uri 数据,iOS 设备执行必填,Android 设备非必填。 | 否 |
actions.[i].data.class_name | String | class 数据,只有 Android 设备的执行返回才会出现这个字段 | 否 |
actions.[i].data.action_name | String | action 数据,只有 Android 设备的执行返回才会出现这个字段 | 否 |
actions.[i].data.extras | Object | 该 app_action 的附带信息,只有 Android 设备的执行返回才会出现这个字段 | 否 |
actions.[i].version | Object | 该 action 支持的版本范围,用户设备对比本地的 APP 版本。若本地 APP 版本不在这个范围内,可以选择不执行。如果是 iOS 设备,这个字段不会出现。 | 否 |
actions.[i].version.start | Long | 支持该 action 的最小版本,若未填写,默认为 0 | 否 |
actions.[i].version.end | Long | 支持该 action 的最大版本,若未填写,代表支持版本无限大。 | 否 |
# 收到指令后设备的执行逻辑
注意
收到的response
中,package_name
不一定与当前设备前景运行的app一致。
不同操作系统收到的 app_action
有所不同,下面是一些简单的示例,但不包含对应用版本的判断执行。
Android
若设备系统为 Android,则可能收到形如以下格式的 app_action
数据。
{
// 其他属性
"data": {
"type": "activity",
"uri": "URI_SAMPLE",
"package_name": "PACKAGE_NAME_SAMPLE",
"category_name": "CATEGORY_NAME_SAMPLE",
"friendly_name": "FRIENDLY_NAME_SAMPLE",
"class_name": "CLASS_NAME_SAMPLE",
"action_name": "ACTION_NAME_SAMPLE",
"extras": {
"EXTRA_KEY_SAMPLE_1": "EXTRA_VALUE_SAMPLE_1",
"EXTRA_KEY_SAMPLE_2": "EXTRA_VALUE_SAMPLE_2",
// 其他的 extra
}
}
// 其他属性
}
那么对于这些数据,设备端应该执行类似下方的处理
val intent = Intent()
intent.data = Uri.parse(URI_SAMPLE)
intent.setPackage(PACKAGE_NAME_SAMPLE)
intent.setClassName(PACKAGE_NAME_SAMPLE, CLASS_NAME_SAMPLE)
// 上述两步也可换为 intent.component = ComponentName(PACKAGE_NAME_SAMPLE, CLASS_NAME_SAMPLE)
intent.addCategory(CATEGORY_NAME_SAMPLE)
intent.putExtra(EXTRA_KEY_SAMPLE_1, EXTRA_VALUE_SAMPLE_1)
intent.putExtra(EXTRA_KEY_SAMPLE_2, EXTRA_VALUE_SAMPLE_2)
when (data.type) {
"activity" -> {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
}
"service" -> {
context.startService(intent)
}
"broadcast" -> {
context.sendBroadcast(intent)
}
}
若 response
中 data
不包含某些字段,则相当于上述代码对应的那一行不执行(例如若不存在 category_name
属性,则 intent.addCategory(...)
不被调用)。
iOS
若设备为 iOS 系统,那么对于收到 app_action
的 response
,data
中只存在 uri
字段。设备端对于 uri
字段做如下处理。
if (@available(iOS 10.0, *)) {
// ios 10 及以后
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:uri]]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:uri] options:@{} completionHandler:nil];
} else {
// 执行无法打开应用的逻辑
}
} else {
// ios 10 之前
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:uri]]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:uri]];
} else {
// 执行无法打开应用的逻辑
}
}
# 通用的应用退出方式
若你的设备不支持exit操作,但用户请求退出某一个APP,你可能会收到以下response
。
{
"iflyos_responses":[
{
"header":{
"name":"app_action.execute"
},
"payload":{
"execution_id":"xxx",
"actions":[
{
"execution_id":"",
"data":{
"type":"activity",
"action_name":"android.intent.action.MAIN",
"category_name":"android.intent.category.HOME"
}
}
]
}
}
]
}
# 判断是否能执行
为了更好的用户体验,云端可能会发送这个 response
来确定设备是否能够支持某些 execute
,设备需要正确处理这个 response
,并返回正确的结果。如果设备告知云端支持该 execute
,云端会再下发 execute
的 response
。
在收到这个 response
时,你需要检查每一项是否能正确执行,并返回结果。
返回示例
{
"iflyos_responses": [
...,
{
"header": {
"name": "app_action.check"
},
"payload": {
"check_id": "xxx",
"actions": [
{
"execution_id": "xxxxx",
"data": {
"package_name": "",
"uri": ""
}
},
{
"execution_id": "xxxxx",
"data": {
"package_name": "",
"uri": ""
}
},
],
}
}
]
}
# request
# 执行成功
返回的一系列actions中,只要有一个action执行成功,即执行成功,发送执行成功的请求,带上执行成功的action的id。
请求示例
{
"iflyos_header": {...},
"iflyos_context": {...},
"iflyos_request": {
"header": {
"name": "app_action.execute_succeed",
"request_id": "xxxxxxxx"
},
"payload": {
"execution_id": "xxxxx",
"feedback_text": "xxxxx"
}
}
}
参数 | 类型 | 说明 | 必填 |
---|---|---|---|
iflyos_header | Object | 构建的通用 iflyos_header | 是 |
iflyos_context | Object | 构建的通用 iflyos_context | 是 |
execution_id | String | 执行成功的action的唯一标识 | 是 |
feedback_text | String | 执行失败反馈给用户的语音提示,iFLYOS收到后将进行语音合成并下发至设备,最多100个字符。若该字段不出现,云端将反馈默认回复。字段出现但取值为空,云端将不会回复。 | 否 |
# 执行失败
云端返回的一系列action中,没有一个action执行成功,则返回执行失败。
请求示例
{
"iflyos_header": {...},
"iflyos_context": {...},
"iflyos_request": {
"header": {
"name": "app_action.execute_failed",
"request_id": "xxxxxxxx"
},
"payload": {
"execution_id": "xxxxx",
"failure_code": "xxxx",
"feedback_text": "xxxxx"
}
}
}
参数 | 类型 | 说明 | 必填 |
---|---|---|---|
iflyos_header | Object | 构建的通用 iflyos_header | 是 |
iflyos_context | Object | 构建的通用 iflyos_context | 是 |
execution_id | String | 执行失败的action的唯一标识 | 是 |
failure_code | String | 失败类型代码,详见下方 | 是 |
feedback_text | String | 执行失败反馈给用户的语音提示,iFLYOS收到后将进行语音合成并下发至设备,最多100个字符。若该字段不出现,云端将反馈默认回复。字段出现但取值为空,云端将不会回复。 | 否 |
错误类型
提示
若多个执行失败的原因不同,则按照错误类型的优先级返回优先级高的失败原因。
说明 | 描述 |
---|---|
ACTION_UNSUPPORTED | 不支持这个action |
APP_NOT_FOUND | 客户端没有这个app |
INTERNAL_ERROR | 内部错误 |
# 检查结果
在检查设备是否可以执行该操作之后,需要把检查结果发送至云端。
{
"iflyos_header": {...},
"iflyos_context": {...},
"iflyos_request": {
"header": {
"name": "app_action.check_result",
"request_id": "xxxxxxxx"
},
"payload": {
"check_id": "xxxxx",
"actions": [
{
"execution_id": "xxxxx",
"result": true
},
{
"execution_id": "xxxxx",
"result": false
}
]
}
}
}