Android SDK集成
一. 集成准备
1.1 获取产品ID
集成SDK之前,您首先需要到DUI控制台创建产品,获取如下的产品ID。
 
1.2 下载和导入SDK
目前Android SDK只支持Android Studio开发环境
 javadoc详见SDK包
Android Demo 码云源码地址:https://gitee.com/szaispeech/dui-dds-android-sdk-samples
1.2.1 手动集成
集成SDK要求Android 4.0及其以上的系统且/data分区剩余空间至少200MB
 可以前往SDK下载页下载最新的SDK包。
如需SDK历史版本,请前往Android_SDK下载页。

将SDK包中的aar文件( 如lib-dds-1.0.2.1.aar )导入到现有的工程中,放入到libs目录下,并添加配置:
build.gradle
 repositories{
     flatDir{
         dirs 'libs'
         }
 }
在build.gradle中配置引用sync工程即可。
build.gradle
dependencies {
    compile(name:'lib-dds-1.1.11.1', ext:'aar')
    compile 'com.google.android.exoplayer:exoplayer-core:2.6.0'
    compile 'com.squareup.okhttp3:okhttp:3.9.0'
    compile 'com.squareup.okio:okio:1.13.0'
}
二. 初始化SDK
使用以下方法来初始化SDK:
初始化
DDS.getInstance().init(
  getApplicationContext(),
  new DDSConfig()
    .addConfig(DDSConfig.K_DEVICE_ID, deviceId)
    .addConfig(DDSConfig.K_PRODUCT_ID, productId)
    .addConfig(DDSConfig.K_USER_ID, userId)
    .addConfig(DDSConfig.K_ALIAS_KEY, aliasKey)
    .addConfig(DDSConfig.K_API_KEY, apiKey)
    .addConfig(DDSConfig.K_PRODUCT_KEY, productKey)
    .addConfig(DDSConfig.K_PRODUCT_SECRET, productSecret)
    .addConfig(DDSConfig.K_DUICORE_ZIP, "duicore.zip")//该配置的用法详见下方"注意"
    .addConfig(DDSConfig.K_USE_UPDATE_DUICORE, "false"), 
  new DDSInitListener() {
    @Override
    public void onInitComplete(boolean isFull) {
        AILog.d(TAG, "onInitComplete: " + isFull);
    }
 
    @Override
    public void onError(int what, String msg) {
        AILog.d(TAG, "onError: " + what + ", error: " + msg);
    }
}, new DDSAuthListener() {
    @Override
    public void onAuthSuccess() {
        AILog.d(TAG, "onAuthSuccess");
    }
 
    @Override
    public void onAuthFailed(String errId, String error) {
        AILog.d(TAG, "onAuthFailed: " + errId + ", error:" + error);
    }
});
注意:
• addConfig(DDSConfig.K_DUICORE_ZIP, "duicore.zip")这行配置的使用规则:
1)如果duicore.zip的放置位置在assets目录下,那么就可以使用如代码中的写法,直接使用文件名:duicore.zip;
2)如果duicore.zip没有放置在assets目录下,就必须使用duicore.zip文件的绝对路径;
3)在duicore.zip所在的文件夹中,必须配置与duicore.zip文件名相匹配的md5文件;举例:名为duicore.zip的资源文件放置在assets目录下,那么在assets中必须存在duicore.zip.md5sum文件;
在收到 onInitComplete 回调之后,就可以使用DDS来完成对应的操作。
 isFull参数如果为false,则表示不完全初始化,缺失资源包,您需要等待资源包的更新下载完成或者内置一份资源包; 如果为true,则表示完全初始化,所有功能就绪。
 除了通过监听onInitComplete回调外,还可以直接通过判断DDS.getInstance().getInitStatus()的返回值来检查初始化是否完毕。
/**
 * 获取当前初始化的状态
 *
 * @return DDS.INIT_COMPLETE_NONE     还未初始化完成,表示DDS正在初始化
 *         DDS.INIT_COMPLETE_NOT_FULL 部分初始化完成,表示DDS已经初始化完成,但还没有完成更新
 *         DDS.INIT_COMPLETE_FULL     完全初始化完成,已经完成更新
 */
DDS.getInstance().getInitStatus();
注意:
 • DDS.getInstance().init()和DDS.getInstance().release()方法不会阻塞应用程序的主线程,也不会影响应用程序性能。
 • 当未初始化完成时,尝试调用一些方法时,会抛出 DDSNotInitCompleteException 异常。
 • 当调用DDS.getInstance().release()之后,之前注册的observers会失效,再次DDS.getInstance().init()后,您需要对之前的observers重新注册。
使用以下方法来释放SDK:
DDS.getInstance().release();
2.1 参数与配置
需要由开发者在DDSConfig中填写的配置项为:
| 参数名 | 取值 | 说明 | 是否必须 | 默认值 | 
|---|---|---|---|---|
| DDSConfig.K_PRODUCT_ID | 产品ID字符串 | 产品ID | 必须 | 无 | 
| DDSConfig.K_ALIAS_KEY | prod/test/(自定义分支) | 产品分支 | 必须 | 无 | 
| DDSConfig.K_USER_ID | 用户ID字符串 | 用户ID,预留字段 | 必须 | 无 | 
| DDSConfig.K_API_KEY | apikey字符串 | 限制一个API Key只被指定的客户端使用,来源:DUI控制台-产品接入-授权管理 | 必须 | 无 | 
| DDSConfig.K_PRODUCT_KEY | 产品Product Key | 用于设备注册请求签名,来源:DUI控制台-产品接入-授权管理 | 必须 | 无 | 
| DDSConfig.K_PRODUCT_SECRET | 产品Product Secret | 用于设备注册请求签名,来源:DUI控制台-产品接入-授权管理 | 必须 | 无 | 
| DDSConfig.K_DEVICE_ID | 设备ID | 用于授权认证的原始设备ID,请务必确保设备ID唯一。若不填,则SDK自己收集设备ID。可以通过DDS.getInstance().getDeviceName()获取授权认证后的唯一ID | 可选 | IMEI | 
2.2 处理授权
SDK在初始化完毕之后,必须进行有效的授权后方可正常使用。
2.2.1 Profile文件授权
适用于一般产品的授权,请在产品的授权管理中申请API Key:授权操作说明
在DDSConfig中设置以下授权参数。
// 将API key、Product Key、Product Secret填入到产品配置中
config.addConfig(DDSConfig.K_API_KEY, "f09dd3xxxxxxxxxxxxxx2d2292");
config.addConfig(DDSConfig.K_PRODUCT_KEY, "89eb8daf750799a16dc24e18c12xxxxx");
config.addConfig(DDSConfig.K_PRODUCT_SECRET, "c803c737c665a1facccfa0b4abexxxxx");
在SDK初始化时,可以设置 DDSAuthListener 来监听授权的情况。
SDK初始化完毕后,您可以使用 DDS.getInstance().isAuthSuccess() 来判断当前是否授权成功。第一次使用SDK,需要主动调用DDS.getInstance().doAuth()的方法做一次授权。
授权操作需要连接到互联网。
授权成功会回调DDSAuthListener.onAuthSuccess,授权失败会收到回调DDSAuthListener.onAuthFailed,需要重新调用DDS.getInstance().doAuth()。
Profile文件的错误码范围从 "070601“ – "070622",处理流程请参考对应的描述(详见第五节:错误码描述)。
2.3 处理更新
如果您想对发布的产品持续进行免安装的更新和升级,您需要做以下几个操作:
2.3.1 请求更新
您可以选择在合适的时候发起更新请求。当sdk在检查到有更新后,会自动下载资源并进行热更新,结果会以回调的方式通知。
DDS.getInstance().getUpdater().update(new DDSUpdateListener() {
    @Override
    public void onUpdateFound(String detail) {
        AILog.d(TAG, "onUpdateFound");
    }
 
    @Override
    public void onUpdateFinish() {
        AILog.d(TAG, "onUpdateFinish");
    }
 
    @Override
    public void onDownloadProgress(float progress) {
        AILog.d(TAG, "onDownloadProgress :" + progress);
    }
 
    @Override
    public void onError(int what, String error) {
        AILog.d(TAG, "onError :" + what + ", error: " + error);
    }
 
    @Override
    public void onUpgrade(String version) {
        AILog.d(TAG, "onUpgrade :" + version);
    }
};
2.3.2 处理更新推送
在您成功发布产品之后,若您已经订阅了消息sys.resource.updated,则会收到资源更新的推送,此时您可以选择直接请求更新,以保持产品一直处于最新状态(推荐)。
DDS.getInstance().getAgent().subscribe("sys.resource.updated", new MessageObserver() {
    @Override
    public void onMessage(String message, String data) {
        try {
            DDS.getInstance().getUpdater().update(ddsUpdateListener);
        } catch (DDSNotInitCompleteException e) {
            e.printStackTrace();
        }
    }
});
SDK中内置一套资源更新时的通知的UI实现,您可以在DDSConfig中设置 DDSConfig.K_USE_UPDATE_NOTIFICATION 来开启或关闭。
2.4 权限说明
SDK需要的权限如下表,请在AndroidManifest.xml 文件中添加。
| 权限 | 用途 | 
|---|---|
| android.permission.INTERNET | 允许接入互联网,以便访问我们的云服务 | 
| android.permission.RECORD_AUDIO | 允许采集音频 | 
| android.permission.READ_PHONE_STATE | 允许读取必要的设备数据 | 
| android.permission.ACCESS_WIFI_STATE | 获取WIFI状态 | 
| android.permission.ACCESS_NETWORK_STATE | 获取网络状态 | 
| android.permission.WRITE_EXTERNAL_STORAGE | 写入外部存储数据,用于存储一些缓存文件 | 
| android.permission.READ_EXTERNAL_STORAGE | 读取外部存储数据 | 
2.5 代码混淆
如果您的应用使用了混淆, 请添加:
 
 proguard-rules.pro
-dontwarn com.aispeech.**
-keep public class com.aispeech.lasa{*;}
-keep public class com.aispeech.dui.dds.luaBug{ *; }
三. 功能列表
3.1 响应command
3.1.1 客户端动作的执行
详细的command编写说明,请参见客户端动作(command)编写说明

3.1.2 快捷唤醒中的命令响应

当您在DUI平台上定制了command之后,可以使用如下的方式在您的工程中做实现。
 类似于Android的广播接收器,您可以在需要的地方注册和注销CommandObserver,同一个CommandObserver可以处理多个commands。
command
// 注册
DDS.getInstance().getAgent().subscribe(new String[]{"open_window", "increase.volume"}, commandObserver);
  
// 注销
DDS.getInstance().getAgent().unSubscribe(commandObserver);
  
private CommandObserver commandObserver = new CommandObserver() {
    @Override
    public void onCall(final String command, final String data) {
        if (command.equals("open_window")){
            JSONObject jsonData = new JSONObject(data);
            String intentName = jsonData.optString("intentName");
            String w = jsonData.optString("w");
            // TODO 依据w的值,执行打开窗户操作
        }else if (command.equals("increase.volume")) {
            // TODO 处理调大音量的快捷唤醒指令
        }
    }
};
3.2 响应native api

当您在DUI平台上定制了native api之后,可以使用如下的方式在您的工程中做实现。
 类似于Android的广播接收器,您可以在需要的地方注册和注销NativeApiObserver,同一个NativeApiObserver可以处理多个native api。
command
// 注册
DDS.getInstance().getAgent().subscribe(new String[]{"query_battery"}, nativeApiObserver);
  
// 注销
DDS.getInstance().getAgent().unSubscribe(nativeApiObserver);
  
private NativeApiObserver nativeApiObserver = new NativeApiObserver() {
    @Override
    public void onQuery(final String nativeApi, final String data) {
        if (nativeApi.equals("query_battery")){
            JSONObject jsonData = new JSONObject(data);
            String intentName = jsonData.optString("intentName");
            // 执行查询电量操作
            String battery = DeviceUtil.getBattery();
            DDS.getInstance().getAgent().feedbackNativeApiResult(nativeApi, new TextWidget().setText(battery));
        }
    }
};
注:
 
• 每个onQuery方法执行时,需要调用feedbackNativeApiResult来向DUI平台返回执行结果,表示一个native api执行结束。
 
• native api的执行超时时间为10s。
更多详细使用请查看: https://www.duiopen.com/docs/skill_FAQ
3.3 响应内置消息
内置消息列表:
| message | data | 说明 | 
|---|---|---|
| sys.kernel.ready | 无 | SDK加载完成,所有功能就绪 | 
| sys.dialog.start | { reason:"wakeup.major",//唤醒词触发对话 } | 对话开始,及开始原因: 1.wakeup.major,唤醒词唤醒 2.wakeup.command,快捷命令唤醒 3.api.startDialog,调用startDialog接口 4.api.sendText,调用sendText接口(对话Idle时) 5.api.triggerIntent,调用triggerIntent接口(对话Idle时) 6.api.avatarClick,调用avatarClick接口(对话Idle时) 7.api.avatarPress,调用avatarPress接口(对话Idle时) | 
| sys.dialog.error | { errId:071304, errMsg:"asr null" recordId:"70dcef50b8b31a6c02dbac1acee31de7" } | 对话中发生的错误 | 
| sys.dialog.end | { reason:"normal",//对话正常结束 skillId:"100001246" } { reason:"error",//对话发生错误; errId:071304, errMsg:"asr null", skillId:"100001246" } { reason:"interrupt",//对话被打断。强制结束对话时出现。 skillId:"100001246" } | 对话结束,及结束原因: 1.normal,对话正常结束 2.error,对话发生错误退出 3.interrupt,对话被打断退出 | 
| sys.dialog.continue | 无 | 对话恢复 | 
| sys.resource.updated | 无 | 收到线上资源变更的推送 | 
| sys.wakeup.result | { "type": "major", "word": "你好小驰", "greeting":"主人你好" } | 语音唤醒 | 
| sys.vad.begin | 无 | VAD触发 | 
| sys.vad.end | 无 | VAD结束 | 
| sys.upload.result | { "result":false, "reqId":"xxxx", "errId":71801, "errMsg":"Network Invalid" } | 上传词库、设备信息的结果 | 
类似于Android的广播接收器,您可以在需要的地方注册和注销MessageObserver,同一个MessageObserver可以处理多个message。
您可以通过注册消息接收器来接收需要UI展示的数据,具体UI消息数据见:
 UI事件及数据定义
command
// 注册
DDS.getInstance().getAgent().subscribe(new String[]{"sys.dialog.start","sys.dialog.end","context.input.text"}, messageObserver);
  
// 注销
DDS.getInstance().getAgent().unSubscribe(messageObserver);
  
private MessageObserver messageObserver = new MessageObserver() {
    @Override
    public void onMessage(final String message, final String data) {
        if (message.equals("sys.dialog.start")){
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                     Toast.makeText(MainActivity.this, "对话开始了", Toast.LENGTH_LONG).show();
                }
            });
        }else if(message.equals("context.input.text")){
            final JSONObject dataJson = new JSONObject(data);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                     Toast.makeText(MainActivity.this, dataJson.optString("text"), Toast.LENGTH_LONG).show();
                }
            });
        }
    }
};
3.4 开启/终止对话
您可以在任何时刻主动开启/终止对话,通过以下接口实现。
 dialog
// 开启对话。如果当前已经在对话中,则重新开启新一轮对话。
DDS.getInstance().getAgent().startDialog();
// 关闭对话
DDS.getInstance().getAgent().stopDialog();
// 支持在开启对话时传入一个播报文本, 先播报文本,后开启对话
Agent.startDialog(JSONObject jsonObject)
// 支持在关闭对话时传入一个播报文本, 文本播报结束后自动结束对话
Agent.stopDialog(JSONObject jsonObject)
使用示例: 
JSONObject jsonObject = new JSONObject();
jsonObject.put("speakText", "播报文本");
DDS.getInstance().getAgent().startDialog(jsonObject);
// 多模态事件同步,该接口用于客户端给对话中控发送一个事件
DDS.getInstance().getAgent().updateDispatchEvent(JSONObject obj)
使用示例:
JSONObject obj = new JSONObject();
obj.put("endSkill", "true");
DDS.getInstance().getAgent().updateDispatchEvent(obj);3.5 按键事件
如果您有相关的软硬件按键,您需要关注以下接口,将用户的行为反馈给SDK。
avatar
// 点击唤醒/停止识别/打断播报 操作接口
DDS.getInstance().getAgent().avatarClick();
 
 
// 点击唤醒/停止识别/打断播报 操作接口 , 并附带一则欢迎语,当此次是唤醒时,播报这则欢迎语
DDS.getInstance().getAgent().avatarClick("有什么可以帮你");
  
// 按下按键接口(调用此接口需关闭VAD,VAD在创建产品时可配置)
DDS.getInstance().getAgent().avatarPress();
  
// 释放按键接口(调用此接口需关闭VAD,VAD在创建产品时可配置)
DDS.getInstance().getAgent().avatarRelease();
3.6 语音播报
参数说明:
 1)text 播报文本,支持SSML。
 2)priority 优先级
提供4个优先级播报。
 ①优先级0:保留,与DDS语音交互同级,仅限内部使用;
 ②优先级1:正常,默认选项,同级按序播放;
 ③优先级2:重要,可以插话<优先级1>,同级按序播放,播报完毕后继续播报刚才被插话的<优先级1>;
 ④优先级3:紧急,可以打断当前正在播放的<优先级1|优先级2>,同级按序播放,播报完毕后不再继续播报刚才被打断的<优先级1|优先级2>。
 3)ttsId 用于追踪该次播报的id,建议使用UUID。
 4)audioFocus 该次播报的音频焦点,默认值:
 ①优先级0:android.media.AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
 ②优先级非0:android.media.AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
tts
// 请求语音播报
 
DDS.getInstance().getAgent().getTTSEngine().speak("这是一段测试文本", 1, "100", AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
停止播报接口如下:
 1)ttsId与speak接口的ttsId一致,则停止或者移除该播报;
 2)ttsId为空, 停止所有播报;
 3)ttsId为"0",停止当前播报。
tts
// 停止播报
 
DDS.getInstance().getAgent().getTTSEngine().shutup("100");
3.7 内置H5
您如果使用和上传了h5资源,可以通过以下方法来获取h5资源包的index.html文件的路径用来在webview中加载。
 H5
// 获取资源包中h5的index.html文件的绝对路径
DDS.getInstance().getAgent().getValidH5Path();
3.8 外部录音机拾音
您如果有自己的录音机,可以通过以下方法将录音数据传给DDS。
external recorder
// 注意:需要将DDSConfig.K_RECORDER_MODE设置为"external",用来关闭DDS内置录音机,该接口才会生效
// 音频长度:无限制。内置录音机是3200(单麦)
// 调用间隔:无限制。内置录音机是100ms
// 调用时机:无限制。DDS会根据对话状态将接受的音频送入识别或者丢弃。
DDS.getInstance().getAgent().feedPcm(byte[] pcm);
3.9 外部TTS引擎
您如果使用第三方的TTS引擎,可以通过以下方法来将第三方TTS引擎注册到DDS中。
External TTS Engine
// 注意:需要将DDSConfig.K_TTS_MODE设置为"external",用来声明使用第三方TTS引擎,该接口才会生效。
 
 
// 注册
DDS.getInstance().getAgent().setTTSRequestListener(listener)
  
// 播报结束通知
DDS.getInstance().getAgent().notifyTTSEnd();
 
private TTSRequestListener listener = new TTSRequestListener() {
    @Override
    public void onStart(String type, String content) {
        Log.d(TAG, "tts start," + type + ":" + content);
        int code = mExternelTts.startSpeaking(content, mTtsListener);
 
        if (code != ErrorCode.SUCCESS) {
            Log.d(TAG, "语音合成失败,错误码: " + code);
        }
    }
 
    @Override
    public void onStop() {
        Log.d(TAG, "tts stop");
        mExternelTts.stopSpeaking();
    }
};
3.10 场景模式
SDK提供了一些场景(如TTS播报/拾音距离)的切换,您可以在需要的时候调用下面的接口。
DDSMode
//TTS场景切换
DDS.getInstance().getAgent().setDDSMode(DDSMode.TTS_SILENCE); //在静音模式下,所有TTS播报将会被静音。
DDS.getInstance().getAgent().setDDSMode(DDSMode.TTS_NORMAL); //默认值。
 
 
//拾音场景切换。仅在"电视助手"解决方案中生效。
DDS.getInstance().getAgent().setDDSMode(DDSMode.PICKUP_NEAR); //在近场模式下,将加载产品配置页中的近场配置
DDS.getInstance().getAgent().setDDSMode(DDSMode.PICKUP_FAR); //在远场模式下,将加载产品配置页中的远场配置
3.11 触发指定意图
如果您期望主动触发某个意图的对话,可以在需要的时候调用下面的接口。
参数说明:
1)skill 技能名称,必填。
 2)task 任务名称,必填。
 3)intent 意图名称,必填。
 4)slots 语义槽的key-value Json,可选。
triggerIntent
//跳过识别和语义,直接进入指定的意图对话。即:DDS主动向用户发起一轮对话。
DDS.getInstance().getAgent().triggerIntent("我是技能名称", "我是任务名称", "我是意图名称", new JSONObject().put("语义槽名称一", "语义槽取值一").put("语义槽名称二", "语义槽取值二").toString());
根据skillid触发意图:
SkillIntent skillIntent = new SkillIntent("我是技能id",
        "我是任务名称", "我是意图名称",
        new JSONObject().put("语义槽名称一", "语义槽取值一").put("语义槽名称二", "语义槽取值二").toString());
DDS.getInstance().getAgent().triggerIntent(skillIntent);
3.12 更新用户词库
如果您期望更新用户的词库,使其能在技能中使用,可以在需要的时候调用下面的接口。上传结果可以通过sys.upload.result消息来获取。
注意:更新的词库仅在该设备下有效,不会影响其他设备。
参数说明:
vocabIntent: 词库intent。包含词库名name,操作action,词条列表contents。
 注1:若词库名是sys.联系人,则会自动做分词处理。
 注2:若需要上传带同义词的词条,格式如下:"${词条取值}:${同义词1},${同义词2}"
返回值:请求ID,用于追踪sys.upload.result。
updateVocabs
//实时更新用户词库
/*
//增加词条
DDS.getInstance().getAgent().updateVocab("设备词库", new String[]{"空调", "电视:电视机", "电灯:电灯泡,灯泡"}, true);
DDS.getInstance().getAgent().updateVocab("sys.联系人", new String[]{"张三", "李四"}, true);
 
 
//删除词条
DDS.getInstance().getAgent().updateVocab("设备词库", new String[]{"空调", "电视:电视机,彩电"}, false);
 
 
//删除所有词条
DDS.getInstance().getAgent().updateVocab("设备词库", null, false);
*/
//向指定词库中添加词条
final String reqId = DDS.getInstance().getAgent().updateVocabs(
        new VocabIntent()
                .setName("应用列表")
                .setAction(VocabIntent.ACTION_INSERT)
                .setContents(Arrays.asList("淘宝", "支付宝:支护宝,付款码"))
);
 
//清空之前上传到该词库的所有词条,然后添加词条
DDS.getInstance().getAgent().updateVocabs(
        new VocabIntent()
                .setName("设备词库")
                .setAction(VocabIntent.ACTION_CLEAR_AND_INSERT)
                .setContents(Arrays.asList("空调", "电视:电视机"))
);
 
//删除该词库的词条
DDS.getInstance().getAgent().updateVocabs(
        new VocabIntent()
                .setName("歌手名")
                .setAction(VocabIntent.ACTION_REMOVE)
                .addContent("刘德华")
);
 
//清空之前上传到该词库的所有词条
DDS.getInstance().getAgent().updateVocabs(
        new VocabIntent()
                .setName("歌曲")
                .setAction(VocabIntent.ACTION_CLEAR_ALL)
);
 
//批量更新词库
DDS.getInstance().getAgent().updateVocabs(
        //向指定词库中添加词条
        new VocabIntent()
                .setName("sys.联系人")
                .setAction(VocabIntent.ACTION_INSERT)
                .addContent("董芳芳")
                .addContent("王强"),
        //清空之前上传到该词库的所有词条,然后添加词条
        new VocabIntent()
                .setName("设备词库")
                .setAction(VocabIntent.ACTION_CLEAR_AND_INSERT)
                .setContents(Arrays.asList("空调", "电视:电视机")),
        //删除该词库的词条
        new VocabIntent()
                .setName("歌手名")
                .setAction(VocabIntent.ACTION_REMOVE)
                .addContent("刘德华"),
        //清空之前上传到该词库的所有词条
        new VocabIntent()
                .setName("歌曲")
                .setAction(VocabIntent.ACTION_CLEAR_ALL)
);
 
 
//关注更新词库的结果
DDS.getInstance().getAgent().subscribe("sys.upload.result", new MessageObserver() {
    @Override
    public void onMessage(String message, String data) {
        Log.e(TAG, message + ":" + data);
        try {
            JSONObject obj = new JSONObject(data);
            if (reqId.equals(obj.optString("reqId", ""))) {
                Log.d(TAG, "updateVocabs result:" + obj.optBoolean("result", false));
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
});
3.13 开启/终止识别
如果您期望仅开启识别并获取识别结果,可以在需要的时候调用下面的接口。
ASREngine
//获取识别引擎
ASREngine asrEngine = DDS.getInstance().getAgent().getASREngine();
//开启识别
asrEngine.startListening(new ASREngine.Callback() {
    @Override
    public void beginningOfSpeech() {
        AILog.i(TAG, "检测到用户开始说话");
    }
 
    /**
    * @buffer  音频数据属性:单声道 16bit
    */
    @Override
    public void bufferReceived(byte[] buffer) {
        AILog.i(TAG, "用户说话的音频数据");
    }
 
    @Override
    public void endOfSpeech() {
        AILog.i(TAG, "检测到用户结束说话");
    }
 
    /**
    * @results. eof 为 0 代表识别过程中的结果, 为 1 代表识别结束的最终结果
    *    {"var":"今","sessionId":"0b48c0d086efc42d55bbf1068137655d","recordId":"6b3ccb1ee745d42fa6ddb74330b1c059","eof":0}
    *    {"var":"今天 天气","sessionId":"0b48c0d086efc42d55bbf1068137655d","recordId":"6b3ccb1ee745d42fa6ddb74330b1c059","eof":0}
    *    {"sessionId":"0b48c0d086efc42d55bbf1068137655d","pinyin":"jin tian tian qi","recordId":"6b3ccb1ee745d42fa6ddb74330b1c059","eof":1,"text":"今天 天气"}
    */
    @Override
    public void partialResults(String results) {
        AILog.i(TAG, "实时识别结果反馈");
    }
 
    /**
    * @results. {"sessionId":"0b48c0d086efc42d55bbf1068137655d","recordId":"6b3ccb1ee745d42fa6ddb74330b1c059","eof":1,"text":"今天天气","pinyin":"jin tian tian qi"}
    */
    @Override
    public void finalResults(String results) {
        AILog.i(TAG, "最终识别结果反馈");
    }
 
    @Override
    public void error(String error) {
        AILog.i(TAG, "识别过程中发生的错误");
    }
 
    @Override
    public void rmsChanged(float rmsdB) {
        AILog.i(TAG, "用户说话的音量分贝");
    }
});
 
//主动结束此次识别
asrEngine.stopListening();
  
//取消此次识别
asrEngine.cancel();
3.13.1 设置实时回传音量
// 设置实时回传音量大小, 默认为true
// 设置false之后, ASREngine.Callback.rmsChanged()不再回传音量变化值
DDS.getInstance().getAgent().getASREngine().enableVolume(boolean enable);
3.14 VAD相关设置
3.14.1设置VAD后端停顿时间
如果您期望修改VAD后端检测的时间,可以在需要的时候调用下面的接口。
参数说明
 millis 后端检测时间,单位毫秒,默认500毫秒。即若VAD在用户说话时停顿超过一定的时间,则认为用户已经说完,发出sys.vad.end消息,结束录音。
setVadPauseTime
//设置VAD后端停顿时间 DDS.getInstance().getAgent().getASREngine().setVadPauseTime(1000);//获取VAD后端停顿时间 DDS.getInstance().getAgent().getASREngine().getVadPauseTime();
3.14.2 设置VAD前端静音检测超时时间
如果您期望修改VAD前端静音检测超时时间,可以在需要的时候调用下面的接口。设置成功后,vad再次启动生效。
 参数说明:
 millis 前端静音检测超时时间,单位毫秒,默认8000毫秒。若VAD启动,一直未检测到用户说话,超过一定时间,发出sys.vad.timeout消息,结束录音。
setVadTimeout
//设置VAD前端静音检测超时时间
DDS.getInstance().getAgent().getASREngine().setVadTimeout(1000);
 
//获取VAD前端静音检测超时时间
DDS.getInstance().getAgent().getASREngine().getVadTimeout();
3.15 输入文本
如果您期望跳过识别直接输入文本进行对话,可以在需要的时候调用下面的接口。
 若当前没有在对话中,则以文本作为首轮说法,新发起一轮对话请求。
 若当前正在对话中,则跳过识别,直接发送文本。
 
参数说明
 text 输入的文本内容
 
sendText
//输入文本
DDS.getInstance().getAgent().sendText("帮我选择第一个");
3.16 TTS相关设置
3.16.1 TTS事件回调
如果您想在TTS播报的相关时间节点收到通知,如:开始播报,播报结束。可以使用如下的方式:
 
OnTTSListener
DDS.getInstance().getAgent().getTTSEngine().setListener(new TTSEngine.Callback() {
    /**
     * 开始合成时的回调
     * @param ttsId 当前TTS的id, 对话过程中的播报ttsid默认为0,通过speak接口调用的播报,ttsid由speak接口指定。
     */
    @Override
    public void beginning(String ttsId) {
        Log.d(TAG, "TTS开始播报");
    }
    /**
     * 合成的音频数据的回调,可能会返回多次,data长度为0表示音频结束
     * @param data 音频数据属性:单声道 16bit, pcm
     */
    @Override
    public void received(byte[] data) {
        Log.d(TAG, "收到音频,此方法会回调多次,直至data为0,音频结束");
    }
    /**
     * TTS播报完成的回调
     * @param status 播报结束的状态。
     *               正常播报结束为0
     *               播报中途被打断结束为1
     */
    @Override
    public void end(String ttsId, int status) {
        Log.d(TAG, "TTS播报结束");
    }
    /**
     * 合成过程中出现错误的回调
     * @param error 错误信息
     */
    @Override
    public void error(String error) {
        Log.d(TAG, "出现错误,"+error);
    }
});
3.16.2 TTS参数设置
如果您想通过SDK定制不同的合成音类型,可以在需要的时候调用下面的接口。
 
setTTS
* 设置TTS播报类型的接口
 * 调用此接口则云端配置的合成音类型失效,此后的合成音类型都将由此接口来托管
 * @param speaker 取值如:zhilingf, gdgm等,若取为null,则表示随机改为一个不同的类型
 */
DDS.getInstance().getAgent().getTTSEngine().setSpeaker("zhilingf");
 
 
/**
 * 设置TTS播报类型的接口
 * 调用此接口则云端配置的合成音类型失效,此后的合成音类型都将由此接口来托管
 * @param speaker 取值如:zhilingf, gdgm等
 * @param path 取值如:"sdcard/tts/zhilingf.bin",自定义合成间类型的全路径
 */
DDS.getInstance().getAgent().getTTSEngine().setSpeaker("zhilingf","sdcard/tts/zhilingf.bin");
 
 
/**
 * 设置TTS播报语速的接口
 * 调用此接口则云端配置的合成音语速失效,此后的合成音语速都将由此接口来托管
 *
 * @param speed 语速,取值0.5-2.0,0.5语速最快,2.0语速最慢,对应控制台上合成音倍率值
 */
DDS.getInstance().getAgent().getTTSEngine().setSpeed(1.0f);
 
 
/**
 * 设置TTS播报音量的接口
 * 调用此接口则云端配置的合成音音量失效,此后的合成音音量都将由此接口来托管
 *
 * @param volume 音量大小,取值1-100
 */
DDS.getInstance().getAgent().getTTSEngine().setVolume(50);
 
 
/**
 * 设置TTS引擎为本地或者云端
 *
 * @param mode 取值 TTSEngine.LOCAL(本地合成),TTSEngine.CLOUD(云端合成)
 */
DDS.getInstance().getAgent().getTTSEngine().setMode(TTSEngine.LOCAL);
 
 
/**
 * 设置TTS播报的通道
 * @param streamType AudioManager.STREAM_*的取值
 * @throws DDSNotInitCompleteException
 */
DDS.getInstance().getAgent().getTTSEngine().setStreamType(int streamType);
/**
 * 设置TTS播报的通道(安卓7.0版本以上支持,并且需要配置K_AUDIO_USAGE和K_CONTENT_TYPE)
 * @param usage 取值: AudioAttributes.USAGE_*
 * @param contentType 取值: AudioAttributes.CONTENT_TYPE_*
 * @throws DDSNotInitCompleteException
 */
DDS.getInstance().getAgent().getTTSEngine().setUsage(int usage, int contentType);
 
 
/**
 * 设置TTS播报自定义录音
 * @param customAudioList 自定义播报音频列表
 * @throws DDSNotInitCompleteException
 */
DDS.getInstance().getAgent().getTTSEngine().setCustomAudio(List<CustomAudioBean> customAudioList);
 
 
/**
 * 设备抢焦点,默认为抢焦点
 * @param enable true/false  true: 抢焦点  false: 不抢焦点
 */
DDS.getInstance().getAgent().getTTSEngine().enableFocus(boolean enable);
/**
 * 设置TTS人设
 * @param style 风格,humor:幽默;calm:沉稳;common:普通;简短:short;
 */
DDS.getInstance().getAgent().getTTSEngine().setStyle(String style);
 
 
/**
 * 清除TTS人设
 */
DDS.getInstance().getAgent().getTTSEngine().removeStyle();
/**
 * 设置TTS结束后延迟时间,单位ms
 * @param afterTime
 * @throws DDSNotInitCompleteException
 */
public void setPlayAfterTime(int afterTime);3.16.3 TTS参数获取
如果您想获取当前TTS配置的接口,可以调用如下接口:
getTTS
//返回String 当前使用的合成音类型,如:"zhilingf",获取失败返回null
DDS.getInstance().getAgent().getTTSEngine().getSpeaker();
 
//返回float 当前合成音语速,返回值0.5-2.0,0.5语速最快,2.0语速最慢,获取失败返回 0
DDS.getInstance().getAgent().getTTSEngine().getSpeed();
 
//返回int 当前合成音音量,返回值1-100,获取失败返回 0
DDS.getInstance().getAgent().getTTSEngine().getVolume();
 
//返回List<CustomAudioBean> 当前自定义播报音频的列表
DDS.getInstance().getAgent().getTTSEngine().getCustomAudio();
//获取当前TTS人设
DDS.getInstance().getAgent().getTTSEngine().getStyle();3.17 唤醒相关设置
唤醒词介绍:当前除了主唤醒,唤醒词的类型还包括了 副唤醒词、命令唤醒词(快捷唤醒词)、打断唤醒词、快速唤醒词。
副唤醒词:如果您期望为设备增加一个别名,可以通过设置该类型唤醒词来完成。
命令唤醒词(快捷唤醒词): 如果您期望在唤醒的时候执行一条指令,可以通过设置该类型唤醒词来完成。
打断唤醒词:如果您期望在唤醒的时候能同时打断语音播报,可以通过设置该类型唤醒词来完成。
快速唤醒词:您想通过代码来控制快速唤醒,QuickStart词为类似“导航去”、“我想听”等,此类唤醒词只在oneshot模式下生效,作用为在未唤醒状态下语音输入“导航去天安门”,可直接进入对话流程。
3.17.1 开关唤醒
默认SDK加载后不会启动语音唤醒,您可以通过以下接口对需对语音唤醒进行控制。
 wakeup
// 开启语音唤醒
DDS.getInstance().getAgent().getWakeupEngine().enableWakeup();
  
// 关闭语音唤醒
DDS.getInstance().getAgent().getWakeupEngine().disableWakeup();
  
// 获取主唤醒词列表
DDS.getInstance().getAgent().getWakeupEngine().getWakeupWords();
3.17.2 更新副唤醒词
如果您期望为设备增加一个副唤醒词,可以在需要的时候调用下面的接口。
参数说明:
1)word 副唤醒词,若设置null,则清空当前的副唤醒词。
 2)pinyin 副唤醒词的拼音,形如:ni hao xiao chi。
 3)threshold 副唤醒词的阈值,形如:0.120(取值范围:0-1)。若设置null,则自动估算。
 4)greetings 副唤醒词的欢迎语,若设置null,则与主唤醒词保持一致。
updateMinorWakeupWord
 
// 实时更新副唤醒词(1.1.2.1版本及以上支持)
WakeupWord minorWord = new WakeupWord()
        .setPinyin("ni hao xiao chi")
        .setWord("你好小迟")
        .setThreshold("0.15")
        .addGreeting("我在");
DDS.getInstance().getAgent().getWakeupEngine().updateMinorWakeupWord(minorWord);
  
//获取当前的副唤醒词
DDS.getInstance().getAgent().getWakeupEngine().getMinorWakeupWord();
3.17.3 更新命令唤醒词(快捷唤醒词)
如果您期望在唤醒的时候执行一条指令,可以在需要的时候调用下面的接口。命令唤醒词和DUI控制台所设置的快捷唤醒词是相同的功能,且互不影响,可同时存在,根据需求来选择设置方式。
 参数说明:
 1)actions 命令唤醒词指令,为string数组,不为null。
 2)words 命令唤醒词,为string数组,不为null。
 3)pinyins 命令唤醒词的拼音,形如:ni hao xiao chi,为string数组, 不为null。
 4)thresholds 命令唤醒词的阈值,形如:0.120(取值范围:0-1),为string数组,不为null。
 5)greetings 命令唤醒词的欢迎语,为string二维数组,不为null,每维对应一个唤醒词的欢迎语。
updateCommandWakeupWord
// 实时更新命令唤醒词-更新一条命令唤醒词(1.1.2.1版本及以上支持)
WakeupWord commandWord = new WakeupWord()
        .setPinyin("xia yi shou")
        .setWord("下一首")
        .setThreshold("0.18")
        .addGreeting("我在")
        .setAction("sys.next");
DDS.getInstance().getAgent().getWakeupEngine().updateCommandWakeupWord(commandWord);
 
 
// 实时更新命令唤醒词-更新多条命令唤醒词(1.1.2.1版本及以上支持)
WakeupWord commandWord = new WakeupWord()
        .setPinyin("xia yi shou")
        .setWord("下一首")
        .setThreshold("0.18")
        .addGreeting("我在")
        .setAction("sys.next");
WakeupWord commandWord1 = new WakeupWord()
        .setPinyin("shang yi shou")
        .setWord("上一首")
        .addGreeting("我在")
        .setThreshold("0.20")
        .setAction("sys.play");
List<WakeupWord> commandList = new ArrayList<>();
commandList.add(commandWord);
commandList.add(commandWord1);
DDS.getInstance().getAgent().getWakeupEngine().updateCommandWakeupWords(commandList);
 
  
//清空当前设置的命令唤醒词
DDS.getInstance().getAgent().getWakeupEngine().clearCommandWakeupWord();
3.17.4 更新打断唤醒词
如果您期望在唤醒的时候能同时打断语音播报,可以在需要的时候调用下面的接口。打断唤醒词暂不支持在DUI控制台设置。(说明:打断需要设备开启回声消除)
 参数说明:
 1)words 打断唤醒词,为string数组,不为null。
 2)pinyins 打断唤醒词的拼音,形如:ni hao xiao chi,为string数组,不为null。
 3)thresholds 打断唤醒词的阈值,形如:0.120(取值范围:0-1)为string数组,不为null。
updateShortcutWakeupWord
//实时更新打断唤醒词-更新一条打断唤醒词(1.1.2.1版本及以上支持)
WakeupWord fixWord = new WakeupWord()
        .setPinyin("da duan")
        .setWord("打断")
        .setThreshold("0.18");
DDS.getInstance().getAgent().getWakeupEngine().updateShortcutWakeupWord(fixWord);
 
 
//实时更新打断唤醒词-更新多条打断唤醒词(1.1.2.1版本及以上支持)
WakeupWord fixWord = new WakeupWord()
        .setPinyin("da duan")
        .setWord("打断")
        .setThreshold("0.18");
WakeupWord fixWord1 = new WakeupWord()
        .setPinyin("da duan ba")
        .setWord("打断吧")
        .setThreshold("0.16");
List<WakeupWord> fixList = new ArrayList<>();
fixList.add(fixWord);
fixList.add(fixWord1);
DDS.getInstance().getAgent().getWakeupEngine().updateShortcutWakeupWords(fixList);
  
//清空当前设置的打断唤醒词
DDS.getInstance().getAgent().getWakeupEngine().clearShortCutWakeupWord();
3.17.5 添加/删除指定的命令唤醒词(快捷唤醒词)
如果您期望添加或者移除一些命令唤醒词而保留之前的命令唤醒词(即控制台上的快捷唤醒词),可以调用下面的接口。
 add remove
// 实时添加命令唤醒词-添加一条命令唤醒词(1.1.2.1版本及以上支持)
WakeupWord commandWord = new WakeupWord()
        .setPinyin("xia yi shou")
        .setWord("下一首")
        .setThreshold("0.18")
        .addGreeting("我在")
        .setAction("sys.next");
DDS.getInstance().getAgent().getWakeupEngine().addCommandWakeupWord(commandWord);
 
// 实时添加命令唤醒词-添加多条命令唤醒词(1.1.2.1版本及以上支持)
WakeupWord commandWord = new WakeupWord()
        .setPinyin("xia yi shou")
        .setWord("下一首")
        .setThreshold("0.18")
        .addGreeting("我在")
        .setAction("sys.next");
WakeupWord commandWord1 = new WakeupWord()
        .setPinyin("shang yi shou")
        .setWord("上一首")
        .addGreeting("我在")
        .setThreshold("0.20")
        .setAction("sys.play");
List<WakeupWord> commandList = new ArrayList<>();
commandList.add(commandWord);
commandList.add(commandWord1);
DDS.getInstance().getAgent().getWakeupEngine().addCommandWakeupWords(commandList);
 
// 实时移除命令唤醒词-移除一条命令唤醒词(1.1.2.1版本及以上支持)
WakeupWord commandWord = new WakeupWord().setWord("下一首");
DDS.getInstance().getAgent().getWakeupEngine().removeCommandWakeupWord(commandWord);
 
 
// 实时移除命令唤醒词-移除多条命令唤醒词(1.1.2.1版本及以上支持)
WakeupWord commandWord = new WakeupWord().setWord("下一首");
WakeupWord commandWord1 = new WakeupWord().setWord("上一首");
List<WakeupWord> commandList = new ArrayList<>();
commandList.add(commandWord);
commandList.add(commandWord1);
DDS.getInstance().getAgent().getWakeupEngine().removeCommandWakeupWords(commandList);
3.17.6 添加/删除指定的打断唤醒词
如果您期望添加或者移除一些打断唤醒词而保留之前的打断唤醒词,可以在需要的时候调用下面的接口。
add remove
//实时添加打断唤醒词-添加一条打断唤醒词(1.1.2.1版本及以上支持)
WakeupWord fixWord = new WakeupWord()
        .setPinyin("da duan")
        .setWord("打断")
        .setThreshold("0.18");
DDS.getInstance().getAgent().getWakeupEngine().addShortcutWakeupWord(fixWord);
 
 
//实时添加打断唤醒词-添加多条打断唤醒词(1.1.2.1版本及以上支持)
WakeupWord fixWord = new WakeupWord()
        .setPinyin("da duan")
        .setWord("打断")
        .setThreshold("0.18");
WakeupWord fixWord1 = new WakeupWord()
        .setPinyin("da duan ba")
        .setWord("打断吧")
        .setThreshold("0.16");
List<WakeupWord> fixList = new ArrayList<>();
fixList.add(fixWord);
fixList.add(fixWord1);
DDS.getInstance().getAgent().getWakeupEngine().addShortcutWakeupWords(fixList);
  
//实时移除打断唤醒词-移除一条打断唤醒词(1.1.2.1版本及以上支持)
WakeupWord fixWord = new WakeupWord().setWord("打断");
DDS.getInstance().getAgent().getWakeupEngine().removeShortcutWakeupWord(fixWord);
 
 
//实时移除打断唤醒词-移除多条打断唤醒词(1.1.2.1版本及以上支持)
WakeupWord fixWord = new WakeupWord().setWord("打断");
WakeupWord fixWord1 = new WakeupWord().setWord("打断吧");
List<WakeupWord> fixList = new ArrayList<>();
fixList.add(fixWord);
fixList.add(fixWord1);
DDS.getInstance().getAgent().getWakeupEngine().removeShortcutWakeupWords(fixList);
3.17.7 添加/删除指定的主唤醒词
如果您想通过代码来控制主唤醒词,可以调用下面的接口。
 注意:通过此接口添加的主唤醒词会屏蔽控制台添加的主唤醒词。
主唤醒词
//实时添加主唤醒词-添加一条主唤醒词(1.1.2.1版本及以上支持)//更新多条主唤醒词的接口,覆盖原有的主唤醒词
WakeupWord mainWord = new WakeupWord() .setPinyin("ni hao xiao chi") .setWord("你好小迟") .addGreeting("我在") .setThreshold("0.15"); DDS.getInstance().getAgent().getWakeupEngine().addMainWakeupWord(mainWord); //实时添加主唤醒词-添加多条主唤醒词(1.1.2.1版本及以上支持)
WakeupWord mainWord = new WakeupWord() .setPinyin("ni hao xiao chi") .setWord("你好小迟") .addGreeting("我在") .setThreshold("0.15"); WakeupWord mainWord2 = new WakeupWord() .setPinyin("ni hao xiao le") .setWord("你好小乐") .addGreeting("我在") .setThreshold("0.15"); List<WakeupWord> mainWordList = new ArrayList<>(); mainWordList.add(mainWord); mainWordList.add(mainWord2); DDS.getInstance().getAgent().getWakeupEngine().addMainWakeupWords(mainWordList); //实时移除主唤醒词-移除一条主唤醒词(1.1.2.1版本及以上支持)
WakeupWord mainWord = new WakeupWord().setWord("你好小迟"); DDS.getInstance().getAgent().getWakeupEngine().removeMainWakeupWord(mainWord); //实时移除主唤醒词-移除多条主唤醒词(1.1.2.1版本及以上支持)
WakeupWord mainWord = new WakeupWord().setWord("你好小迟"); WakeupWord mainWord2 = new WakeupWord().setWord("你好小乐"); List<WakeupWord> mainWordList = new ArrayList<>(); mainWordList.add(mainWord); mainWordList.add(mainWord2); DDS.getInstance().getAgent().getWakeupEngine().removeMainWakeupWords(mainWordList);
WakeupWord mainWord = new WakeupWord() .setPinyin("ni hao xiao le") .setWord("你好小乐") .setThreshold("0.15") .addGreeting("我在");
WakeupWord mainWord2 = new WakeupWord() .setPinyin("ni hao xiao chi") .setWord("你好小迟") .setThreshold("0.15") .addGreeting("我在");
List<WakeupWord> mainWordList = new ArrayList<>();
mainWordList.add(mainWord);
mainWordList.add(mainWord2);
DDS.getInstance().getAgent().getWakeupEngine().updateMainWakeupWords(mainWordList);
3.17.8 添加/删除指定的快速唤醒词
如果您想通过代码来控制快速唤醒,可以调用下面的接口。
QuickStart词为类似“导航去”、“我想听”等,此类唤醒词只在oneshot模式下生效,作用为在未唤醒状态下语音输入“导航去天安门”,可直接进入对话流程。
quickStart
//添加多条QuickStart词 WakeupWord quickStartWord = new WakeupWord() .setPinyin("dao hang qu") .setWord("导航去") .setThreshold("0.15"); List<WakeupWord> quickStartWordList = new ArrayList<>(); quickStartWordList.add(quickStartWord); DDS.getInstance().getAgent().getWakeupEngine().addQuickStartWords(quickStartWordList); //实时移除一条QuickStart词 WakeupWord quickStartWord = new WakeupWord().setWord("导航去"); DDS.getInstance().getAgent().getWakeupEngine().removeQuickStartWord(quickStartWord); //实时移除多条QuickStart词 WakeupWord quickStartWord = new WakeupWord().setWord("导航去"); List<WakeupWord> quickStartWordList = new ArrayList<>(); quickStartWordList.add(quickStartWord); DDS.getInstance().getAgent().getWakeupEngine().removeQuickStartWords(quickStartWordList); //更新多条QuickStart词的接口,覆盖原有的QuickStart词 WakeupWord quickStartWord = new WakeupWord() .setPinyin("dao hang qu") .setWord("导航去") .setThreshold("0.15"); List<WakeupWord> quickStartWordList = new ArrayList<>(); quickStartWordList.add(quickStartWord); DDS.getInstance().getAgent().getWakeupEngine().updateQuickStartWords(quickStartWordList); //清空QuickStart词 DDS.getInstance().getAgent().getWakeupEngine().clearQuickStartWords();
3.17.9 oneshot开关
如果您想动态更改唤醒模式,可以在需要的时候调用下面的接口。
oneshot
//开启oneshot DDS.getInstance().getAgent().getWakeupEngine().enableOneShot(); //关闭oneshot DDS.getInstance().getAgent().getWakeupEngine().disableOneShot();
3.17.10 设置环麦增强角度
// 如果您想动态指定环麦增强角度,可以在需要的时候调用下面的接口。
DDS.getInstance().getAgent().getWakeupEngine().setWakeupDoa(int doa);
3.17.11 设置车载双麦模式
// 如果您想动态指定车载双麦的驾驶模式,可以在需要的时候调用下面的接口。
// 0:全模式, 1:主驾模式
DDS.getInstance().getAgent().getWakeupEngine().setWakeupMode(int mode);
3.17.12 获取当前唤醒内核的版本号
如果您想获取当前唤醒内核的版本号,可以在需要的时候调用下面的接口。
DDS.getInstance().getAgent().getWakeupEngine().getWakeupVersion();3.17.13 设置是否允许识别过程中响应唤醒
如果您想设置是否允许识别过程中响应唤醒,可以在需要的时候调用下面的接口。
//enable: true. 允许识别过程中响应唤醒, false. 不允许识别过程中响应唤醒
DDS.getInstance().getAgent().getWakeupEngine().enableWakeupWhenAsr(boolean enable);3.17.14 设置自定义欢迎语回调
如果您想设置自定义欢迎语,可以在需要的时候调用下面的接口, 该方法是阻塞方法,不建议在该方法内部做耗时操作。
DDS.getInstance().getAgent().getWakeupEngine().setWakeupCallback(WakeupCallback wakeupCallback);
DDS.getInstance().getAgent().getWakeupEngine().setWakeupCallback(new WakeupCallback() {
    /**
     *
     * @param wakeupResult 唤醒状态
     *                     <p>
     *                     wakeupResult.optString("word");// 唤醒词
     *                     <p>
     *                     wakeupResult.optString("type");// 唤醒状态: major: 正常唤醒  command: 命令唤醒   interrupt: 打断唤醒
     *                     <p>
     *                     wakeupResult.optString("gender");// 性别: male / female
     *                     <p>
     *                     wakeupResult.optString("action");// 命令唤醒的动作
     *                     <p>
     * @return
     */
     @Override
     public JSONObject onWakeup(JSONObject wakeupResult) {
         JSONObject result = new JSONObject();
         try {
             result.put("greeting", "你好");
         } catch (JSONException e) {
             e.printStackTrace();
         }
         return result;
});3.17.15 获取主唤醒词列表
获取主唤醒词列表,默认返回WakeupEngine所设置的主唤醒词,如果没有设置过则返回产品配置的主唤醒词。
DDS.getInstance().getAgent().getWakeupEngine().getMainWakeupWords();3.17.16 设置Beamforming监听器
设置Beamforming监听器, 实时回调Beamforming音频
DDS.getInstance().getAgent().getWakeupEngine().setBfListener(BfListener listener);
3.17.17 设置唤醒模块的模式/低功耗模式
设置唤醒模块的模式(信号处理模块不变,环麦中暂不支持)
// 设置唤醒模块的模式(信号处理不变,环麦中暂不支持)
DDS.getInstance().getAgent().getWakeupEngine().setWakeupSwitch(boolean mode);
// 开启低功耗模式后, 唤醒功能不可用, cpu会降低(此方法已被废弃)
DDS.getInstance().getAgent().getWakeupEngine().setLpSwitch(boolean lpSwitch);3.17.18 就近唤醒
如果你有使用就近唤醒的需求, 可以参照下面的配置与设置(目前支持线性双麦/线性四麦的就近唤醒, 1.2.12.1-1.2.15.1的版本暂不支持就近唤醒)
1. 设置major参数为true (从1.2.8.1版本开始, 不再需要此配置)
config.addConfig("MAJOR", "true");
2. 设置K_USE_NEAR_WAKEUP为true, 表示使用就近唤醒
config.addConfig(DDSConfig.K_USE_NEAR_WAKEUP, "true");
3. 在设置唤醒词的时候设置major字段
WakeupWord minorWord = new WakeupWord()
        .setPinyin("ni hao xiao chi")
        .setWord("你好小驰")
        .setThreshold("0.25")
        .setMajor("1")(从1.2.8.1版本开始, 不再需要此配置)
        .addGreeting("小驰回来了");
DDS.getInstance().getAgent().getWakeupEngine().addMainWakeupWord(minorWord);3.18 数据上传接口
开发者调用此接口来上传一些设备的信息,这些信息可以在本地使用,也可以在对话中获取,作为对话决策的一部分。
 数据点
/**
 * 更新设备状态,产品级的配置。比如:定位信息,设备硬件状态等
 * 更新结果可以通过sys.upload.result消息来获取
 *
 * @param  intent 请求的ContextIntent对象,包括key和value
 *                如:ContextIntent intent = new ContextIntent("status","{\"platform\":\"Android\"}");
 *                   updateProductContext(intent);
 *                技能里通过$context.system.settings.status.platform$即可获取到"Android"
 * @return        请求的ID,用于追踪sys.upload.result
 * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
 */
DDS.getInstance().getAgent().updateProductContext(ContextIntent intent);
 
 
/**
 * 更新技能配置,需要调用ContextIntent.setSkillId设置技能ID
 * 更新结果可以通过sys.upload.result消息来获取
 *
 * @param  intent   请求的ContextIntent对象,包括key、value、skillId。
 *                  如:ContextIntent intent = new ContextIntent("status","{\"platform\":\"Android\"}");
 *                     intent.setSkillId("xxxxxxxxxxxxxxxxx");
 *                     updateSkillContext(intent);
 *                  该技能里通过$context.skill.settings.status.platform$即可获取到"Android",其他技能则无法使用。
 * @return          请求的ID,用于追踪sys.upload.result
 * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
 */
DDS.getInstance().getAgent().updateSkillContext(ContextIntent intent);
 
 
/**
 * 获取产品的配置信息
 *
 * @param inputKey 配置项名称
 * @return 配置项值
 * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
 */
DDS.getInstance().getAgent().getProductContext(String inputKey);
 
/**
 * 获取技能的配置信息
 *
 * @param skillId  技能ID
 * @param inputKey 配置项名称
 * @return 配置项值
 * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
 */
 
DDS.getInstance().getAgent().getSkillContext(String skillId, String inputKey);
/**
 * 更新热词识别接口(请求级别)
 * 每次请求都会带上热词词库, 例如: [{"type": "vocab", "name": "sys.联系人", "data":["章大樵"]}]
 * 本接口为覆盖式接口,以最新设置为准,如需要清除请求空参数即可
 * 
 * @param phraseHints 需要更新的热词识别列表
 * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
 */
 
DDS.getInstance().getAgent().updatePhraseHints(PhraseHintsIntent... phraseHints);3.19 获取性别/年龄信息
在初始化DDS SDK的时候加入如下配置:
config.addConfig(DDSConfig.K_USE_GENDER, "true");
config.addConfig(DDSConfig.K_USE_AGE, "true"); 然后订阅message:sys.dialog.start
 内容为:{"gender":"male","age":"youth","reason":"wakeup.major"}
gender就是性别字段,age就是年龄字段,性别年龄信息只有在主唤醒词唤醒后,才会发出。
3.20 动态更新云端识别模型
/**
 * 更新云端识别的模型名字,
 * 在调用完该接口后,下一次对话开始时生效,并一直用该模型,除非客户端再调用该接口设置为其他的模型
 *
 * @param asrModel 云端识别的模型名字,有aihome, airobot等,
 *               默认为dui控制台配置的模型资源,
 *               如果填null,则表示清除之前本地配置的模型名,之后会使用dui控制台配置的模型资源
 * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
 */
DDS.getInstance().getAgent().getASREngine().updateAsrModel("aihome");
 
 
/**
 * 获取当前使用的云端识别的模型
 *
 * @return asrModel 当前使用的云端识别的模型, 如果失败会返回null,或者抛出DDSNotInitCompleteException
 * @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
 */
DDS.getInstance().getAgent().getASREngine().getAsrModel();3.21 快捷指令
订阅 sys.dm.inspire 消息,用于接收快捷指令。
DDS.getInstance().getAgent().subscribe(new String[]{..., "sys.dm.inspire", ...}, new MessageObserver() {
    @Override
    public void onMessage(String message, String data) {
       if("sys.dm.inspire".equals(message)) {
            try {
                JSONObject obj = new JSONObject(data);
                JSONArray inspire = obj.getJSONArray("inspire");
                ...
            } catch (JSONException e) {
                e.printStackTrace();
            } catch (DDSNotInitCompleteException e) {
                e.printStackTrace();
            }
        }
    }
});inspire 即为快捷指令的集合数组,通过解析 inspire 来处理指令。inspire 数据结构如下:
inspire:[
    {
        speak:{
            "type":"text",
            "text":"123"
        },
        widget:{
            "type":"text",
            ...
        }
    },
    {
        speak:{
            "type":"text",
            "text":"抱歉由于设备离线,操作失败,请再试一次"
        },
        widget:{
            "type":"list",
            ...
        }
    },
    ...
]上述结构中,speak 并不是必须的字段, widget 是必须的。
widget即为需要需要展示出来的控件样式,其中 type 字段代表控件样式的类型,有 text/list/web/image/media...
关于 widget 不同控件样式的不同数据结构,可参考: https://www.duiopen.com/docs/ct_UI 。举例:list 对应这 context.widget.list,以此类推
3.22 全双工模式
3.22.1 模式切换
// 设置dds模式
DDS.getInstance().getAgent().setDuplexMode(Agent.DuplexMode.HALF_DUPLEX);// 半双工,一问一答模式
DDS.getInstance().getAgent().setDuplexMode(Agent.DuplexMode.FULL_DUPLEX);// 全双工模式
  
注意: 在切换全双工时如需要唤醒还请调用: DDS.getInstance().getAgent().getWakeupEngine().enableWakeup();
 
// 获取dds模式
DDS.getInstance().getAgent().getDuplexMode();3.22.2 全双工不支持接口与功能
1. 由于全双工模式的特性不再需要vad来做音频的切割, 所以设置vad前端与后端停顿时间无效 @4.5 识别配置项
2. 由于全双工模式为全程识别状态, 所以开启识别时startListening不可用 @3.13 开启/终止识别
3. 由于全双工模式为全程识别状态, 在模拟半双工下的打断唤醒由识别代替,主唤醒词正常开启下一轮对话
4. 由于全双工模式下暂时没有快捷指令的使用场景, 所以快捷指令在全双工模式下不可用 @3.21 快捷指令
5. 基于全双工模式下性能优化的考虑, 目前在全双工模式下默认禁用vad功能, 如有oneshot需求请添加配置K_USE_VAD_IN_FULLDUPLEX打开vad
3.22.3 全双工下跳过Vad超时检测
// 在全双工模式下, 如果你想跳过Vad的检测直接进入识别状态则可以调用下面的接口
DDS.getInstance().getAgent().getASREngine().killVadTimeoutInFullDuplex();
3.23 对话结果支持内容修改
此接口支持修改对话中的语音播报,修改文本展示等功能
// 此接口由于有死锁的风险, 从1.2.8.1开始废弃, 代替此接口的为setDMTaskCallback
DDS.getInstance().getAgent().setDMCallback(new DMCallback() {
    @Override
    public JSONObject onDMResult(JSONObject dmResult) {
        // 这里可以对dmResult做一些修改
        return dmResult;
    }
});
// 从1.2.8.1版本开始支持
DDS.getInstance().getAgent().setDMTaskCallback(new DMTaskCallback() {
    @Override
    public JSONObject onDMTaskResult(JSONObject dmTaskResult, Type type) {
        if (type == DMTaskCallback.Type.DM_OUTPUT) {// 处理dm的消息
            // 显示
            String display = dmTaskResult.optString("display");
            // 播报
            String nlg = dmTaskResult.optString("nlg");
            Log.d(TAG, "display = " + display);
            Log.d(TAG, "nlg = " + nlg);
            try {
                dmTaskResult.put("display", "修改之后的显示");
                dmTaskResult.put("nlg", "修改之后的播报");
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } else if (type == DMTaskCallback.Type.CDM_ERROR) {// // 处理对话异常的消息
            // 播报
            String nlg = dmTaskResult.optString("nlg");
            Log.d(TAG, "nlg = " + nlg);
            try {
                dmTaskResult.put("nlg", "修改之后的播报");
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return dmTaskResult;
    }
});
3.24 声纹
3.24.1 声纹接口设置
// 注册声纹监听器
VprintEngine.getInstance().setVprintListener(new VprintListener() {
        @Override
        public void onState(String state) {
            Log.e(TAG, "onState = " + state);
        }
        @Override
        public void onResults(String result) {
            Log.e(TAG, "onResults = " + result);
        }
        @Override
        public void onError(String error) {
            Log.e(TAG, "onError = " + error);
        }
});
// 注册声纹
VprintIntent intent = new VprintIntent.Builder()
        .setAction(VprintIntent.Action.REGISTER)
        .setTrainNum(3)
        .setOutChannelNum(2)
        .setSnrThresh(8.67f)
        .setUserId("userId")
        .setVprintWord("ni hao xiao chi")
        .create();
DDS.getInstance().getAgent().getVprintEngine().start(intent);
// 更新声纹
VprintIntent intent = new VprintIntent.Builder()
        .setAction(VprintIntent.Action.UPDATE)
        .setTrainNum(3)
        .setOutChannelNum(2)
        .setSnrThresh(8.67f)
        .setUserId("userId")
        .setVprintWord("ni hao xiao chi")
        .create();
DDS.getInstance().getAgent().getVprintEngine().start(intent);
// 追加声纹
VprintIntent intent = new VprintIntent.Builder()
        .setAction(VprintIntent.Action.APPEND)
        .setTrainNum(3)
        .setOutChannelNum(2)
        .setSnrThresh(8.67f)
        .setUserId("userId")
        .setVprintWord("ni hao xiao chi")
        .create();
DDS.getInstance().getAgent().getVprintEngine().start(intent);
// 删除一条声纹
VprintIntent intent = new VprintIntent.Builder()
        .setAction(VprintIntent.Action.UNREGISTER)
        .setTrainNum(3)
        .setOutChannelNum(2)
        .setUserId("userId")
        .setVprintWord("ni hao xiao chi")
        .create();
DDS.getInstance().getAgent().getVprintEngine().start(intent);
// 删除所有声纹
VprintIntent intent = new VprintIntent.Builder()
        .setAction(VprintIntent.Action.UNREGISTER_ALL)
        .create();
DDS.getInstance().getAgent().getVprintEngine().start(intent);
// 使用声纹
VprintIntent intent = new VprintIntent.Builder()
        .setAction(VprintIntent.Action.TEST)
        .setOutChannelNum(2)
        .create();
 
DDS.getInstance().getAgent().getVprintEngine().start(intent);
// 获取声纹模型
String result = VprintEngine.getInstance().getMode();
// 停止使用声纹
VprintEngine.getInstance().stop();四、高级配置项
4.1 资源更新配置项
| 参数名 | 取值 | 说明 | 默认值 | 
|---|---|---|---|
| DSConfig.K_CUSTOM_ZIP | 文件名字符串 | 预置在指定目录下的DUI产品配置资源包名 (参考提前预置资源包 ) | N/A | 
| DDSConfig.K_DUICORE_ZIP | 文件名字符串 | 预置在指定目录下的DUI内核资源包名(参考提前预置资源包) | N/A | 
| DDSConfig.K_USE_UPDATE_DUICORE | true/false | 设置为false可以关闭dui内核的热更新功能,可以配合内置dui内核资源使用 | true | 
| DDSConfig.K_USE_UPDATE_NOTIFICATION | true/false | 是否使用内置的资源更新通知栏 | true | 
4.2 录音配置项
| 参数名 | 取值 | 说明 | 默认值 | 
|---|---|---|---|
| DDSConfig.K_RECORDER_MODE | external/internal | 录音机模式: external(使用外置录音机,需主动调用拾音接口) internal(使用内置录音机AudioRecord,DDS自动录音) | internal | 
| DDSConfig.K_AEC_MODE | external | AEC模式:external(DDS会认为宿主设备已经完成了AEC回声消除,选择默认模组也可以支持唤醒打断) | N/A | 
| DDSConfig.K_AUDIO_SOURCE | AudioSource的取值 | 内置录音机数据源类型 | AudioSource.DEFAULT | 
| DDSConfig.K_IS_REVERSE_AUDIO_CHANNEL | true/false | 是否反转内置录音机通道 | false | 
| DDSConfig.K_AUDIO_BUFFER_SIZE | 数值型字符串 | 内置录音机读buffer的大小 | 通道数 * 16/8 * 16000 * 100/1000 B | 
4.3 TTS配置项
| 参数名 | 取值 | 说明 | 默认值 | 备注 | 
|---|---|---|---|---|
| DDSConfig.K_TTS_MODE | external/internal | TTS模式: external(使用外置TTS引擎,需主动注册TTS请求监听器) internal(使用内置DUI TTS引擎) | internal | |
| DDSConfig.K_STREAM_TYPE | AudioManager.STREAM_*的取值 | 内置播放器的STREAM类型 | AudioManager.STREAM_ALARM | K_AUDIO_USAGE与K_CONTENT_TYPE为7.0以后新版本参数, 同时设置时替换原先的K_STREAM_TYPE参数 | 
| DDSConfig.K_AUDIO_USAGE | AudioAttributes.USAGE_*的取值 | 内置播放器的USAGE类型,兼容7.0以后的新版本参数 | 无 | |
| DDSConfig.K_CONTENT_TYPE | AudioAttributes.CONTENT_TYPE_*的取值 | 内置播放器的contenttype类型,兼容7.0以后的新版本参数 | 无 | |
| DDSConfig.K_CUSTOM_TIPS | json字符串 | 指定对话错误码的TTS播报。若未指定,则使用产品配置。 { "71304":"这是识别结果为空的自定义播报", "71305":"这是语义结果为空的自定义播报", "71308":"这是进入闲聊技能的自定义播报", "713**":"*****" } | 产品配置 | |
| DDSConfig.K_CUSTOM_AUDIO | JSONArray字符串 | 用预置音频来代替指定的TTS播报。 [ { "name":"我在", "type":"wav", "path":"/sdcard/x.pcm" }, { "name":"好的,再见", "type":"mp3", "path":"/sdcard/y.mp3" } ] | 无 | |
| DDSConfig.K_TTS_OPTIMIZATION | true/false | 是否TTS开启内存优化 | false | 
4.4 唤醒配置项
| 参数名 | 取值 | 说明 | 默认值 | 
|---|---|---|---|
| DDSConfig.K_WAKEUP_ROUTER | partner/dialog | 唤醒路由: partner(唤醒后不会主动进入对话,开发者可以通过注册sys.wakeup.result来接收唤醒消息) dialog(唤醒后主动进入对话) | dialog | 
| DDSConfig.K_WAKEUP_BIN | 唤醒资源的磁盘绝对路径,比如/sdcard/wakeup.bin | 商务定制版唤醒资源的路径。如果开发者对唤醒率有更高的要求,请联系商务申请定制唤醒资源。 | 内置通用唤醒资源 | 
| DDSConfig.K_ONESHOT_MIDTIME DDSConfig.K_ONESHOT_ENDTIME | 数值型字符串,毫秒 | OneShot配置: 5.若MIDTIME=-1&ENDTIME=-1, 唤醒后进入识别; 若第一次识别结果为空, 则再次进入识别 | 500,2000 | 
| DDSConfig.K_NR_ENABLE | true/false | 是否开启降噪功能 | false | 
| DDSConfig.K_NR_BIN | 降噪库的磁盘绝对路径,比如/sdcard/nr.bin | 商务定制版降噪资源的路径 | 内置能用降噪资源 | 
| DDSConfig.K_HIGH_VOLUME_CHECK | true/false | 是否开启大音量检测 如果配置为true,则调用:WakeupWord.setThreshold(String threshold, String threshold2) 设置唤醒词阈值 | false | 
| DDSConfig.K_USE_AGE | true/false | 是否开启使用年龄识别 | false | 
| DDSConfig.K_USE_GENDER | true/false | 是否开启使用性别识别 | false | 
| DDSConfig. K_USE_NEAR_WAKEUP | true/false | 是否开启就近唤醒 | false | 
| DDSConfig. K_WAKEUP_DISABLE_CUSTOM_GREETING | true/false | 是否禁止自定义欢迎语功能 | false | 
4.5 识别配置项
| 参数名 | 取值 | 说明 | 默认值 | 
|---|---|---|---|
| DDSConfig.K_ASR_ROUTER | partner/dialog | 识别路由: partner(将识别结果传递给partner,不会主动进入对话) dialog(将识别结果传递给dui,会主动进入对话) | dialog | 
| DDSConfig.K_ASR_ENABLE_PUNCTUATION | true/false | 识别结果是否带标点符号 | false | 
| DDSConfig.K_ASR_ENABLE_TONE | true/false | 识别结果的拼音是否带音调 | false | 
| DDSConfig.K_VAD_TIMEOUT | 数值型字符串,毫秒 | VAD静音检测超时时间,默认8000毫秒 | 8000 | 
| DDSConfig.K_VAD_BIN | VAD资源的磁盘绝对路径,比如/sdcard/vad.bin | 商务定制版VAD资源的路径。如果开发者对VAD有更高的要求,请联系商务申请定制VAD资源。 | 内置通用VAD资源 | 
| DDSConfig.K_ASR_TIPS | true/false | 识别完成是否播报提示音 | false | 
| DDSConfig.K_ASR_ENABLE_NUMBER_CONVERT | true/false | 中文数据转阿拉伯数字 | false | 
| DDSConfig.K_ASR_NOT_DROP_WAKEUP | true/false | 识别时不要过滤唤醒词 | false | 
注: DDSConfig.K_ASR_ENABLE_PUNCTUATION 开关同时控制识别和语义,开启后,语义解析结果也会带标点符号,且不建议在oneshot、中英文连用、轻音的情况下使用。
4.6 麦克风阵列配置项
| 参数名 | 取值 | 说明 | 默认值 | 
|---|---|---|---|
| DDSConfig.K_MIC_TYPE | 0、1、2、3、4、5、6、7、8 | 设置硬件采集模组的类型 7:新车载双麦(2路音频)-- 替换原有车载双麦方案 8:线性六麦(6路音频) | 线上的采集模组配置 | 
| DDSConfig.K_MIC_ARRAY_AEC_CFG | 麦克风阵列aec资源的磁盘绝对路径,比如/data/aec.bin | 麦克风阵列aec资源的磁盘绝对路径 1. 麦克风阵列的AEC默认做在ROM里。若需SDK做AEC,请配置此项。 2.需要开发者确保在这个路径下这个资源存在。 3.需要开发者在外部实现录音机(参考K_RECORDER_MODE)。 | 无 | 
| DDSConfig.K_MIC_ARRAY_BEAMFORMING_CFG | 麦克风阵列beamforming资源的磁盘绝对路径,比如/data/beamforming.bin | 麦克风阵列beamforming资源的磁盘绝对路径 1.需要开发者确保在这个路径下这个资源存在。 2.默认的双麦/四麦/六麦内置资源为35mm/35mm/72mm。 | 内置资源 | 
| DDSConfig.K_WAKEUP_BIN | 麦克风阵列wakeup配置资源的磁盘绝对路径,比如/data/wakeup_cfg.bin | 麦克风阵列wakeup配置资源的磁盘绝对路径 1.需要开发者确保在这个路径下这个资源存在 | 内置资源 | 
4.7 调试配置项
| 参数名 | 取值 | 说明 | 默认值 | 
|---|---|---|---|
| DDSConfig.K_ASR_DEBUG | true|false | 将会自动保存ASR音频 | 无 | 
| DDSConfig.K_CACHE_PATH | 调试信息保存路径,比如/sdcard/... | 调试信息保存路径 | AppCacheDir(/sdcard/Android/data/com.xxx.xxx/cache/) | 
| DDSConfig.K_TTS_DEBUG | true|false | 将会自动保存TTS音频 | 无 | 
| DDSConfig.K_VAD_DEBUG | true|false | 将会自动保存VAD音频 | 无 | 
| DDSConfig.K_WAKEUP_DEBUG | true|false | 将会自动保存唤醒音频 | 无 | 
4.8 性别识别配置项
| 参数名 | 取值 | 说明 | 默认值 | 
|---|---|---|---|
| DDSConfig.K_USE_GENDER | true/false | 是否使用性别识别 | false | 
4.9 全双工配置项
| 参数名 | 取值 | 说明 | 默认值 | 
|---|---|---|---|
| DDSConfig.K_DUPLEX_MODE | HALF_DUPLEX|FULL_DUPLEX | 配置当前的使用模式 HALF_DUPLEX:对话模式 FULL_DUPLEX:全双工模式 | HALF_DUPLEX | 
| DDSConfig.K_USE_VAD_IN_FULLDUPLEX | true/false | 全双工中是否使用vad功能 | false | 
4.10 声纹配置项
| 参数名 | 取值 | 说明 | 默认值 | 
| DDSConfig.K_VPRINT_ENABLE | true/false | 是否开启声纹功能 | false | 
| DDSConfig.K_VPRINT_BIN | 声纹资源的磁盘绝对路径,比如/data/vprint.bin | 声纹资源的磁盘绝对路径 | 内置资源 | 
| DDSConfig.K_USE_VPRINT_IN_WAKEUP | true/false | 是否开启声纹功能并在唤醒中使用声纹判断 | false | 
五. 错误码描述
| error id | 错误描述 | 原因及解决办法 | 
|---|---|---|
| 1 | 解压dds.bin失败 | 系统IO错误 | 
| 2 | 内核执行出错 | 请检查配置是否正确,或者联系DUI客服 | 
| 3 | 系统启动超时 | 请检查配置是否正确,或者联系DUI客服 | 
| 4 | 存储空间不足 | 请检查/data/目录剩余大小是否充足 | 
| 070302 | 解码失败 | 联系DUI客服 | 
| 070303 | 未发现新的版本 | 略 | 
| 070304 | 请先升级您的客户端(SDK) | 因为产品选择的dui内核和sdk不匹配,需要升级sdk | 
| 070305 | 网络异常, 无法连接至服务器 | 请检查网络是否正常或者配置是否正确 | 
| 070306 | 解码失败 | 联系DUI客服 | 
| 070307 | 补丁安装失败 | 存储空间不够 | 
| 070308 | 备份压缩文件不存在 | 用户手动删掉了app私有空间的文件 | 
| 070309 | 提取压缩文件失败 | 存储空间不够 | 
| 070310 | 未设置产品ID | 需要设置产品id | 
| 070311 | 无效客户端版本 | 请检查配置是否正确 | 
| 070312 | 无效用户ID | 需要设置用户id | 
| 070313 | 无效设备ID | 设备id不正确 | 
| 070314 | 资源地址无效 | 请检查配置是否正确 | 
| 070315 | 无效的产品分支 | 需要设置产品分支 | 
| 070316 | 无法找到资源 | 服务端资源生成有问题,请尝试重新发布一下,或者请提供产品id反馈给DUI客服,去后台查询根本原因 | 
| 070317 | 资源校验失败 | 下载资源过程中资源被纂改 | 
| 070319 | 当前产品中内核资源版本过低,请前往DUI控制台对应的产品中,选择最新的内核资源版本并重新发布产品 | 当前产品中内核资源版本过低,请前往DUI控制台对应的产品中,选择最新的内核资源版本并重新发布产品。 | 
| 070320 | 存储空间不足 | 系统存储空间不足,请在错误的详细信息中查看需要的存储空间和现有的存储空间 | 
| 070601 | 设备注册过程中无法连接到授权服务器 | 请检查网络是否畅通,或者productId与api key是否匹配 | 
| 070602 | 设备注册过程无法颁发有效的profile文件 | 请检查产品ID或与客服联系 | 
| 070603 | API Key无效 | 请到产品授权配置页面查看api key信息是否正确,请确认签名证书是否匹配,包名是否匹配 | 
| 070604 | 无效的产品ID | 无效的产品ID,请确认是否未设置产品ID | 
| 070606 | profile文件被禁用 | 请重新进行注册或者与客服联系 | 
| 070607 | profile文件过期 | 请重新进行注册或者与客服联系 | 
| 070609 | 设备注册无法保存有效的profile文件 | 检查文件系统是否异常或者重新进行设备注册 | 
| 070612 | dns resolve failed: no answers(DNS失败) | 请检查网络是否畅通 | 
| 070613 | dns resolve failed: exceed retry count(DNS失败) | 请检查网络是否畅通 | 
| 070614 | dns resolve failed: network is unreachable(DNS失败) | 请检查网络是否畅通 | 
| 070615 | dns resolve timeout(DNS超时) | 请检查网络是否畅通 | 
| 070616 | connect ip failed: reasons for uncertainty(建立连接失败) | 请检查网络是否畅通 | 
| 070617 | connect ip failed: network is unreachable(建立连接失败) | 请检查网络是否畅通 | 
| 070618 | connect ip timeout(建立连接超时) | 请检查网络是否畅通 | 
| 070619 | websocket handshake failed: reasons for uncertainty(websocket握手失败) | 请检查网络是否畅通 | 
| 070620 | recv timeout(接收超时) | 请检查网络是否畅通 | 
| 070621 | send timeout(发送超时) | 请检查网络是否畅通 | 
| 070622 | orderly shutdown(发完数据正常关闭) | 请检查网络是否畅通 | 
| 071301 | TTS合成超时 | 请检查网络是否正常 | 
| 071302 | 对话超时 | 请检查网络是否正常 | 
| 071303 | 对话连接断开 | 请检查网络是否正常 | 
| 071304 | 识别结果为空 | 未检测到用户说法 | 
| 071305 | 语义结果为空 | 用户的说法没有命中产品中的非闲聊技能 | 
| 071306 | WebAPI错误 | 调用WebAPI时发生错误 | 
| 071307 | NativeAPI错误 | 调用NativeAPI时发生错误 | 
| 071308 | 进入闲聊技能 | 用户的首轮说法没有命中产品中的非闲聊技能 | 
| 071309 | 异常重试达到最大次数 | 达到了产品错误处理的最大重试次数 | 
| 071310 | 命中退出词 | 用户说了产品的退出词 | 
| 071311 | NativeAPI未注册 | 请检测是否注册并实现NativeAPI | 
| 071312 | 本地识别结果置信度低 | 网络离线时本地识别结果置信度较低 | 
| 071313 | 自定义技能响应超时 | 联系技能开发者 | 
| 071314 | 自定义技能内部错误 | 联系技能开发者 | 
| 071315 | 自定义技能返回为空 | 联系技能开发者 | 
| 071316 | 当前场景下不支持这么说 | 该技能关闭了智能调度 | 
| 071317 | 进入兜底技能 | 用户说法进入了产品中的兜底技能 | 
| 071318 | 进入知识型技能 | 用户说法进入了产品中的知识型技能,包括新闲聊、新百科 | 
| 071319 | 未授权 | 请调用doAuth | 
| 071320 | 在使用oauth授权方式的情况下,access token过期或者不合法 | 请使用oauth sdk刷新access token,然后用dds sdk的接口传入access token | 
| 071321 | 自定义技能speaklist播报超时 | 请检查音频链接是否正常 | 
| 071322 | 鉴权失败的情况下请求对话 | 请检查授权错误信息 | 
| 071300 | 对话服务内部错误 | 联系DUI客服 | 
| 072101 | ASREngine VAD超时 | 超过8s未检测到人声 | 
| 072102 | ASREngine 识别为空 | 未检测到用户说法 | 
| 072103 | ASREngine 识别服务超时 | 请检查网络是否正常 | 
| 072104 | ASREngine 识别过程发生错误 | 联系DUI客服 | 
| 072201 | 唤醒词个数超过限制 | 请清除之前的唤醒词后重试 | 
六. 常见问题
6.1 SDK的软硬件配置要求
1)需要Android 4.0及其以上的系统;
 2)/data分区剩余空间至少200MB。
6.2 授权失败
关于070603授权错误的问题,请做以下检查:
 1)平台上生成的apikey和本地使用的apikey是否一致;
 2)平台上release debug的sha256值是否和本地的对应;
 3)gradle文件配置的signingConfigs,只针对generate生成的apk;
 4)如果是点run运行的程序,debug的sha256要填的.android目录下的debug.keystore(最常见)。
6.3 客户端没收到Command/NativeAPI回调
常见原因如下,可以自上而下确认:
 1)技能修改后,未发布;
 2)技能发布后,产品没有选择该技能的最新版本;
 3)产品未发布;
 4)客户端配置的K_ALIAS_KEY和产品发布的分支不一致;
 5)客户端没有注册对应的Command/NativeAPI;
 6)客户端注册Command/NativeAPI的逻辑没走到;
 7)客户端注册的Command/NativeAPI没填对,把?后面的参数也填进去了;
 8)客户端注册Command/NativeAPI后,又重新初始化了DDS(release+init)。
6.4 智能家居refreshToken 断网2年后导致SDK授权失败且无法恢复的问题
1)通过订阅token_refresh.fail消息,如果token刷新失败,SDK会抛出这个消息,应用收到该消息后,重新走以下流程:requestAuthCode() -- setAuthCode()
2)setAuthCode授权成功后,将智能家居绑定流程再重新走一遍;确保DCA绑定成功。