编译安装源代码到小度设备,通过语音指令"小度小度,打开单肩包",调起app。app内部有支付接口示例,UIControl示例。可以参考示例代码实现自己的功能.如果有疑问可以参考FAQ
有些情况下 ,开发者需要以客户端app的型式,实现一个bot
,包括但不限于以下情况:
- app(可能是电视、手机、pad上的)已经存在,需要和dcs语音交互的主控程序去打通
- bot的功能,需要在端上有比较复杂的界面、交互、功能实现(只用view + tts 的简单交互满足不了)
所以,需要实现一个安卓系统的sdk,辅助开发以安卓app形式存在的bot。
开发出来的app可以用在在电视、show等基于安卓的DuerOS设备上
android bot sdk
的基本功能:
- 被调起
- 被探测
- 接收语音解析出来的指令
- 主动上报ui状态(供语音解析使用)
- 在适当的时候发起语音请求
- 申请成为DuerOS开发者
- AndroidApp技能类型尚未开放,需要进入到如下页面填入激活码激活AndroidApp技能开发
- 激活码
8ea5dfe6-2b25-83d8-0f0b-8285ab6a7869-19c45ea4-6deb-a02d-fd36-410c8bb75e86
- https://dueros.baidu.com/dbp/bot/index#/authorization
- 激活码
- 在DBP上创建技能,类型是Android App
- packageName
- key
- [调用名称]
可以在dbp平台上定义intent,也可以是云端预定义的ScreenNavigator等指令
建议在application启动的时候完成BotSdk的初始化
BotSdk.getInstance().init(application);
如果启动后不能正确注册,将无法收到解析出来的指令
public void register(){
if (!BotSdk.getInstance().isRegister()) {
String rand1="hongyang"+Math.random();
String rand2= "yanghong"+Math.random();
String botId="3fcc17e3-7e97-b9ec-84cd-5211f6271394"; //来自DBP平台
BotSdk.getInstance().register(
messageListener,
botId,
rand1,
sign(rand1),
rand2,
sign(rand2)
);
}
}
public String sign(String rand){
String key = "abcdefghijk12345"; //来自DBP平台
return getMD5(rand+key);
}
onHandleIntent 响应DBP平台上定义的intent。onHandleScreenNavigatorEvent响应内置的屏幕导航请求
new IBotMessageListener() {
@Override
public void onHandleIntent(String token, BotIdentity identity, BotIntent intent,
String customData) {
Log.d("BotSdk", "onHandleIntent:" + token + "|" + identity
.accessToken + "|" + intent.name + "|" + intent.slots + "|" +
customData);
if ("light_on".equals(intent.name )) {
if (intent.slots!=null && intent.slots.size() > 0 && intent.slots.get(0).value.equals("黄灯")) {
mLight.setImageDrawable(getResources().getDrawable(R.drawable.light2));
} else {
mLight.setImageDrawable(getResources().getDrawable(R.drawable.light3));
}
} else if ("light_off".equals(intent.name)) {
mLight.setImageDrawable(getResources().getDrawable(R.drawable.light));
}
}
//内置的屏幕导航请求
@Override
public void onHandleScreenNavigatorEvent(int event) {
String msg = "";
switch (event) {
case IBotMessageListener.NAV_SCROLL_LEFT: //“向左滚动”
msg = "NAV_SCROLL_LEFT";
break;
case IBotMessageListener.NAV_SCROLL_RIGHT: //“向右滚动”
msg = "NAV_SCROLL_RIGHT";
break;
case IBotMessageListener.NAV_SCROLL_UP: //“向上滚动”
msg = "NAV_SCROLL_UP";
break;
case IBotMessageListener.NAV_SCROLL_DOWN: //“向下滚动”
msg = "NAV_SCROLL_DOWN";
break;
case IBotMessageListener.NAV_NEXT_PAGE: //“下一页”
msg = "NAV_NEXT_PAGE";
break;
case IBotMessageListener.NAV_PREVIOUS_PAGE: //“上一页”
msg = "NAV_PREVIOUS_PAGE";
break;
case IBotMessageListener.NAV_GO_HOMEPAGE: //“回到首页”
msg = "NAV_GO_HOMEPAGE";
break;
case IBotMessageListener.NAV_GO_BACK: //“返回”
msg = "NAV_GO_BACK";
break;
default:
break;
}
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
}
};
//定义自定义交互
private void updateUiContext() {
UiContextPayload payload = new UiContextPayload();
HashMap<String, String> params;
params = new HashMap<>();
params.put("name", "地址");
params.put("type", "city");
payload.addHyperUtterance(
"sdkdemo://input", //url
null, //words,自定义的query列表
"input", //type
params); //其他参数
String[] words = {"试一试", "点击试一试"};
params = new HashMap<>();
params.put("name", "试一试");
payload.addHyperUtterance("sdkdemo://clicktest",
words,
"link",
params);
BotSdk.getInstance().updateUiContext(payload);
}
//响应自定义交互
new IBotMessageListener() {
@Override
public void onClickLink(String url, HashMap<String, String> paramMap) {
Log.d(TAG, "onClickLink: " + url + " , " + paramMap);
if("sdkdemo://clicktest".equals(url)){
findViewById(R.id.test).performClick();
}
if("sdkdemo://input".equals(url)){
((TextView)findViewById(R.id.input)).setText(paramMap.get("content"));
}
Toast.makeText(MainActivity.this, "url = " + url, Toast.LENGTH_SHORT).show();
}
}
type |
request params |
response slots
(除了默认的url之外) |
example |
input |
name:
(optional) value:
(optional) type:
date
car_number
cityxpress_number
city
(optional) prefix(暂不支持)
|
content |
“输入地址北京”
request params
{
name:地址,
type:city
}
response params
{
content:北京
} |
button |
name
(optional) index
(optional) index_x
(optional) index_y |
- |
“点击确认”、“选择确认”、“选择第一个”
request params
{
name: 确认,
index: 1,
} |
link |
name
(optional) index
(optional) index_x
(optional) index_y
(optional) prefix(暂不支持) |
- |
“点击确认”、“选择确认”、“选择第一个”
request params
{
name: 确认,
index: 1,
} |
select |
name
(optional) selected
(optional) index
(optional) index_x
(optional) index_y |
- |
“选择确认”、“选择第一个”
request params
{
name: 确认,
index: 1,
} |
video |
name
(optional) index
(optional) index_x
(optional) index_y
(optional) actors(screen_e)
(optional) director
(optional) prefix(暂不支持)
//后续增加的字段要与structures/search-video-structure-private.md 保持一致
|
- |
"播放琅琊榜"
request params
{
name: 琅琊榜
} |
music |
name
(optional) index
(optional) index_x
(optional) index_y
(optional) singers
(optional) album
(optional) prefix(暂不支持) |
- |
"播放青花瓷"
request params
{
name: 青花瓷
} |
tab |
name
(optional) selected
(optional) index
(optional) index_x
(optional) index_y
(optional) prefix(暂不支持) |
- |
“切换到电视剧”
request params
{
name: 电视剧
} |
scroll |
(optional) name:
(optional) type:
vertical
horizontal
page |
direction 方向,取值{left/right/up/down}
by 滚动的相对值,可以有正负
to 滚动的绝对值,-1代表滚到底 |
"把电影列表向下滚动"
request params
{
name:电影列表
}
response params
{
direction:{left/right/up/down}
by: {{LONG}},
to: {{LONG}}, //to ==-1的时候,表示“滚到底”
//by和to的单位,暂时都是 屏幕/页,以后有需求再加别的unit
} |
pager |
(optional) name:
(optional) cur_page:
(optional) min
(optional) max
|
by 页码的相对值,可以有正负
to 页码的绝对值,-1代表最后一页(如果没有max的话, 才会返回-1;否则应该返回max-1)
|
"把电影列表翻到最后一页"
request params
{
name:电影列表
}
response params
{
to: {{LONG}},
} |
step |
(optional) name:
(optional) cur_page:
(optional) min
(optional) max
|
by 页码的相对值,可以有正负
to 页码的绝对值,-1代表最后一页(如果没有max的话, 才会返回-1;否则应该返回max-1)
|
"下一步"
request params
{
}
response params
{
by: {{LONG}},
} |
call_phone |
name
(optional) index
|
-
|
"电话第一个"
request params
{
index:1
}
response params
{
call_phone_type:(normal/voice/video)
} |
send_message |
name
(optional) index
|
-
|
"发消息给第一个"
request params
{
index:1
}
|
read_message |
(optional) index
|
-
|
"阅读第一条留言"
request params
{
index:1
} |
view_photo |
(optional) index
|
-
|
"查看第一张照片"
request params
{
index:1
} |
完成开发的app,可以在小度设备上完成测试
在项目build.gradle中新增 maven库依赖
maven{ url 'https://dueros.baidu.com/maven/repository/maven-releases/'}
在app/build.gradle加入依赖
implementation 'com.alibaba:fastjson:1.1.71.android'
implementation 'com.baidu.duer.botsdk:bot-sdk-android:1.32.0@aar'
然后参考以上代码示例进行集成
为便于开发这尽快在本地跑通流程,在DBP创建技能可以直接选则导入技能分享链接,填入:“https://dueros.baidu.com/dbp/main/console?shareCode=FXXs” 可以快速导入demo app对应的BDP技能。