DCA SDK集成(Android)

1.前言

DCA SDK是运行在手机端的配套app的sdk。

DCA 相关功能全都依赖于设备端(比如音箱等)的DDS SDK配置oauth信息(userid,authcode等),才能使得DCA的功能生效。

本文档下面提到的账号登录部分的授权是DCA SDK的授权。

DDS SDK的oauth信息配置使用请看本文档最后部分。

下面的接口除了内容音频资源不需要登录就可以使用,其他接口都需要登录后使用。

2.集成准备

先在DUI开放平台注册一个账号成为开发者,并登录APP管理后台申请apiKey、apiSecret、manufacture、clientid等一些集成SDK需要的参数;具体流程参考DCA SDK创建引导

apiKey:集成SDK时需用到的鉴权参数

apiSecret:集成SDK时需用到的鉴权参数

manufacture:厂商标识的明文,由开发者自己取名(英文名,不超过20位);当开发者使用自有账号时,贵司账号与思必驰账号互通时用到

manufacture_secret:厂商标识对应的密文,当开发者使用自有账号时,贵司账号与思必驰账号互通时用到

设备oauth授权的clientId:用于DDS SDK的账号授权

3.集成sdk

3.1 导入dca aar

将lib-dca-x.x.x-release.aar导入到现有的工程中,放入到libs目录下,并在build.gradle中添加配置

repositories {
    flatDir {
        dirs 'libs'//this way we can find the .aar file in libs folder
 }
}

在dependencies中加入:

//gson
implementation 'com.google.code.gson:gson:2.8.2'
//okhttp
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation "com.squareup.okhttp3:logging-interceptor:3.10.0"
//Retrofit
implementation "com.squareup.retrofit2:retrofit:2.5.0"
implementation "com.squareup.retrofit2:converter-gson:2.5.0"

implementation(name: 'lib-dca-3.xxx-release', ext: 'aar')
implementation files('libs/alipaySdk-20180601.jar')//如果用的到技能商店功能,这里要引入支付宝sdk

//蓝牙配网用到,可选择性使用
implementation 'no.nordicsemi.android.support.v18:scanner:1.1.0'

//mqtt,可选择性使用
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'

 

3.2 权限

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK"/> 

 

3.3 代码混淆

 如果您的应用混淆了代码,请加入:

#dca
-dontwarn com.aispeech.**
-keep class com.aispeech.dca.** { *;}
-keep class com.aispeech.dui.account.** { *;}

#gson
-dontwarn com.google.gson.**
-keep class com.google.gson.** { *; }


#okhttp
-dontwarn okhttp3.**
-keep class okhttp3.** { *; }


# Retrofit
-keep class retrofit2.** { *; }
-dontwarn retrofit2.**
-keepattributes Signature
-keepattributes Exceptions
-dontwarn okio.**
-dontwarn javax.annotation.**

#alipay
-dontwarn com.alipay.**
-keep class com.alipay.** {*;}
-keep class org.json.alipay.** { *; }
-keep class com.alipay.tscenter.** { *; }
-keep class com.ta.utdid2.** { *;}
-keep class com.ut.device.** { *;}

 

3.4 初始化

在自定义Application的onCreate方法中:

DcaSdk.initialize(this, apiKey, apiSecret);  //初始化dca sdk,新版本初始化,新客户需要申请apiKey,apiSecret
MqttManager.getInstance().initMqtt(this);  //如果用到mqtt

4.账号登录

开发者在集成账号登录有如下三种方式可选:1.使用思必驰账号系统  2.客户账号和思必驰账号互通

4.1 使用思必驰账号系统

//登录之发送验证码到手机
private void getLoginMobileVerifyCode(String mobile) {
    UserVerifyBean userVerifyBean = new UserVerifyBean();
    userVerifyBean.setUserName(mobile); //设置用户名(手机号)
    userVerifyBean.setType(UserVerifyBean.TYPE_LOGIN); //登录验证码type为1
    DcaSdk.getAccountApiClient().getVerifyCode(userVerifyBean, new Callback2() {
        @Override
        public void onSuccess() {
            Log.i(TAG, "getLoginMobileVerifyCode success");
        }
 
        @Override
        public void onFailure(int errCode, String errMsg) {
            Toast.makeText(AccountApiActivity.this, errMsg + "" , Toast.LENGTH_LONG).show();
        }
    });
}
 
//手机验证码登录,如果以前没注册过,后台会自动注册
private void loginWithMobileVerifyCode(final String mobile, String verifyCode) {
    UserLoginBean userLoginBean = new UserLoginBean();
    userLoginBean.setUserName(mobile); //设置用户名(手机号)
    userLoginBean.setSmsCode(verifyCode); //设置验证码
    DcaSdk.getAccountApiClient().login(userLoginBean, new Callback<User>() {
        @Override
        public void onSuccess(User user) {
            mUser = user;
            Log.i(TAG, "loginWithMobileVerifyCode success");
        }
 
        @Override
        public void onFailure(int errCode, String errMsg) {
            Toast.makeText(AccountApiActivity.this, errMsg + "" , Toast.LENGTH_LONG).show();
        }
    });
}
 
 
//账号密码登录
private void loginWithPassword(final String username, String password) {
    UserLoginBean userLoginBean = new UserLoginBean();
    userLoginBean.setUserName(username); //设置用户名(账号)
    userLoginBean.setPassword(password); //设置密码
    DcaSdk.getAccountApiClient().login(userLoginBean, new Callback<User>() {
        @Override
        public void onSuccess(User user) {
            mUser = user;
            Log.i(TAG, "loginWithPassword success");
        }
 
        @Override
        public void onFailure(int errCode, String errMsg) {
            Toast.makeText(AccountApiActivity.this, errMsg + "" , Toast.LENGTH_LONG).show();
        }
    });
}
//忘记密码之发送验证码到手机
private void getForgetPasswordVerifyCode(String mobile) {
    UserVerifyBean userVerifyBean = new UserVerifyBean();
    userVerifyBean.setUserName(mobile);//设置用户名(手机号)
    userVerifyBean.setType(UserVerifyBean.TYPE_FORGET_PASSWORD); //忘记密码的验证码type为2
    DcaSdk.getAccountApiClient().getVerifyCode(userVerifyBean, new Callback2() {
        @Override
        public void onSuccess() {
            Log.i(TAG, "getForgetPasswordVerifyCode success");
        }
 
        @Override
        public void onFailure(int errCode, String errMsg) {
            Toast.makeText(AccountApiActivity.this, errMsg + "" , Toast.LENGTH_LONG).show();
        }
    });
}
 
 
//忘记密码之发送验证码到邮箱
private void getForgetPasswordEmailVerifyCode(String email) {
    UserVerifyBean userVerifyBean = new UserVerifyBean();
    userVerifyBean.setUserName(email);//设置用户名(邮箱号)
    userVerifyBean.setType(UserVerifyBean.TYPE_FORGET_PASSWORD); //忘记密码的验证码type为2
    DcaSdk.getAccountApiClient().getVerifyCode(userVerifyBean, new Callback2() {
        @Override
        public void onSuccess() {
            Log.i(TAG, "getForgetPasswordEmailVerifyCode success");
        }
 
        @Override
        public void onFailure(int errCode, String errMsg) {
            Toast.makeText(AccountApiActivity.this, errMsg + "" , Toast.LENGTH_LONG).show();
        }
    });
}
 
//忘记密码之校验验证码接口
private void validateCode(final String username, final String code) {
    UserForgetPassword userForgetPassword = new UserForgetPassword();
    userForgetPassword.setUserName(username);//设置用户名(手机号或邮箱)
    userForgetPassword.setCode(code);//设置验证码
    DcaSdk.getAccountApiClient().validateCode(userForgetPassword, new Callback<User>() {
        @Override
        public void onSuccess(User user) {
            mUser = user;
            Log.i(TAG, "validateCode success");
        }
 
        @Override
        public void onFailure(int errCode, String errMsg) {
            Toast.makeText(AccountApiActivity.this, errMsg + "" , Toast.LENGTH_LONG).show();
        }
    });
}
 
//设置密码接口 , user对象可以从登录接口或者 忘记密码之校验验证码接口 回调中获得
private void setPassWord(final User user, String password) {
    UserSetPassword userSetPassword = new UserSetPassword();
    userSetPassword.setPassword(password);  //设置密码
    userSetPassword.setToken(user.getTOKEN().getValue()); //设置token
    userSetPassword.setUserId(user.getUserId() + ""); //设置用户id
    DcaSdk.getAccountApiClient().setPassword(userSetPassword, new Callback2() {
        @Override
        public void onSuccess() {
            Log.i(TAG, "setPassWord success ");
        }
 
        @Override
        public void onFailure(int errCode, String errMsg) {
            Toast.makeText(AccountApiActivity.this, errMsg + "" , Toast.LENGTH_LONG).show();
        }
    });
}

 

4.2 客户使用自有账号系统

在实际项目中,客户有自己的账号系统或指定其他的账号系统,需要和思必驰账号打通,打通后即可使用自有账号系统,具体流程如下:
1)用户在客户的配套APP注册登录,登录成功后客户从自身云端获取该用户的UID和AccessToken;
2)客户调用SDK的账号接口,传入上述的UID和AccessToken;
3)思必驰云端接收客户的UID+AccessToken,并与客户云端互通校验UID和Token(客户需要提供一个校验接口,方便思必驰服务端和客户服务端互通);
4)客户返回给思必驰校验结果后,思必驰基于合法的客户的UID生成思必驰C端账号;
5)思必驰云端将思必驰C端账号的userID传给DCA SDK,实现SDK登录授权

6)accesstoken的有效期是2小时,refresh token的有效期为2年,生成有效参数后,配套app会将参数传输给dds sdk(具体可查看dds sdk文档),后续维护均在dds sdk(设备侧)中,需要保持设备在2年内通电通网,不然可能会造成授权失效,需重新绑定设备,才可再次进行授权。

 

 

4.2.1  客户账号和思必驰账号对接接口

该接口是dca的登录接口,只需要在登录或者切换账号后调用,app重启后如果还是处于登录状态(见4.5)并且没有切换过用户(切换用户可先退出登录,见4.6)就不需要再次调用

AccountManager类中:

public void linkAccount(String thirdPlatformUid, String thirdPlatformToken, String manufactureSecret,
                        final AccountListener listener)

thirdPlatformUid 贵司帐号系统用户ID

thirdPlatformToken 用来访问贵司uid校验服务的token

manufactureSecret 由贵司的厂商名生成的密文,由思必驰颁发,当贵司需要接入时,请在APP管理后台,找到对应项目,详情页面中有对应字段

 

同时,这里需要贵司服务端实现如下接口,并把该接口的地址提供给思必驰,思必驰会在后台管理系统配置该地址,当贵司客户端在调用dca sdk的上面的

linkAccount(String thirdPlatformUid, String thirdPlatformToken, String manufactureSecret, final AccountListener listener)时,

思必驰的服务端会调用贵司的下面即将实现的服务接口来检验sdk传上来的贵司的uid的合法性

客户需要实现的服务端接口:

该接口用于检验贵司的uid(用户id)是否合法

要求贵司提供的服务端api接口格式如下给到思必驰项目经理:

POST /%external-platform-path%

http body部分为:{"uid":"xxx","token":"xxx"}

 

成功: 200  {"code":"SUCCESS","message":"success!"}

失败: 200  {"code":"ACCOUNT_NOT_EXIST","message":"account is not exist!"}

 

参数说明:

uid:   贵司帐号系统用户ID

token:  用来访问贵司uid校验服务的token

 

code 说明

SUCCESS:                 uid校验通过

ACCOUNT_NOT_EXIST:       账号不存在

INVALIDATE_PARAMS:       参数错误

TOKEN_INVALIDATE:        token无效(包括失效)

 

4.3 设置需要登录的listener

当需要登录(比如内部token失效等)时,会回调该接口

//设置需要登录时的listener
        DcaSdk.setNeedOnLoginListener(new NeedLoginListener() {
            @Override
            public void onNeedLogin() {
                
            }
        });

 

4.4 获取用户id

AccountManager.getInstance().getUserId()

 

4.5 判断当前登录状态

 

AccountManager.getInstance().isLogined()

 

4.6 退出登录

 

AccountManager.getInstance().clearToken();

 

5.用户相关

入口为

DcaSdk.getUserManager()

5.1 获取用户信息

如果查找用户信息异步回调的userInfo为null则需要先调用首次上传用户信息接口

/**
 * 查询用户信息
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call queryUserInfo(Callback<UserInfo> callback);

 

5.2 首次上传用户信息

/**
 * 首次上传用户信息
 * @param nickname nickname 昵称
 * @param phone phone 手机号
 * @param sex sex MALE-男,FAMALE-女,UNKNOWN-未知
 * @param head 头像链接地址
 * @param callback 异步回调
 * @return
 */
Call register(String nickname, String phone, String sex, String head, Callback<UserInfo> callback);

 

5.3 更换头像

/**
 * 更新头像地址
 * @param headUrl 头像地址
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call updateHeadUrl(String headUrl, Callback2 callback);

 

5.4 修改昵称

/**
 * 修改昵称
 * @param nickName 昵称
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call updateNickName(String nickName, Callback2 callback);

 

5.5 修改性别

/**
 * 更新性别
 * @param sex MALE-男,FAMALE-女
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call updateSex(String sex, Callback2 callback);

 

5.6 获取宝宝资料

/**
 * 返回宝宝资料信息,不存在回调nul
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call queryBabyInfo(Callback<AddBabyInfoRequest> callback);

 

5.7 保存宝宝资料

/**
 * 填写宝宝信息
 * @param request AddBabyInfoRequest
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call saveBabyInfo(AddBabyInfoRequest request, Callback2 callback);

 

5.8 收藏

5.8.1 获取收藏列表

/**

 * 获取收藏列表
 * @param page 第几页, 从1开始
 * @param count 每页多少条
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call getCollectionByPage(int page, int count, Callback<CollectionResponse> callback);

 

5.8.2 添加收藏

/**
 * 添加收藏列表
 * @param musicList musicList
 * @param callback 异步回调
 * @return retrofit2.Call
 */ 
Call addCollection(List<MusicBean> musicList, Callback2 callback);

 

5.8.3 删除收藏

/**
 * 删除收藏列表
 * @param musicList musicList
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call deleteCollection(List<MusicBean> musicList, Callback2 callback);

 

5.9 通讯录

5.9.1 获取通讯录

/**
 * 获取通讯录
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call queryContacts(final Callback<ContactsResult> callback);

 

5.9.2 添加通讯录

/**
 * 添加好友到通讯录
 * @param contactAddRequest ContactAddRequest
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call addContacts(ContactAddRequest contactAddRequest, final Callback2 callback);

 

5.9.3 获取用户个人二维码

/**
 * 获取用户个人二维码
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call getUserQRCode(Callback<String> callback);

 

5.9.4 扫码添加到通讯录,无需同意

/**
 * 扫一扫调用的添加到通讯录,无需同意
 * @param scanContactAddRequest scanContactAddRequest
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call scanAddContact(ScanContactAddRequest scanContactAddRequest, final Callback2 callback);

 

5.9.5 获取好友申请列表

/**
 * 获取好友申请列表
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call queryFriendsApply(final Callback<List<ContactsBean>> callback);

 

5.9.6 同意好友申请

/**
 * 同意好友申请
 * @param acceptInviteRequest acceptInviteRequest
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call acceptFriendsApply(AcceptInviteRequest acceptInviteRequest, final Callback2 callback);

 

5.9.7 编辑通讯录好友信息

/**
 * 编辑通讯录好友信息
 * @param contactEditRequest contactEditRequest
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call editContacts(ContactEditRequest contactEditRequest, final Callback2 callback);

 

5.9.8 删除通讯录好友

/**
 * 删除通讯录好友
 * @param contactDelRequest contactDelRequest
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call delContacts(ContactDelRequest contactDelRequest, final Callback2 callback);

6.APP信息相关

入口为DcaSdk.getAppManager()

 

6.1 广告

/**
 * 获取广告信息
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call getAdvertisement(Callback<Advertisement> callback);

 

6.2 轮播图

/**
 * 轮播图
 * @param type 暂时只传"index"
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call getCarouselData(String type, Callback<List<Carousel>> callback);

 

6.3 用户反馈

/**
 * 提交用户反馈
 * @param userFeedbackRequest
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call postFeedback(UserFeedbackRequest userFeedbackRequest, Callback2 callback);

 

6.4 加载协议等相关信息

/**
 * 加载协议等相关信息
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call loadAboutUsMsgData(Callback<AboutUsBean> callback);

 

6.5 app是否需要更新

/**
 * app是否需要更新
 * @param version
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call checkAppVersion(String version, Callback<UpgradeDataBean> callback);

 

6.6 上传图片并生成地址

/**
 * 上传图片并生成地址
 * @param file
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call uploadFile(File file, Callback<ImageUploadBean> callback);

7.设备配网

 

7.1 配网绑定流程图

7.1.1 客户自有设备配网绑定流程

7.1.2 思必驰整机配网绑定流程

 

蓝牙配网授权绑定流程(具体代码请参考demo):

 

 

声波配网授权绑定流程(具体代码请参考demo)

 

wifi ap配网授权绑定流程:

 /**
     * 连接该热点
     * @param SSID 设备热点名字
     * @param connectListener 回调
     */
    public void connectToAp(String SSID, ApConnectListener connectListener)

//连接该热点
SoftApLinkManager.getInstance(mContext).connectToAp(ssid, new SoftApLinkManager.ApConnectListener() {
                            @Override
                            public void onTargetApConnected() {
                                
                            }
                        });

/**
     * 为远程设备配网
     *
     * @param linkManager  用于配网的链路(SoftApLinkManager/BleLink)
     * @param device       配网设备(AP:SSID / BLE:BluetoothDevice)
     * @param ssid         要为设备配置的网络SSID
     * @param psk          要为设备配置的网络密码
     * @param data         需要发送给设备端的数据
     * @param listener     配网监听
     */
    public void configNetworkForRemoteDevice(LinkManager linkManager,
                                             Object device,
                                             String ssid,
                                             String psk,
                                             String data,
                                             NetworkConfigListener listener)


NetworkConfigClient mClient = new NetworkConfigClient();
mClient.configNetworkForRemoteDevice(linkManager
                            , targetSsid
                            //TODO
                            , wifiName.getText().toString().trim()
                            //TODO
                            , wifiPsw.getText().toString().trim()
                            , uid
                            , new NetworkConfigClient.NetworkConfigListener() {
                                @Override
                                public void onNetworkConfigResult(int resultCode, String json_from_server) {
                                    if(resultCode == NetworkConfigClient.CONFIGURATION_SUCCESS) {
                                        //发送数据成功
                                    }
                                }
                            });

 

扫码绑定流程图:

 

7.2 获取authcode给音箱端(dds sdk)使用

流程:首先由手机端生成codeverifier,authcode和userid(思必驰用户id),然后在配网的过程中把codeverifier,authcode和userid传给音箱端,

音箱端把这些值设置给dds sdk

 

下面是生成authcode的代码

 

String codeVerifier = OAuthManager.getInstance().genCodeVerifier();
String codeChallenge = OAuthManager.getInstance().genCodeChallenge(codeVerifier);
String userId = AccountManager.getInstance().getUserId() + "";
OAuthManager.getInstance().setOAuthListener(new MyOAuthCodeListener());
OAuthManager.getInstance().requestAuthCode(codeChallenge, "http://dui.callback", clientId);


private class  MyOAuthCodeListener implements OAuthCodeListener {

    @Override
    public void onError(String s) {

    }

    @Override
    public void onSuccess(final String authcode) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                mAuthCodeTv.setText("authcode : " + authcode);
            }
        });

    }
}

 

8.设备相关接口

入口为DcaSdk.getDeviceManager()

 

8.1 绑定设备

当您成功为设备配网后,需要调用本接口来为用户绑定设备。

注:

1. 一台设备只能被一个用户绑定;一个用户可以绑定多台设备。

2. 若已绑定设备的信息需要更新,如deviceAlias、deviceInfo,也可以调用本接口

/**
 * 用户绑定智能设备
 * 如果该设备被其他用户绑定过,这次绑定会先把其他用户和该设备解绑,再和这次的用户绑定
 * @param deviceBean 需要绑定的设备的设备信息
 * @param callback 回调接口
 * @return okhttp3.Call
 */
okhttp3.Call bindDevice(DeviceBean deviceBean, Callback2 callback);

 

8.2 解除绑定

/**
 * 用户解除绑定智能设备
 * @param callback 回调接口
 * @return okhttp3.Call
 */
okhttp3.Call unbindDevice(Callback2 callback);

 

如果设备端使用的是思必驰的整机设备或者使用思必驰dla sdk或者自行接入思必驰app端和设备端mqtt协议的,

调用完上面的接口后,还需要调用MqttManager.getInstance().unbind(deviceName)通知设备端要解绑了,让设备端去清空他的本地用户信息

 

8.3 获取绑定设备列表

/**
 * 获取绑定的设备列表
 * @param callback  callback
 * @return okhttp3.Call
 */
okhttp3.Call queryDevices(Callback<List<DeviceBean>> callback);

 

8.4 获取设备的基本信息(音量、网络连接状态、wifi名称、电量、播放列表数量、蓝牙)

/**
 * 获取设备的基本信息(音量、网络连接状态、wifi名称、电量、播放列表数量、蓝牙)
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call getDeviceBasicInfo(Callback<DeviceBasicInfo> callback);

 

8.5 获取设备的状态(在线,离线)

/**
 * 获取设备的状态(在线,离线)
 * @param callback callback
 * @return retrofit2.Call
 */
Call getDeviceStatus(Callback<DeviceStatus> callback);

 

8.6 查询设备是否配网成功

/**
 * 查询设备是否配网成功
 * @param uid uid,在配网的时候通过蓝牙或者声波传给设备端的本次配网的唯一标识
 * @param callback 异步回调
 * @return retrofit2.Call
 */
Call getDeviceNetWork(String uid, Callback<DeviceNetState> callback);

 

8.7 闹钟

8.7.1 获取闹钟列

/**
 * 获取闹钟列表
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call getAlarmList(Callback<List<AlarmDateBean>> callback);

 

8.7.2 新增闹钟

/**
 * 添加闹钟
 * @param alarmDateBean 闹钟信息
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call addAlarm(AlarmDateBean alarmDateBean, Callback2 callback);

 

8.7.3 删除闹钟

/**
 * 删除闹钟(id数组)
 * @param list 闹钟id的数组
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call delAlarm(List<Integer> list, Callback2 callback);

 

8.8 日程提醒

8.8.1 获取日程提醒列表

/**
 * 获取日程提醒列表
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call getScheduleList(Callback<List<ScheduleDateBean>> callback);

 

8.8.2 新增日程提醒

/**
 * 增加日程
 * @param scheduleDateBean 日程信息
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call addSchedule(ScheduleDateBean scheduleDateBean, Callback2 callback);

 

8.8.3 删除日程提醒

/**
 * 删除日程
 * @param list 日程id组成的列表
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call delSchedule(List<Integer> list, Callback2 callback);

 

8.9 打开或关闭蓝牙

/**
 * 设置蓝牙状态
 * @param open true:打开 false:关闭
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call setBluetoothState(boolean open, Callback2 callback);

 

8.10 打开或关闭就近唤醒

/**
 * 设置就近唤醒开关状态 true:打开 false:关闭
 * @param open true:打开 false:关闭
 * @param callback callback
 * @return retrofit2.Call
 */
Call setNearWakeupState(boolean open, Callback2 callback);

 

8.11 语音留言

8.11.1 获取语音留言

/**
 * 获取语音留言记录
 * @param page 页码
 * @param count 每页的留言个数
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call getVoiceMessage(int page, int count, final Callback<ChatMessageDataResult> callback);

 

8.11.2 上传语音留言

/**
 * 保存语音留言记录
 * @param file 文件
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call sendVoiceMessage(File file, final Callback2 callback);

 

8.11.3 将留言未读转换成已读

/**
 * 将留言未读转换成已读
 * @param chatId 留言id
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call readVoiceMessage(String chatId, final Callback2 callback);

 

8.12 群聊

8.12.1 获取群聊列表

/**
 * 查询群聊天列表
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call getGroupChats(final Callback<List<ChatItem>> callback);

 

8.12.2 创建群聊

/**
 * 新建群聊天
 * @param chatCreateRequest 群信息
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call createGroupChat(ChatCreateRequest chatCreateRequest, final Callback<ChatItem> callback);


8.12.3 获取某个群的聊天记录

/**
 * 获取某个群的聊天记录
 * @param chatId chatId
 * @param page 第几页
 * @param count 每页的聊天消息的个数
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call getGroupChatMessage(long chatId, int page, int count, Callback<ChatGroupMsgResult> callback);

 

8.12.4 发送聊天信息

/**
 * 发送聊天信息
 * @param chatId chatId
 * @param file file
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call sendGroupChatMessage(long chatId, File file, final Callback2 callback);

 

8.12.5 将群聊消息置为已读

/**
 * 将群聊消息置为已读
 * @param chatId
 * @param messageId
 * @param callback 回调接口
 * @return retrofit2.Call
 */
Call setGroupChatMsgRead(long chatId, long messageId, Callback2 callback);

 

8.13 场景模式(快捷指令)

场景模式(快捷指令)生效后对应的语音端dds sdk的处理见https://www.duiopen.com/docs/ct_common_Andriod_SDK 3.21 快捷指令

8.13.1 创建场景模式

/**
 * 创建场景模式
 * @param productId
 * @param quickCreateRequest
 * @param callback
 * @return
 */
Call addInstructionV2(String productId, QuickCreateRequestV2 quickCreateRequest, Callback<AddQuickResult> callback)

调用示例:

        //todo productId 填自己的产品id,由音箱端获得,然后传给手机端
        String productId = "278571847";
        // 快捷指令说法,数组长度至少为一,第一个为主说法,其他为同义说法,目前仅支持主说法
        List<String> listSentences = new ArrayList<>();
        listSentences.add("测试测试测试测试测试");
        // 说了上面的说法后系统将执行的动作
        List<Command> listCommands = new ArrayList<>();
        listCommands.add(new Command("今天天气怎么样", CommandType.OPERATION)); //CommandType.OPERATION表示执行动作,一个Command对象表示一个操作指令
        listCommands.add(new Command("命令1", CommandType.OPERATION));
        listCommands.add(new Command("命令2", CommandType.OPERATION));
        listCommands.add(new Command("执行完毕", CommandType.REPLY)); //CommandType.REPLY表示回复语

        QuickCreateRequestV2 quickCreateRequest = new QuickCreateRequestV2();
        quickCreateRequest.setSentences(listSentences);
        quickCreateRequest.setCommands(listCommands);
        Log.d(TAG, "submit quickCreateRequest : " + quickCreateRequest.toString());
        DcaSdk.getDeviceManager().addInstructionV2(productId, quickCreateRequest, new Callback<AddQuickResult>() {
            @Override
            public void onSuccess(AddQuickResult addQuickResult) {
                if (addQuickResult != null){
                    Log.d(TAG, "addInstruction onSuccess: " + addQuickResult.getInstructionId());
                    instructionId = addQuickResult.getInstructionId();
                }
            }

            @Override
            public void onFailure(int errCode, String errMsg) {
                Log.d(TAG, "addInstruction  errCode: " + errCode + " , errMsg = " + errMsg);
            }
        });

 

8.13.2 删除场景模式

/**
 * 删除场景模式
 * @param instructionId
 * @param productId
 * @param callback
 * @return
 */
Call deleteInstructionV2(String instructionId, String productId, Callback2 callback)

 

8.13.3 更新场景模式

/**
 * 更新场景模式
 * @param instructionId
 * @param productId
 * @param quickCreateRequest
 * @param callback
 * @return
 */
Call updateInstructionV2(String instructionId, String productId, QuickCreateRequestV2 quickCreateRequest, Callback2 callback)


8.13.4 获取用户场景模式

/**
 * 获取场景模式
 * @param productId
 * @param callback
 * @return
 */
Call getInstructionV2(String productId, Callback<List<QuickListResultV2>> callback)

 

8.14 将authCode等参数上报服务器 服务器下发给设备授权

/**
     * 将authCode等参数上报服务器  服务器下发给设备授权
     * @param isScan 是否是扫码绑定  true:带上accessToken、refreshToken
     * @param authCode 授权码
     * @param codeVerifier 代码验证器
     * @param callback
     * @return retrofit2.Call
     */
    Call deviceAuth(boolean isScan,String authCode,String codeVerifier, final Callback2 callback);

 

9.内容资源相关接口

根据信源ID获取信源信息,logo和name用于品牌露出(资源id请联系思必驰项目经理):

DcaSdk.getSourceManager.getSourceInfo(String id, Callback<SourceInfo> callback);

 

若需要接入内容资源,请联系思必驰项目经理或在“APP开发->客户咨询”联系我们

10.音频播控接口

以下接口需要在用户登录后,

并且需要设置

DcaSdk.setCurrentDeviceId(deviceName);//设置devicename

后调用

入口为:DcaSdk.get().getMediaCtrlManager()

/**
 * 获取设备当前的播放列表 page:第几页,如果填0,则取当前正在播放的那一页 count:每页多少条
 * @param page 页码 从1开始
 * @param count 每页个数
 * @param callback 回调 当前的播放列表
 * @return retrofit2.Call
 */
Call getMusicPlayList(int page, int count, Callback<PlayerListResponse> callback);

/**
 * 播放播放列表里的第几首歌, 从1开始
 * @param index
 * @param callback 回调
 * @return retrofit2.Call
 */
Call playMusicInPlayListByIndex(int index, Callback2 callback);


/**
 * 播放上一首
 * @param callback 回调 当前歌曲信息
 * @return retrofit2.Call
 */
Call playPrev(Callback<MusicBean> callback);

/**
 * 播放下一首
 * @param callback 回调 当前歌曲信息
 * @return retrofit2.Call
 */
Call playNext(Callback<MusicBean> callback);

/**
 * 暂停
 * @param callback 回调
 * @return retrofit2.Call
 */
Call pause(Callback2 callback);

/**
 * 继续播放
 * @param callback 回调
 * @return retrofit call
 */
Call resume(Callback2 callback);

/**
 * 播放过程中,调用该方法会跳转到这一秒播放
 * @param seconds 秒,播放过程中,跳转到这一秒播放
 * @param callback 回调
 * @return retrofit call
 */
Call seekTo(long seconds, Callback2 callback);

/**
 * 获取当前播放模式
 * @param callback 回调 当前播放模式
 * @return retrofit2.Call
 */
Call getPlayerMode(Callback<PlayerMode> callback);

/**
 * 设置当前播放模式
 * @param playerMode 1:顺序播放 2: 单曲播放
 * @param callback 回调
 * @return retrofit2.Call
 */
Call setPlayerMode(int playerMode, Callback2 callback);

/**
 * 获取音量
 * @param callback 回调 音量 0~100
 * @return retrofit2.Call
 */
Call getVolume(Callback<Volume> callback);

/**
 * 设置音量
 * @param volume  音量 0~100
 * @param callback 回调
 * @return retrofit2.Call
 */
Call setVolume(int volume, Callback2 callback);

/**
 * 播放指定歌曲
 * @param isOwn  公版默认true
 * @param musicBean 歌曲信息
 * @param callback 回调
 * @return retrofit2.Call
 */
Call playSong(boolean isOwn, MusicBean musicBean, Callback2 callback);

/**
 * 播放指定专辑
 * @param albumBean 专辑信息
 * @param callback 回调
 * @return retrofit2.Call
 */
Call playAlbum(AlbumBean albumBean, Callback2 callback);

/**
 * 如果是播放的收藏歌曲,在播放收藏歌曲回调成功后,需要调用这个接口告知服务端在播放收藏歌曲
 * @param callback
 * @return retrofit2.Call
 */
Call notifyCollectionPlay(Callback2 callback);

/**
 * 播放歌曲列表
 * @param request PlaySongListRequest 歌曲列表
 * @param callback  回调
 * @return retrofit2.Call
 */
Call playSongList(PlaySongListRequest request, Callback2 callback);

11.通过mqtt推送设备端状态信息到app端

在AndroidManifest.xml中声明:

<service android:name="org.eclipse.paho.android.service.MqttService" /> <!-- 如果用到mqtt -->
MqttManager.getInstance().registerListener(mMqttListener); //注册listener,这个listener会收到音箱端的实时状态消息
String deviceName = "00000000100220181120704f08000ea2"; //todo 设置设备deviceName
if(TextUtils.isEmpty(deviceName)) {
    Toast.makeText(this, "请设置设备deviceName", Toast.LENGTH_LONG).show();
    return;
}
DcaSdk.setCurrentDeviceId(deviceName);


//这里音频播放分两种,
//一种是直接对着音箱说我要听周杰伦的歌,这种我们称为dui的资源
//另一种是通过app点播的歌,这个我们称为app的资源

MqttListener mMqttListener = new MqttListener() {
    @Override
    public void onPlayerPlay(MusicBean musicBean) {
        Log.d(TAG, "onPlayerPlay : " + musicBean);
        //这个回调是dui的资源的回调,对着音箱说我要听周杰伦的歌,会走这个回调
        //如果音箱在播放dui的资源,那说下一首,上一首,也会走这个回调

    }

    @Override
    public void onPlayerPause() {
        Log.d(TAG, "onPlayerPause");
        //对着音箱说暂停播放
    }

    @Override
    public void onPlayerResume() {
        Log.d(TAG, "onPlayerResume");
        //对着音箱说继续播放
    }

    @Override
    public void onPlayerPre(MusicBean musicBean) {
        Log.d(TAG, "onPlayerPre : " + musicBean);
        //如果音箱在播放app的资源,那说上一首,会走这个回调
    }

    @Override
    public void onPlayerNext(MusicBean musicBean) {
        Log.d(TAG, "onPlayerNext : " + musicBean);
        //如果音箱在播放app的资源,那说下一首,会走这个回调
    }

    @Override
    public void onDeviceInfo(DeviceInfo deviceInfo, MusicBean musicBean) {
        Log.d(TAG, "onDeviceInfo : " + deviceInfo + " musicBean : " + musicBean);
        //这个是调用了GlobalInfo.setCurrentDeviceId(deviceName);后会回调这个回调,
        //主要用于app刚启动,或者app端切换选择的设备的时候用到,用于首次显示音箱的状态,和是否在播放歌曲等
    }

    @Override
    public void onVolume(int volume) {
        Log.d(TAG, "onVolume : " + volume);
        //语音或者音箱端按键控制的音量变化
    }

    @Override
    public void onBlueToothState(boolean isTurnedOn) {
        Log.d(TAG, "onBlueToothState : " + isTurnedOn);
        //语音或者音箱端按键控制的蓝牙变化
    }

    @Override
    public void onPlayerMode(int mode) {
        Log.d(TAG, "onPlayerMode : " + mode);
        //语音控制的播放模式的变化,1 :顺序播放,2 : 单曲播放
    }

    @Override
    public void onAppOnline() {
        Log.d(TAG, "onAppOnline");
        //设备在线会一直调这个接口
    }

    @Override
    public void onAppOffline() {
        Log.d(TAG, "onAppOffline" );
        //设备下线
    }

    @Override
    public void onUnbind() {
        //设备主动解绑
    }

    /**
     * 设备主动取消收藏
     *
     * @param musicBean
     */
    @Override
    public void onCancelLike(MusicBean musicBean) {

    }

    /**
     * 设备主动收藏
     *
     * @param musicBean
     */
    @Override
    public void onLike(MusicBean musicBean) {

    }
};

12.自定义问答

自定义问答是指用户可以根据自己的喜好设置问答对,当用户对设备提问时,设备根据用户设置的答案进行回复,比如“我的老婆是谁” “你的老婆还未成年呢”

前提:自定义问答生效需要在dui的平台产品里面加上会话精灵的闲聊技能

入口为DcaSdk.getQaManager()

/** 
* 初始化qa信息,获取QaInitResult,其中的值需要在后续操作中使用 
* @param callback 请求的异步回调方法 
*/
public Call initQa(final Callback<QaInitResult> callback)


/** 
* 根据productId获取知识点问答信息概览,这个productid不是dui的产品id,而是对话精灵的产品id,可以从initQa的回调中获取 
* 这个接口可以返回所有知识点,但每个知识点只显示一对主问答对,该知识点的其他的相似问答对,需要调用 queryQaInfoDetail获取 
* @param productId 对话精灵的产品id * @param callback 请求的异步回调方法 
*/
public Call queryQaInfo(String productId, final Callback<List<QaInfo>> callback)



/** 
* 根据kid查询知识点问答对 
* @param kId 知识点id,可以从queryQaInfo获取 
* @param callback 请求的异步回调方法 
*/
 public Call queryQaInfoDetail(String kId, final Callback<QaInfo> callback)


/** 
* 新增知识点问答对 
* @param qaInfo qaInfo 
* @param callback 请求的异步回调方法 
*/
public Call addQaInfo(QaInfo qaInfo, final Callback<QaInfo> callback)


/** 
* 根据kid,删除知识点 
* @param kId kId,知识点id,由QaInfo的TopicKnowledgeModelBean的kid获取到 
* @param callback 请求的异步回调方法 
*/
public Call deleteQaInfo(String kId, final Callback2 callback)


/** 
* 更新知识点问答对 
* @param qaInfo qaInfo 
* @param callback 请求的异步回调方法 
*/
public Call updateQaInfo(QaInfo qaInfo, final Callback2 callback)


/** 
* 每次调用增加或者修改或者删除数据后,都要调用这个接口 
* 使得增加和修改的数据在语音对话中生效, 每次调用其他接口增加或者修改数据后,都要调用这个接口 
* @param productId 对话精灵的产品id 
* @param callback 请求的异步回调方法 
*/
public Call effectiveOperation(String productId, final Callback2 callback) 

13.智能家居接口

以下为智能家居的相关接口,接口的使用和字段表示可以查看示例代码的demo

 

完成智能家居的整套调用流程一般需要编写的代码包括第4章账号相关接口,7.2使用dca sdk获取authcode, 本章智能家居接口,和第18章配置dds sdk

API入口为:

DcaSdk.getSmartHomeManager()

 

13.1 查询智能家居技能

备注:可通过此接口获取第三方品牌商IoT云平台列表(比如涂鸦、海尔U+)

private void querySmartHomeSkill() {
    //查询有哪些智能家居技能
    DcaSdk.getSmartHomeManager().querySmartHomeSkill( new DcaListener() {
                @Override
                public void onResult(int httpResponseCode, String httpResponseBody) {
                    Log.d(TAG, "httpResponseCode : " + httpResponseCode);
                    Log.d(TAG, "httpResponseBody : " + httpResponseBody);
                  
                }

                @Override
                public void onFailure(IOException e) {
                    Log.e(TAG, "onFailure ");
                    e.printStackTrace();
                }
            });
}

 

13.2 查询智能家居技能的账号绑定状态

/** 
* 查询智能家居技能中的思必驰(自己的)账号和第三方智能家居平台账号的绑定状态 
* @param skillId 智能家居技能的id 
* @param skillVersion 技能版本号 
* @param productId 产品id 
* @param listener 回调接口 **/
    public Call querySmartHomeAccountStatus(String skillId,
                                                   String skillVersion,
                                                   String productId, final DcaListener listener)


/**
* 批量获取第三方平台智能家居账号绑定状态
* @param productId 产品id
* @param list 技能请求list
* @param listener 异步回调
* @return okhttp3.Call
*/
    public Call batchQuerySmartHomeAccountStatus(String productId, List<SkillRequest> list, final com.aispeech.dca.Callback<List<BindStatus>> listener)

 

13.3 和第三方智能家居平台账号绑定过程

此接口用于智能家居技能账号授权时跳转到IoT平台登录页,首先生成第三方智能家居平台的web的oauth url(该URL的生成的字端在查询智能家居技能接口中返回,然后拼接出一个url,具体方法见示例demo),然后写一个webview加载该url,

用户会输入用户名和密码,然后点击授权,授权完后,第三方智能家居平台会http 302跳转到一个地址,客户端的webview需要去拦截这个地址, 并调用

DcaSdk.getSmartHomeManager().bindSmartHomeAccount方法,具体见demo

 

class CustomWebviewClient extends MyWebview.CustomWebviewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        Log.d(TAG, "shouldOverrideUrlLoading : " + url);
        if(url.contains(ACCOUNT_LINK_URL)) {
            //webview拦截这个redirect_url,然后调用dca的绑定智能家居账号的接口
            bindSmartHomeAccount(url);
            return true;
        }

        return super.shouldOverrideUrlLoading(view, url);
    }

    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        Log.e(TAG,"页面加载ssl onReceivedSslError = "+ error.toString());
        //handler.cancel();// 默认的处理方式,WebView变成空白页
        handler.proceed();//忽略证书的错误继续Load页面内容,不会显示空白页面
        // super.onReceivedSslError(view, handler, error);
    }
}

private void bindSmartHomeAccount(String url) {
    DcaSdk.getSmartHomeManager().bindSmartHomeAccount(url,productId, mSkillVersion, new DcaListener() {
        @Override
        public void onResult(int httpResponseCode, String httpResponseBody) {
            Log.d(TAG, "httpResponseCode : " + httpResponseCode);
            Log.d(TAG, "httpResponseBody : " + httpResponseBody);
            SmartHomeOAuthActivity.this.finish();
        }

        @Override
        public void onFailure(IOException e) {
            Log.e(TAG, "onFailure ");
            e.printStackTrace();
        }
    });
}

 

13.4 解绑智能家居

/** 
* 解除绑定第三方智能家居账号 
* @param skillId 智能家居技能id 
* @param listener 回调接口 
**/
public Call unbindSmartHomeAccount(String skillId,String productId, final DcaListener listener)

 

13.5 获取智能家居平台下的设备列表

//查询所有平台的设备
DcaSdk.getSmartHomeManager().queryAllSmartHomeAppliance(productId
        , new DcaListener() {
            @Override
            public void onResult(int httpResponseCode, String httpResponseBody) {
                Log.d(TAG, "httpResponseCode : " + httpResponseCode);
                Log.d(TAG, "httpResponseBody : " + httpResponseBody);
            }

            @Override
            public void onFailure(IOException e) {
                Log.e(TAG, "onFailure ");
                e.printStackTrace();
            }
        } );


//查询某个平台的列表(skillid)
//group 设备所属的group,若为空,可以填null或者""
DcaSdk.getSmartHomeManager().querySmartHomeAppliance(skillid, skillversion
        , productId, group, new DcaListener() {
            @Override
            public void onResult(int httpResponseCode, String httpResponseBody) {
                Log.d(TAG, "httpResponseCode : " + httpResponseCode);
                Log.d(TAG, "httpResponseBody : " + httpResponseBody);
            }

            @Override
            public void onFailure(IOException e) {
                Log.e(TAG, "onFailure ");
                e.printStackTrace();
            }
        } );

返回数据描述:

{

"result": {

"appliances": [{

"applianceType": "SOCKET",

"modelName": "xxxx",

"alias": "小明",

"discription": "",

"manufacturerName": "lifeSmart",

"actions": ["TurnOn", "TurnOff"],

"friendlyName": "多孔插座",

"applianceId": "34ea34cf2e64",

"skillId": "ssss"

}]

},

"errId": 0

}

applianceType :设备类型,从家居厂商平台获取到的。见https://www.duiopen.com/docs/smarthome_protocol 里的3.2 payload参数里的appliances.applianceType

modelName:设备型号,从家居厂商平台获取到的

alias:使用思必驰dca接口给设备取的名字

discription:设备的描述信息,从家居厂商平台获取到的

manufacturerName:设备厂商,从家居厂商平台获取到的

actions:设备支持的操作指令,从家居厂商平台获取到的。见https://www.duiopen.com/docs/smarthome_protocol 里的3.2 payload参数里的appliances.actions

friendlyName:家居厂商自己app里用户给设备取的名字

applianceId:设备id,从家居厂商平台获取到的

skillId:该家居技能id

 

13.6 设置智能家居设备的位置信息

目前限定位置自定义位置:

1. 字符必须为汉字,英文字母(必须为大写字母)或者阿拉伯数字(最多 1 个)。

2. 如果有阿拉伯数字,则必须在词尾。

3. 字符(UTF-8)长度在 [2, 6] 内。

4. 整个语句不在敏感词列表中。

/** 
* 更新智能家居第三方平台下的设备的自定义位置信息
* @param applianceId 智能家居平台的设备id 
* @param skillId 智能家居技能id 
* @param position 位置信息
* @param productId 产品id 
* @param group 设备所属的group,若为空,可以填null或者""
* @param listener 回调接口 **/
    public Call updateApplianceCustomPosition(String applianceId, String skillId,
                                       String position, String productId, String group, final DcaListener listener)

 

13.7 获取智能家居设备的位置信息

/** 
* 查询智能家居第三方平台下的设备的自定义位置信息 
* @param applianceId 智能家居平台的设备id 
* @param skillId 智能家居技能id 
* @param listener 回调接口 
**/
public Call queryAppliancePosition(String applianceId,String skillId,final DcaListener listener) 

/**
* 批量获取第三方智能家居平台的设备的自定义位置信息, 注意:如果某个设备没有设置过位置信息,就不会返回该设备的数据
* @param productId 产品id
* @param requests 技能id列表
* @param listener 异步回调
* @return okhttp3.Call
*/
public Call batchQueryAppliancePosition(String productId, List<BatchPosRequest> requests, final com.aispeech.dca.Callback<List<AppliancePosResult>> listener)

 

13.8 设置家居设备名称

目前限定自定义名称 :

1. 字符必须为汉字,英文字母(必须为大写字母)或者阿拉伯数字(最多 1 个)。

2. 如果有阿拉伯数字,则必须在词尾。

3. 字符(UTF-8)长度在 [2, 10] 内。

4. 整个语句不在敏感词列表中。

 

设置完成后可以从获取智能家居平台下的设备列表的接口返回的alias字段查到

设置完成后可以从获取智能家居平台下的设备列表的接口返回的alias字段查到

/** 
* 更新第三方智能家居平台设备的自定义名称信息 
* @param applianceId 智能家居平台的设备id
* @param skillId 智能家居技能id 
* @param productId 产品id 
* @param alias 要更新的名称,只支持中文,长度为2-6个,单个用户下仅支持最多50个自定义名称. 
* @param group 设备所属的group,若为空,可以填null或者""
* @param listener 回调接口 
**/
public Call updateApplianceAlias(String applianceId, String skillId, String productId,
                                 String alias, String group, final DcaListener listener) 

 

13.9 跳过智能家居技能登录页面

当集成本sdk的开发者和智能家居厂商是同一家公司的时候,这时候在app登录完成后,如果使用智能家居技能,则还需要登录一次,那么这个体验会很差。为了解决这个问题,我们提供了跳过二次智能家居平台的登录页面接口,接口如下:

注意:skillid和skillversion一定要填写正确,不能瞎填。token一定要是和思必驰oauth对接后,思必驰服务端能使用该token访问贵司智能家居服务,智能家居技能务必要上架成功。

 

通常调了该接口后,语音或者查询iot设备,返回用户没有绑定智能家居技能, 那大部分都是因为上面标红的原因造成的

SmartHomeTokenRequest request= new SmartHomeTokenRequest();
request.setProductId(productId);
request.setSkillId("xxx");
//设置智能家居技能id,技能id写死,在dui平台的技能页面可以看到
request.setSkillVersion(skillVersion);
//设置技能版本号,版本号可以通过 13.11 智能家居技能详情接口动态获取
request.setSmartHomeAccessToken(smarthometoken);
//这个token是第三方智能家居厂商自己的token,用来访问智能家居厂商的后台服务

request.setSmartHomeRefreshToken(smarthomeRefreshtoken); 
//除非AccessToken永久有效,否则需要传入refreshtoken、ExpiresIn相关参数以保证思必驰定时刷token
//思必驰后台会在ExpiresIn的时间后刷新token,如果开发者想要自己维护token,
//那么请确保在使用智能家居相关功能前,调用updateSmartHomeTokenInfo,确保AccessToken有效
//请注意:一旦更新某个用户的token(永久token),那么该用户历史设置的token立即失效,无法在其他接口中使用

request.setAccessTokenExpiresIn(2*60*60); 
//如果没有refreshtoken,那么可以不用调用该接口

DcaSdk.getSmartHomeManager().updateSmartHomeTokenInfo(request, new DcaListener() {
    @Override
    public void onResult(int httpResponseCode, String httpResponseBody) {

    }

    @Override
    public void onFailure(IOException e) {

    }
});

ps:一旦更新某个用户的token(永久token),那么该用户历史设置的token立即失效,无法在其他接口中使用

13.10 同步智能家居厂商的设备名称和设备位置

目前限定自定义名称 :

1. 字符必须为汉字,英文字母(必须为大写字母)或者阿拉伯数字(最多 1 个)。

2. 如果有阿拉伯数字,则必须在词尾。

3. 字符(UTF-8)长度在 [2, 10] 内。

4. 整个语句不在敏感词列表中。

 

目前限定位置自定义位置:

1. 字符必须为汉字,英文字母(必须为大写字母)或者阿拉伯数字(最多 1 个)。

2. 如果有阿拉伯数字,则必须在词尾。

3. 字符(UTF-8)长度在 [2, 6] 内。

4. 整个语句不在敏感词列表中。

 

否则同步设备名称和位置会出现异常

注意:在调用了跳过智能家居页面接口或者在智能家居页面登录绑定后可以不用立刻调用该接口,否则会出错

因为在绑定过程中服务端默认会同步一次设备,而思必驰的同一用户的同步设备是单任务的

private void applianceAliasSync() {
    ApplianceAliasSyncRequest request = new ApplianceAliasSyncRequest();
    request.setProductId(productId);
    ArrayList<ApplianceAliasSyncRequest.SkillListBean> skillList = new ArrayList<>();
    ApplianceAliasSyncRequest.SkillListBean skillListBean = new ApplianceAliasSyncRequest.SkillListBean();
    skillListBean.setSkillId("2019112800000007"); //todo 设置skillid, 这里随便填一个,真实场景要使用真实的家居技能id
 skillListBean.setSkillVersion("2");// todo 设置skillversion, 这里随便填一个,真实场景要使用真实的家居技能version,可以调用13.11 智能家居技能详情接口动态获取
 skillList.add(skillListBean);
    request.setSkillList(skillList);

//        request.setGroup("家庭B"); //可选参数,如果有可以调用,设备所属的group
//        request.setIotSkillId("2019112800000007"); //可选参数,用于限定 group 过滤的技能 ID
    //主动触发设备列表同步接口,调用该接口后,思必驰服务端会向绑定了的厂商的智能家居平台同步设备名称
 DcaSdk.getSmartHomeManager().applianceAliasSync(request, new DcaListener() {
        @Override
 public void onResult(int httpResponseCode, String httpResponseBody) {

        }

        @Override
 public void onFailure(IOException e) {

        }
    });
}

13.11 智能家居详情接口

/**
     * 根据智能家居技能id获取详情
     * @param skillId 智能家居技能id
     * @param listener 回调
     * @return okhttp3.Call
     */
    public Call querySmartHomeSkillDetail(String skillId, final com.aispeech.dca.Callback<SmartHomeSkillDetail> listener)

13.12 智能家居技能支持的设备接口

 /**
     * 查询该智能家居技能支持的设备
     * @param skillId 智能家居技能id
     * @param page 分页拉取页数 从1开始
     * @param pageSize 每页数量
     * @param listener 回调
     * @return okhttp3.Call
     */
    public Call querySupportDevice(String skillId, int page, int pageSize, final com.aispeech.dca.Callback<SupportDeviceResult> listener) 

14.对话消息

入口为DcaSdk.getDialogueManager()

14.1 查询对话消息历史记录

查询对话消息历史的前提是该用户必须已经和设备处于绑定状态(即已经调用过绑定设备的接口)

private void queryDialog() {
    
    DcaSdk.getDialogueManager().queryDialogRecord(deviceName, productId, "", 10
            , new DcaListener() {
                @Override
                public void onResult(int httpResponseCode, String httpResponseBody) {
                    Log.d(TAG, "httpResponseCode : " + httpResponseCode);
                    Log.d(TAG, "httpResponseBody : " + httpResponseBody);
                }

                @Override
                public void onFailure(IOException e) {
                    Log.e(TAG, "onFailure ");
                    e.printStackTrace();
                }
            } );
}


参数说明:
* @param deviceName deviceName ,可以从设备端的dds sdk获取到
* @param productId 产品id
* @param seqId 消息拉取的起始seqId,选填,填null或者空字符串则默认返回最新的消息
* @param count 拉取消息个数
* @param listener 回调接口

返回格式如下:

inputText为语音输入,dmOutput为对话输出,其中的nlg为tts播报内容

返回的对话消息为逆序, 最下面的是最新消息

{
    "errorId":0,
    "result":[
        {
            "seqId":1541573331577000,
            "dmOutput":{
                "dm":{
                    "widget":{
                        "type":"text",
                        "text":"保持微笑吧!老天爷眷顾爱笑的人"
                    },
                    "nlg":"保持微笑吧!老天爷眷顾爱笑的人"
                },
                "error":{
                    "errMsg":"ba skill respond ok.",
                    "errId":"010507"
                }
            },
            "inputText":"今天天气怎么样"
        },
        {
            "seqId":1541573756014000,
            "dmOutput":{
                "dm":{
                    "widget":{
                        "type":"text",
                        "text":"我猜你是我的主人呀,嘿嘿,猜对了吧"
                    },
                    "nlg":"我猜你是我的主人呀,嘿嘿,猜对了吧"
                },
                "error":{
                    "errMsg":"ba skill respond ok.",
                    "errId":"010507"
                }
            },
            "inputText":"猜猜我是谁"
        }
    ]
}

15.技能

入口为DcaSdk.getSkillManager()

15.1 查询产品内置技能

根据产品版本号查询:

private void querySkillListByProductVersion() {
    DcaSdk.getSkillManager().querySkillListByProductVersion(productId, productVersion
            , new DcaListener() {
                @Override
                public void onResult(int httpResponseCode, String httpResponseBody) {
                    Log.d(TAG, "httpResponseCode : " + httpResponseCode);
                    Log.d(TAG, "httpResponseBody : " + httpResponseBody);
                }

                @Override
                public void onFailure(IOException e) {
                    Log.e(TAG, "onFailure ");
                    e.printStackTrace();
                }
            } );
}

根据产品分支号查询:

private void querySkillListByAliasKey() {
    DcaSdk.getSkillManager().querySkillListByAliasKey(productId, aliasKey
            , new DcaListener() {
                @Override
                public void onResult(int httpResponseCode, String httpResponseBody) {
                    Log.d(TAG, "httpResponseCode : " + httpResponseCode);
                    Log.d(TAG, "httpResponseBody : " + httpResponseBody);
                }

                @Override
                public void onFailure(IOException e) {
                    Log.e(TAG, "onFailure ");
                    e.printStackTrace();
                }
            } );
}

查询结果:

{
    "code": "0",
    "data": {
        "chat": {
            "id": "4",
            "libs": [
                "0"
            ],
            "portrait": {
                "爱好": "陪主人聊天",
                "语言": "普通话",
                "星座": "天秤座",
                "生日": "二零一七年",
                "出生地": "苏州",
                "物种": "机器人",
                "妈妈": "思必驰",
                "朋友": "主人",
                "爸爸": "思必驰",
                "性别": "女",
                "姓名": "小驰",
                "属相": "羊",
                "技能": "查天气,讲故事,笑话,背古诗,聊天解闷",
                "老板": "思必驰",
                "姓氏": "小",
                "住址": "苏州",
                "食物": "电",
                "制造商": "思必驰",
                "国籍": "中国",
                "年龄": "一岁",
                "身高": "一米"
            }
        },
        "skills": [
            {
                "skillName": "地图_native",
                "skillId": "100000531",
                "img": "",
                "skillType": 1,
                "engineType": 0,
                "isFallback": false,
                "category": 4,
                "isBuiltIn": 0,
                "version": "1"
            },
            {
                "skillName":"新百科",
                "skillId":"2018042100000006",
                "img":"https://console.oss.dui.ai/skills/icon/test/1000000076_1524313809_85aa0b58febdd71098f8ace9c9d312d9",
                "skillType":1,
                "engineType":2,
                "isFallback":false,
                "category":7,
                "isBuiltIn":1,
                "version":"2"
            }
        ],
        "talkinggenius": [
            {
                "skillName": "1233",
                "skillId": 10000101
            },
            {
                "skillName": "456",
                "skillId": 10000201
            }
        ]
    },
    "message": "success"
}

开发者可以关注skills字端(技能信息)

chat字端表示旧闲聊的技能,如果chat中有id字端,表示产品中有旧闲聊的技能, 没有id字端,表示没有旧闲聊的技能

 

15.2 查询技能的详情

/** 
* 查询技能详情 
* @param skillId 技能id 
* @param skillVersion 技能版本号 
* @param listener 回调接口 
* @return okhttp3.call 
**/
public Call querySkillDetails(String skillId, String skillVersion, final DcaListener listener)


/**
* 批量查询技能详情
*
* @param list 支持传多个技能列表id和version
* @return okhttp3.call
**/
public Call querySkillDetails(List<SkillDetailRequest> list, final DcaListener listener)

返回格式:

{
    "errcode":0,
    "errmsg":null,
    "data":[
        {
            "skillName":"天气家居",
            "image":"",
            "skillId":100000574,
            "utterances":"",
            "versionDesc":"",
            "skillDesc":"",
            "changeLog":"",
            "defaultLogo":8,
            "version":5
        }
    ]
}
skillId 技能id
version 技能版本
skillName 技能名称
skillDesc 技能描述
versionDesc 版本更新说明(指定到解决方案时填的)
changeLog 版本发布说明
utterances 推荐说法
defaultLogo

int型,每个值对应一张图片 默认logo,logo见工程demo中drawable目录

1: "ico_xiaolv.png",
2: "ico_life.png",
3: "ico_traffic.png",
4: "ico_movie.png",
5: "ico_social.png",
6: "ico_news.png",
7: "ico_quiz.png",
8: "ico_home.png",
9: "ico_car.png",
10: "ico_finance.png",
11: "ico_sports.png",
12: "ico_shopping.png",
13: "ico_game.png",
14: "ico_education.png"

image 用户上传的技能图标,优先取image,没有的话再取defaultLogo

 

15.3 技能内付费

流程:需要在dui语音产品中加入付费技能,然后该用户使用oauth授权机制来授权dds sdk,

然后通过语音识别指令触发该付费技能(比如,我要听xxx的歌),机器会回复该资源需要付费。

然后接下来可以调用dca sdk接口(需要保证dca sdk的登录用户和给dds sdk授权的用户是同一个)来付费。

1.获取对话记录中付费资源列表
//**
     * 从最近count条对话记录中获取付费资源列表,可能为空
     *
     * @param deviceName 设备id,可以从设备端的dds sdk获取到,可以从设备端在配网绑定设备的时候从设备端传到手机端
     * @param productId  产品id
     * @param count      拉取的对话记录消息个数,这个count是表示对话记录的消息个数,不是付费资源消息的个数,会从这些对话记录消息中查看是否有付费资源消息
     * @param callback   付费资源列表
     * @return call
     */
    public Call getPayResourceList(final String deviceName, final String productId, int count, final com.aispeech.dca.Callback<List<PayBean>> callback)

2.生成订单

/**
     * 生成订单
     *
     * @param payBody  {@link PayBean.PayBody}
     * @param callback 订单id回调
     * @return call
     */
    public Call generateOrderId(PayBean.PayBody payBody, final com.aispeech.dca.Callback<String> callback)

3.调起支付宝付款

 /**
     * 调起支付宝付款
     *
     * @param activity 当前界面
     * @param orderId  订单id
     * @param callback 结果回调
     * @return call
     */
    public Call pay(final Activity activity, String orderId, final com.aispeech.dca.Callback2 callback)

4.查询订单支付状态

/**
     * 查询订单支付状态
     *
     * @param orderId  订单id
     * @param callback 结果回调,json string
     * @return call
     */
    public Call getOrderStatus(String orderId, final com.aispeech.dca.Callback<String> callback)

16.H5集成

为了方便开发者快速集成功能,减少开发流程,DCA提供了多个H5页面,

h5界面由Fragment的形式提供给开发者,包括

enum WebType {
SMARTHOME("智能家居"),
SMARTHOME_DEVICE_LIST("智能家居设备列表"),
DIALOG_MESSGAE("对话日志"),
CUSTOM_QA_CREATE("创建自定义问答"),
CUSTOM_QA("自定义问答"),
SKILL_CENTER("技能中心"),
SKILL_SEARCH("搜索技能结果页"),
//以下为兼容老版本dca的
PRODUCT_SKILL("产品内置技能"),
SKILL_STORE("技能商店");
}

都必须先通过账号sdk登录并绑定设备后,并传入userid,token,devicename才能使用

WebViewParam param = new WebViewParam.Builder()
        .productId("278570261")//todo 填自己的产品id,由音箱端获得,然后传给手机端 
        .aliasKey("prod") //todo 填自己产品在dui控制台的分支号
        .deviceId("2b8a6bc0e5304a3b843ede7ecd85c0ea")//todo 填自己音箱的devicename,由dds sdk获取得到
	.hideTitle(true)//是否隐藏h5页面的默认title,true隐藏, false不隐藏, 默认为false 
                        // , 对智能家居,智能家居设备列表,对话记录的h5页面有效
        .webType(mWebType) //web type表示h5界面的类型
        .build();


WebViewFragment mFragment = DcaSdk.getDcaWebViewFragment(param);

 

17.人声复刻

用户可以复刻合成一个与用户相似的TTS音色,应用在特定的一些播报场景,提升语音交互的趣味性

note:使用该功能前,需要项目经理向人声复刻服务申请使用。每个账户最多复刻三个音色

本模块接口的入口为:DcaSdk.getVoiceCopyManager()

 

17.1 获取tts复刻录音文本列表

 /**
     * 获取tts复刻所需要录音的文本列表,用户拿到这些列表后需要对着文本录音,然后再上传训练等
     * @param productId dui全链路语音产品id
     * @param callback 回调 见Text
     * @return retrofit2.Call
     */
    Call getText(String productId, Callback<List<Text>> callback);


public class Text implements Serializable {


    /**
     * 文本id
     */
    private String textId;
    /**
     *  文本内容
     */
    private String text;
}

 

17.2 上传音频(音频检测)

    /**
     * 上传音频(音频检测)
     * @param request 见UploadRequest
     * @param callback 回调, 见UploadResult
     * @return retrofit2.Call
     */
    Call upload(UploadRequest request, Callback<UploadResult> callback);


public class UploadRequest implements Serializable {
    /**
     * 产品id
     */
    private String productId;
    /**
     * 文本id 由getText(String productId, Callback<Text> callback); 中的Text的getTextId获取
     */
    private String textId;
    /**
     * MALE / FEMALE , 必填
     */
    private String gender;

    /**
     * age 年龄段 (成人|儿童) ADULT / CHILD, 非必填
     */
    private String age;

    /**
     * 音频文件路径
     */
    private String filePath;

}



public class UploadResult implements Serializable {


    /**
     * is_valid : true
     * match_percent : 100
     * audio_reserve_id : a7baea217bfa4037b3f0d26ff336d834
     * highlight_text : 天空那么蓝,太阳那么高,一群大雁往南飞。这是收获的季节,很多果实开始成熟了。
     * productId : 278578188
     */

    private boolean is_valid;

    /**
     * 匹配度,所有字都读对,100分
     */
    private int match_percent;

    /**
     * 音频文件的唯一标识, 后面提交训练会用到
     */
    private String audio_reserve_id;

    /**
     * 读错的字会高亮显示,就是<mark>包含的部分
     */
    private String highlight_text;
    private String productId;
}

 

17.3 提交训练

    /**
     * 提交训练, 回调成功指提交成功,不是指训练成功,训练需要较长的时间
     * @param request 见TrainRequest
     * @param callback 回调,见TrainResult
     * @return retrofit2.Call
     */
    Call training(TrainRequest request, Callback<TrainResult> callback);


public class TrainRequest  implements Serializable {
    /**
     *
     */
    private String productId;

    /**
     * 自定义声音录音性别(MALE 和 FEMALE)
     */
    private String gender;

    /**
     * 年龄段 (成人|儿童) ADULT / CHILD
     */
    private String age;

    /**
     * 自定义音色资源名称
     */
    private String customInfo;

    /**
     * 音频上传(音频检测)接口所返回的 "audio_reserve_id" 集合
     */
    @SerializedName("audio_list")
    private List<AudioListBean> audio_list;

    /**
     * 指定的试听音频文本,训练成功之后会返回一段试听音频链接,这个文本就是你指定的试听音频的文本。
     */
    @SerializedName("pre_tts_text")
    private List<PreTtsTextBean> pre_tts_text;

}


public class TrainResult  implements Serializable {

    /**
     * 提交训练后返回的任务id
     */
    private String taskId;
}

 

17.4 查询该用户下训练任务的状态

    /**
     * 查询该用户下训练任务的状态
     * @param productId 产品id
     * @param callback 回调,见TaskResult
     * @return retrofit2.Call
     */
    Call queryTask(String productId, Callback<TaskResult> callback);

public class TaskResult implements Serializable {
    
    /**
     * 产品id
     */
    private String pid;

    /**
     * 用户id
     */
    private String userId;

    /**
     * 任务列表
     */
    private List<TaskListBean> taskList;
}

    public static class TaskListBean implements Serializable {

        /**
         * 任务id
         */
        private String taskId;
        /**
         * eventName: 训练状态,  "waiting_train", "begin_train" , "complete_train",   "fail_train"
         */
        private String eventName;

        /**
         * 音色id
         */
        private String voiceId;
        /**
         * 音色名字
         */
        private String customInfo;
        /**
         * 预听合成音列表
         */
        private List<PreTtsListBean> preTtsList;
}

 

17.5 删除音色

    /**
     * 删除音色
     * @param productId 产品id
     * @param deleteRequest 见DeleteRequest
     * @param callback2 回到篇
     * @return retrofit2.Call
     */
    Call delete(String productId, DeleteRequest deleteRequest, Callback2 callback2);

public class DeleteRequest  implements Serializable {

    /**
     * taskId : 1f596872812c465fbcebde99ea83c139
     */


    /**
     * 任务id
     */
    private String taskId;
}

 

17.6 更新音色名字

    /**
     * 更新音色名字
     *
     * @param productId 产品id
     * @param taskId 任务ID
     * @param customInfo 音色名字
     * @param callback2 回到篇
     * @return retrofit2.Call
     */
    Call updateCustomInfo(String productId,String taskId, CustomInfo customInfo, Callback2 callback2);

public class CustomInfo implements Serializable {


    /**
     * 自定义音色名字
     */
    private String customInfo;
}

 

在任务训练完成后,可以查询到该任务对应的音色的voiceId,后续在请求云端合成的时候可以将speaker设置为该voiceId,请求的服务端地址设置为http://tts.duiopen.com/api/v1/voicecopy/synthesize

云端合成出的声音就是该voiceId对应的复刻出的声音

 

18.dds sdk配置使得dca功能生效

以下是android dds sdk的配置方法,linux dds sdk版本请参考linux文档

DCA 相关功能全都依赖于设备端(比如音箱等)的DDS SDK配置oauth信息,才能使得DCA的功能生效,

18.1 sdk 配置

oauth 的相关功能已经内置在 DDS SDK 中:

 

在dependencies中加入

compile 'com.squareup.okhttp3:okhttp:3.10.0'

 

18.2 权限

<uses-permission android:name="android.permission.INTERNET" />

 

18.3 oauth初始化操作

注意:

1. 如果产品是类似于天猫精灵这种由手机app和音箱设备组成的,而且音箱端跑了语音识别等(dds sdk)功能,手机app只是配套app使用,那么

需要把client id, user id, auth code, code verifier从手机app通过某种方式(比如通过配网方式)发送给音箱端,然后用下面的代码设置oauth信息。

如果音箱端使用的是Linux系统,那么可以忽略以下内容,请参考linux开发文档。

2.如果产品不是配套app+音箱(或盒子等)设备组成的,只是一个手机app或者 只有带屏幕的音箱app的话,那么就dca sdk和dds sdk跑在一个app中,那么直接在一个app中使用(dca sdk 给 dds sdk 传递相关参数,dds 进行oauth信息设置操作)。

tips:不需要多次生成code verifie等参数,只需生成一次,存起来用作全局变量。

 

在 dds 初始化成功后调用:

dds的使用方式本文档不再详细说明,请参考dds sdk开发文档。

 

clientId                        发邮件找思必驰项目经理申请

userId                          aispeechUserId,从dca sdk中获取

authCode                    从dca sdk中获取

codeVerifier                 在 authorize 中获取 authcode 的匹配的值

redirectUri (非必须)     针对特殊需求的项目对接,一般使用默认值

 

DDS.getInstance().init(getApplicationContext(), createConfig(), new DDSInitListener() {
            @Override
            public void onInitComplete(boolean isFull) {
                if(!isFull){
                    // 初始化失败
                    return;
                }
                ...
                //以下代码是 oauth 初始化的代码,必须在初始化成功后才可调用
                AuthInfo authInfo = new AuthInfo();
                authInfo.setClientId(cliendId);
                authInfo.setUserId(userId);
                authInfo.setAuthCode(authCode);
                authInfo.setCodeVerifier(codeVerifier);
                authInfo.setRedirectUri(redirectUri);//若不设置,使用默认地址值 http://dui.callback

                try {
                     DDS.getInstance().getAgent().setAuthCode(authInfo, new TokenListener() 
                     {
                      @Override
                      public void onSuccess(TokenResult tokenResult) {
  
                      }

                      @Override
                      public void onError(int i, String s) {

                      }
                      });
                 } catch (DDSNotInitCompleteException e) {
                     e.printStackTrace();
                 }

            }

            @Override
            public void onError(int what, final String msg) {
                ...
            }

        }, new DDSAuthListener() {
            @Override
            public void onAuthSuccess() {
                ...
            }

            @Override
            public void onAuthFailed(final String errId, final String error) {
                //070611:token 非法错误码
                if (errId.equals("070611")) {
                    DDS.getInstance().getAgent().clearAuthCode();// 清除DDS SDK账号授权
                    ...relogin...//开发者可以在此处重新进行SDK的账号授权流程
                    return;
                }
            }
        });

18.4 清空用户信息(oauth信息)

一般在解绑设备的时候可以调用该接口

try {
    DDS.getInstance().getAgent().clearAuthCode();
} catch (DDSNotInitCompleteException e) {
    e.printStackTrace();
}

18.5 dds sdk获取devicename

String deviceName = "";
try {
    deviceName = DDS.getInstance().getDeviceName();
} catch (DDSNotInitCompleteException e) {
    e.printStackTrace();
}

18.6 授权完整流程图

18.7 授权注意事项

1. linkAccount 与 setAuthCode 不可同时多次调用,否则可能会引发授权失败的风险。

2. DDS授权的生命周期:

DDS授权状态与账号的登录/登出是同步的,账号登入调用 setAuthCode, 账号登出调用 clearAuthCode; DDS并不需要在每次授权成功后都必须调用 setAuthCode, 除非主动调用 clearAuthCode 的操作,否则 DDS 会一直保持当前账号授权的状态。

3. 对于已经对DDS授权过的场景,建议每次启动 DDS ,都要调用 DDS.getInstance().doAuth(), 进行鉴权判断,在 DDSAuthListener 的 success 回调里面操作DDS相关的API。

19.常见错误码

-1 网络错误,请检查网络

-2 用户信息异常,请检查登录信息

-3 设备信息缺失,请调用DcaSdk.setCurrentDeviceId

-4 用户或设备信息缺失

      首先请检查登录信息;

      然后请检查在调用相关接口前是否有调用DcaSdk.setCurrentDeviceId:DcaSdk.setCurrentDeviceId调用时机是程序启动或者切换设备后,设置设备的deviceName

108900  服务器内部错误

108901  服务器内部错误

108902  服务器内部错误

108903  传参出错

108904  账号互通接口,第三方token无效

108905  服务器内部错误

108906  传参出错

108907  服务器内部错误

108908  思必驰用户id和思必驰账号的token不匹配

108909  设备(音箱)绑定出错

108910  服务器内部错误

108911  服务器内部错误

108912  查询第三方智能家居厂商设备超时

103108  不合法的dca token,需要刷新dca token

103601  dcatoken 已过期,需要刷新dca token

103602  dca 记住我凭证不合法, 需要重新登录dca 账号

20.FAQ

Q: 为什么querySmartHomeSkillDetail提示查不到

A: 因为该智能家居技能只是发布了,但是没有上架

 

Q: 跳过智能家居登录接口updateSmartHomeTokenInfo接口什么时候需要重新调用?

A: 当skillid和skillversion变了,一定需要重新调用,productId变了可以不用重新调用。如果没有refreshtoken,当accessToken过期了需要重新调用

 

Q: 自定义问答QaManager的queryQaInfo接口查到的问答对为什么是一对一的?

A: 自定义问答QaManager的queryQaInfo接口查到的是问答信息概览,queryQaInfoDetail是详情,能查到多对多的问答对

 

Q: 为什么有时搜不到蓝牙设备

A: 搜索蓝牙设备的回调接口onScanResults每隔一小段时间会回调蓝牙设备,不要回调一次就结束扫描

 

Q: 智能家居为什么设备的名称同步完后是空的?

A: 请检查名称和位置是否合法

目前限定自定义名称 :

1. 字符必须为汉字,英文字母(必须为大写字母)或者阿拉伯数字(最多 1 个)。

2. 如果有阿拉伯数字,则必须在词尾。

3. 字符(UTF-8)长度在 [2, 10] 内。

4. 整个语句不在敏感词列表中。

 

目前限定位置自定义位置:

1. 字符必须为汉字,英文字母(必须为大写字母)或者阿拉伯数字(最多 1 个)。

2. 如果有阿拉伯数字,则必须在词尾。

3. 字符(UTF-8)长度在 [2, 6] 内。

4. 整个语句不在敏感词列表中。

 

Q: 为什么有时候调用playMusicInPlayListByIndex接口播放的歌曲不正确?

A: 入参index要填getMusicPlayList接口出参中MusicBean中的getSort()

 

Q: 为什么有时候在语音控制智能家居时,会出现"user not bind"的错误?

A: 1.请检查是否进行了账号绑定

     2.如果账号已经绑定,请检查在调用13.9 跳过智能家居技能登录页面接口的时候skillversion是否写死,应该要调用13.11 智能家居技能详情接口动态获取

 

Q:accessToken的有效期是多长时间?SDK内部刷新机制是什么样的?

A:accessToken的有效期是2个小时。DDS SDK每小时刷新一次。如果刷新失败,会重试50次,重试间隔时间是:(3000+次数n的3次方)毫秒。

 

Q:refreshToken的有效期是多长时间?刷新机制是什么样的?

A:refreshToken的有效期是30天。刷新机制跟accessToken的刷新机制是一致的。SDK在刷新accessToken的同时刷新refreshToken。当使用RefreshToken更新AccessToken时,原RefreshToken会失效,然后生成新的refreshToken。

 

 

accessToken和refreshToken是在集成了DCA SDK后,加入了OAuth授权后才有的参数,但是这两个token的维护在DDS SDK中。