技能-客户端FAQ

1 DUI-DEV客户端

1.1 DUI-DEV扫码更新后频繁崩溃?

这个问题一般是解决方案内的语音内核和DUI-DEV比较旧,需要更新;
可以查看APP的版本以及产品语音内核的版本,目前最新的内核版本为1.2.6.1,建议更新到最新。
最新DUI-DEV地址:
http://aispeech-dui.oss-cn-shanghai.aliyuncs.com/production/dds/android/V1.2.6.1/dds-demo.apk
如果解决方案的DUI-DEV不方便更新,并且内核已经是最新的,可以使用上面链接的DUI-DEV,版本更新后修改对应版本号链接仍然有效。

1.2 DUI-DEV卡在初始化界面启动不了?

检查手机上有没有其他DDS相关的应用在运行,如果有就杀掉,再重启DUI-DEV。

1.3 DUI-DEV唤不醒,识别不了?

1.检查APP有没有录音权限。
2.重启手机(可能是偶现的系统录音机异常)

1.4 DUI-DEV不显示对话记录,只能听见声音?

检查产品配置页的UI样式,需要选择默认样式;
如果已经选了默认样式仍然不显示,检查解决方案内的UI样式资源是否正常,尝试重新上传。

1.5 DUI-DEV TTS没有声音?

1.DUI-DEV TTS默认使用的闹钟的通道,调高一下闹钟的音量试试。
2.参考1.1,可能是内核版本与SDK版本不兼容导致,尽量保证一致。

1.6 DUI-DEV一直显示授权失败?

1.检查产品内的设备授权个数是否达到上限。
2.如果是test或者dev环境的产品,需要客户端设备连到公司内网才可以请求。

 

2 技能内开发客户端相关问题

2.1 什么时候使用command?什么时候使用nativeApi?

需要回传数据给技能的使用native API,直接下发指令给客户端用command

2.2 技能内如何使用CInfo功能?

cinfo是设备级的存储服务,用来保存联系人、定位信息等数据。

1.首先需要客户端使用SDK接口上传数据到CInfo

Android见https://www.duiopen.com/docs/ct_common_Andriod_SDK 3.18部分

IOS见https://www.duiopen.com/docs/ct_IOSdetail 1.12部分

2.技能内通过$context.system.settings.xxx$(cinfoV2)或$context.xxx$(cinfoV1)来引用

2.3 技能内如何引用客户端nativeApi返回的数据?

客户端nativeApi返回的数据依据协议 https://www.duiopen.com/docs/ct_UI

协议提前定义好的可以直接引用,如$text$引用文本控件的内容,$count$引用列表控件的数目

需要注意:除非是共有的参数,否则引用前必须确定当前控件是否有对应的参数,比如:文本控件条件里不能直接引用$count$,否则dm就会报错

协议未定义的、额外的参数需要加extra引用,如$extra.name$,$extra.city$等,具体引用的格式需要和客户端进行确认。

需要注意:在条件内引用客户端回传参数时必须对参数进行存在判断,否则条件不会命中,且可能直接播报出$extra.xxx$

2.4 词库相关问题?

参考hotword 常见问题汇总的错误原因

2.5 说法在产品页测试和客户端测试结果不一样?

检查客户端产品版本是否和产品页版本一致。
如果确定客户端产品版本与测试页版本一致,且结果还是不一致,需要服务端排查。

 

2.6 先执行command还是先播报回复?

如果这个command需要等回复语播报完成之后再执行,就选择先播报回复语,再执行command;
反之就选择先执行command,再播报回复语。
举个例子:
有个command是播放音乐,
如果是nlgFirst,那么流程是“好的,即将播放”->客户端开始播放;
如果是commandFirst,那么流程是客户端已经开始播放了->nlg也同时播,会出现音乐和nlg一起播

2.7 产品页的错误配置客户端能否修改?

错误播报内容客户端都可以自己配;但是重试次数客户端不能修改。
参考https://www.duiopen.com/docs/ct_common_Andriod_SDK 4.3部分 DDSConfig.K_CUSTOM_TIPS

2.8 command和nativeApi的传参客户端如何获取?

//command
DDS.getInstance().getAgent().subscribe("DUI.MediaController.SetVolume", new CommandObserver() {
    @Override
    public void onCall(String command, String data) {
        if(command.equals("DUI.MediaController.SetVolume")){
            try {
                JSONObject object = new JSONObject(data);
                String volume = object.optString("volume");//获取command下发的参数
                Log.d(TAG, "volume: "+volume);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
});
//nativeApi
DDS.getInstance().getAgent().subscribe("DUI.System.GetInfo", new NativeApiObserver() {
    @Override
    public void onQuery(String nativeApi, String data) {
        if(nativeApi.equals("DUI.System.GetInfo")){
            try {
                JSONObject object = new JSONObject(data);
                String tgt = object.optString("tgt");//获取nativeApi下发的参数
                if(tgt.equals("当前电量")){
                    String power = DeviceUtils.getBatteryLevel() + "%";
                    TextWidget textWidget = new TextWidget();
                    textWidget.addExtra("errId", "0");//nativeApi回传的参数
                    textWidget.addExtra("power", power);//nativeApi回传的参数
                    DDS.getInstance().getAgent().feedbackNativeApiResult(nativeApi,textWidget);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
});

2.9 nativeApi回传的数据如何通过recordId查询?

1.通过recordId在大数据平台查找对应的json日志
2.找到recordId对应的sessionId
3.以sessionId为查询条件重新查找
4.在新的查询结果内找最新一条数据
5.nativeApi回传数据的位置为dm-message-input-widget
ps:如果没有的话,可能是客户端没有回传

2.10 nativeApi回传的数据格式及示例代码

### 文本控件的nativeApi客户端返回示例 JSON格式
```json
{
    "type":"text",
    "name":"default",
    "extra": {
        "errId":"78208",//技能内引用这个参数的方式为 $extra.errId$
        "xxx":"xxx" //技能内引用这个参数的方式为 $extra.xxx$
    }
}
```
### 列表控件的nativeApi客户端返回示例 JSON格式
```json
{
    "type" : "list",
    "name":"default",
    "intentName":"导航",
    "content": [{
            "title": "金鸡湖摩天轮",
            "subTitle": "观枫街1号",
            "imageUrl": "https://img.api.aispeech.com/s/3724150899028.png",
            "linkUrl": "https://map.amap.com/m/7867766776.html",
            "label": "3.6km",
            "extra": {
                "latitude": 120.733062,//技能内引用这个参数的方式为 $content[1].extra.latitude$
                "longitude": 31.26473,
                "tel": "0512-66666666"
            }
        },
        {
            "title": "金鸡湖李公堤",
            "subTitle": "金鸡湖大道888号",
            "imageUrl": "https://img.api.aispeech.com/s/3724150899030.png",
            "linkUrl": "https://map.amap.com/m/78979878979.html",
            "label": "2.6km",
            "extra": {
                "latitude": 124.783483,//技能内引用这个参数的方式为 $content[2].extra.latitude$
                "longitude": 37.324893,
                "tel": "0512-88888888"
            }
        }
    ],
    "totalPages": 5,
    "itemsPerPage": 5,
    "currentPage": 2,
    "recommendations": "[\"第3个\", \"下一页\"]",
    "extra": {
        "source": "amap",//技能内引用这个参数的方式为 $extra.source$
        "apiVersion": "0.3.2"
    }
}
```
### 文本控件的nativeApi客户端返回示例 DDS-Android-SDK格式
```java
DDS.getInstance().getAgent().subscribe("DUI.System.GetInfo", new NativeApiObserver() {
    @Override
    public void onQuery(String nativeApi, String data) {
        if(nativeApi.equals("DUI.System.GetInfo")){
            try {
                JSONObject object = new JSONObject(data);
                String tgt = object.optString("tgt");//获取nativeApi下发的参数
                TextWidget textWidget = new TextWidget();
                textWidget.addExtra("errId", "0");//nativeApi回传的参数
                DDS.getInstance().getAgent().feedbackNativeApiResult(nativeApi,textWidget);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
});
```
### 列表控件的nativeApi客户端返回示例 DDS-Android-SDK格式
```java
DDS.getInstance().getAgent().subscribe("phone.acquire.contacts", new NativeApiObserver() {
    @Override
    public void onQuery(String nativeApi, String data) {
        if (nativeApi.equals("phone.acquire.contacts")) {
            try {
                JSONObject object = new JSONObject(data);
                String name = object.optString("name");//获取nativeApi下发的参数
                ListWidget listWidget = new ListWidget();
                for (int i = 0; i < 10; i++) {
                    ContentWidget widget = new ContentWidget();
                    widget.setTitle("张三" + i);
                    widget.setSubTitle("10086" + i);
                    widget.addExtra("name", "张三" + i);//nativeApi回传的参数,技能内引用方式为$content[i+1].extra.name$
                    widget.addExtra("phone", "10086" + i);
                    listWidget.addContentWidget(widget);
                }
                listWidget.addExtra("errId","0");//nativeApi回传的参数,技能内引用方式为$extra.errId$
                DDS.getInstance().getAgent().feedbackNativeApiResult(nativeApi, listWidget);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
});
```

 

3 客户端DDS SDK功能

什么情况下需要客户端配合SDK的接口去完善技能的体验。

3.1 在技能内使用客户端数据?使用Cinfo接口。

1.使用词库
https://www.duiopen.com/docs/ct_common_Andriod_SDK 3.12部分
2.使用Cinfo上传定位信息
https://www.duiopen.com/docs/ct_common_Andriod_SDK 3.18部分
//如下
try {
    JSONObject object = new JSONObject();
    object.put("city", "苏州");
    object.put("longitude", "120.73696");
    object.put("latitude", "31.254458");
    object.put("time", "2018-08-22T12:46:16+0800");
	ContextIntent in = new ContextIntent("location", object);
    DDS.getInstance().getAgent().updateProductContext(in);
} catch (DDSNotInitCompleteException | JSONException e) {
    e.printStackTrace();
}

3.2 客户端如何在静默情况下命中这个技能?使用triggerIntent接口。

triggerIntent是不通过用户语音,而是通过代码形式去触发技能的一种方式。
通过传入技能名称、任务名称、意图名称、语义槽去命中技能。会跳过识别和语义,直接进入对话。典型场景是按钮点击触发技能。
见https://www.duiopen.com/docs/ct_common_Andriod_SDK 3.11部分

3.3 手写的一句话怎么进入技能?使用sendText接口。

sendText接口和triggerIntent功能比较类似。
通过传入一句话代替用户语音输入。只跳过识别,继续进行语义和对话。典型场景是通过输入框输入文字代替语音。
见https://www.duiopen.com/docs/ct_common_Andriod_SDK 3.15部分

3.4 动态修改识别模型?

1.技能内修改,见https://wiki.aispeech.com.cn/pages/viewpage.action?pageId=55282017#command%E6%8C%87%E4%BB%A4%E9%9B%86%E5%90%88-%E5%88%87%E6%8D%A2%E8%AF%86%E5%88%AB%E8%B5%84%E6%BA%90%E6%A8%A1%E5%9E%8B
2.客户端修改,见https://www.duiopen.com/docs/ct_common_Andriod_SDK 3.20部分

4 技能SDK

技能SDK相关问题请咨询技能同学

4.1 技能SDK是什么?

技能SDK是把需要客户端配合开发的技能的客户端代码集成起来,不用每次对接技能都需要客户端去写这些代码。

5 客户端常用文档

5.1 对外文档

1.DDS Android SDK开发文档(https://www.duiopen.com/docs/ct_common_Andriod_SDK

2.DDS IOS SDK开发文档(https://www.duiopen.com/docs/ct_common_iOS_SDK

3.DDS Linux SDK开发文档(https://www.duiopen.com/docs/ct_common_Embedded_SDK

4.服务对接文档(https://www.duiopen.com/docs/websocket)(https://www.duiopen.com/docs/product_http

5.UI事件及数据定义,Widget相关(https://www.duiopen.com/docs/ct_UI

6.DCA Android SDK开发文档(https://www.duiopen.com/docs/DCA_SDK_Android

7.DCA IOS 开发文档(https://www.duiopen.com/docs/DCA_SDK_iOS