Android SDK集成

一. 集成准备

1.1 获取产品ID

集成SDK之前,您首先需要到DUI控制台创建产品,获取如下的产品ID。
Minion

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下载页

 

Minion

将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), 
  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);
    }
});

在收到 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)编写说明

Minion

 

3.1.2 快捷唤醒中的命令响应

Minion

当您在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

Minion

当您在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。

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().endSkillInDialog()

// 多模态事件同步,该接口用于客户端给对话中控发送一个事件(可替代endSkillInDialog接口)
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);

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会降低(单麦/环麦/线麦支持, 从1.2.8.1版本开始支持)
DDS.getInstance().getAgent().getWakeupEngine().setLpSwitch(boolean lpSwitch);

3.17.18 就近唤醒

如果你有使用就近唤醒的需求, 可以参照下面的配置与设置(目前支持线性双麦/线性四麦的就近唤醒)

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配置:
1.若MIDTIME=0&ENDTIME=0,唤醒后进入识别;若VAD检测超时,则直接退出对话
2.若MIDTIME=0&ENDTIME!=0,唤醒后进入识别;若ENDTIME超时,则直接退出对话
3.若MIDTIME!=0&ENDTIME=0,唤醒后进入识别;若MIDTIME超时,则播放欢迎语,继续识别
4.若MIDTIME!=0&ENDTIME!=0,唤醒后进入识别;若MIDTIME超时,则播放欢迎语,继续识别;若ENDTIME超时,则直接退出对话

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

设置硬件采集模组的类型
0:原始单麦(1路音频)
1:单麦回消(1路音频+1路参考音)
2:线性四麦(4路音频)
3:环形六麦(6路音频)
4:车载双麦(2路音频)
5:家居双麦(2路音频)
6:环形四麦(4路音频)

7:新车载双麦(2路音频)-- 替换原有车载双麦方案
默认使用DUI控制台上产品的对应配置项。若客户端通过SDK配置此项后,则以客户端配置为准。

线上的采集模组配置
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)。