当前位置: 代码迷 >> Android >> Android集成讯飞SDK实现语音拨号、话音导航、语音启动应用
  详细解决方案

Android集成讯飞SDK实现语音拨号、话音导航、语音启动应用

热度:50   发布时间:2016-04-28 00:59:40.0
Android集成讯飞SDK实现语音拨号、语音导航、语音启动应用

转载请注明出处:周木水的CSDN博客
http://blog.csdn.net/zhoumushui

科大讯飞语音SDK的语义分析还是挺强大的,可使我们的应用更加强大。
上篇博文介绍了讯飞SDK的一些简单功能:
Android 使用讯飞语音SDK

今天来看看对语义分析结果JSON的解析并处理:

实现语音拨号


首先,我们看看“打电话给张三”这句话在服务器分析之后,传给我们的JSON是什么样的:

{"semantic": {"slots": {"name": "张三"}},"rc": 0,"operation": "CALL","service": "telephone","text": "打电话给张三。"}

所以,我们的思路就是获取到name,然后和联系人ContentProvider中的联系人DisplayName进行逐一匹配。但是要考虑到同音字的问题(例如:“打电话给张晓静”,服务器返回的name是”张小静“,这就没法匹配。)在没有匹配的情况下,我们将name转成拼音,然后再和联系人拼音进行对比即可。

看一下核心代码:

if ("telephone".equals(strService)) {// "operation": "CALL"    String peopleName = jsonObject.getJSONObject("semantic").getJSONObject("slots").getString("name");    String operationStr = jsonObject.getString("operation");    if ("CALL".equals(operationStr)) {        String phoneNum = getContactNumberByName(peopleName);        String phoneCode = "";        try {                phoneCode = jsonObject.getJSONObject("semantic").getJSONObject("slots").getString("code");            } catch (Exception e) {}        if (phoneNum != null & phoneNum.trim().length() > 0) {        String strAnswer = "正在打电话给:" + peopleName;        tvAnswer.setText(strAnswer);        startSpeak(strAnswer);        Uri uri = Uri.parse("tel:" + phoneNum);        Intent intent = new Intent(Intent.ACTION_CALL, uri);        startActivity(intent);        } else if (phoneCode != null& phoneCode.trim().length() > 0) {                String strAnswer = "正在打电话给:" + peopleName;                tvAnswer.setText(strAnswer);                startSpeak(strAnswer);                Uri uri = Uri.parse("tel:" + phoneCode);                Intent intent = new Intent(Intent.ACTION_CALL, uri);                startActivity(intent);            } else {            String phoneNumFromPinYin = getContactNumberByPinYin(PinYinUtil.convertAll(peopleName));            if (phoneNumFromPinYin != null& phoneNumFromPinYin.trim().length() > 0) {            String strAnswer = "正在打电话给:" + peopleName;            tvAnswer.setText(strAnswer);            startSpeak(strAnswer);            Uri uri = Uri.parse("tel:" + phoneNumFromPinYin);            Intent intent = new Intent(Intent.ACTION_CALL, uri);            startActivity(intent);            } else {            String strAnswer = "通讯录中未找到:" + peopleName;            tvAnswer.setText(strAnswer);            startSpeak(strAnswer);                        }                    }                }}



语音导航


这里不考虑”从A到B怎么走(A,B都为异地)“的情况。起点不是当前位置的情况解析方式相同,只是不常用。所以这里的例子起点默认为当前定位位置。
当我们说”导航到深圳北站“时,服务器返回的JSON如下:

{"semantic": {"slots": {"endLoc": {"type": "LOC_POI","poi": "深圳南站","city": "深圳市","cityAddr": "深圳"},"startLoc": {"type": "LOC_POI","city": "CURRENT_CITY","poi": "CURRENT_POI"}}},"rc": 0,"operation": "ROUTE","service": "map","text": "导航到深圳南站。"}

首先我们对JSON进行解析:

if ("map".equals(strService)) {    // operation": "ROUTE"    String endPoiStr = jsonObject.getJSONObject("semantic").getJSONObject("slots").getJSONObject("endLoc").getString("poi");    String endCityStr = jsonObject.getJSONObject("semantic").getJSONObject("slots").getJSONObject("endLoc").getString("city");    String endAddressStr = "";    if ("CURRENT_CITY".equals(endCityStr))    endCityStr = mSharedPreferences.getString("cityName", "未知");}

调用百度地图的导航接口,需要传入起始点的经纬度。当前位置的经纬度是已知的,所以要将目的地的字符串转成经纬度。这就涉及到百度LBS SDK的使用:

{    mEndSearch = GeoCoder.newInstance();    mEndSearch.setOnGetGeoCodeResultListener(new MyOnGetGeoCoderResultListener());    mEndSearch.geocode(new GeoCodeOption().city(endCityStr).address(endPoiStr));    }
    class MyOnGetGeoCoderResultListener implements OnGetGeoCoderResultListener {        @Override        public void onGetGeoCodeResult(GeoCodeResult result) {            // TODO Auto-generated method stub            mEndLatLng = result.getLocation();            if (mEndLatLng != null) {                // 起始点:当前位置                startLat = Double.parseDouble(mSharedPreferences.getString(                        "latitude", "0.0"));                startLng = Double.parseDouble(mSharedPreferences.getString(                        "longitude", "0.0"));                // 目的地                endLat = mEndLatLng.latitude;                endLng = mEndLatLng.longitude;                LatLng startLatLng = new LatLng(startLat, startLng);                LatLng endLatLng = new LatLng(endLat, endLng);                // 构建 导航参数                NaviPara para = new NaviPara();                para.startPoint = startLatLng;                para.startName = "从这里开始";                para.endPoint = endLatLng;                para.endName = "到这里结束";                try {                    BaiduMapNavigation.openBaiduMapNavi(para,                            getApplicationContext());                } catch (BaiduMapAppNotSupportNaviException e) {                    e.printStackTrace();                }            }        }        @Override        public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {        }    }



语音启动应用


当我们说”打开百度地图“时,服务器返回的JSON是:

{"semantic": {"slots": {"name": "百度地图"}},"rc": 0,"operation": "LAUNCH","service": "app","text": "打开百度地图。"}

和语音拨号类似,我们可以获取到应用的名称,然后和ResolveInfo中应用的名称Label进行比对,如果匹配,则拿到包名,然后进行启动。

注意:要考虑到应用名称为非中文的情况。(比如我们说”启动QQ“,但讯飞识别的是”qq“,如果简单粗暴的进行String的equals比较,则会匹配失败。这时候需要将应用名称与Label都转成大写或小写。)

if ("app".equals(strService)) {    // "operation": "LAUNCH",    String appName = jsonObject.getJSONObject("semantic").getJSONObject("slots").getString("name");    String operationStr = jsonObject.getString("operation");    if ("LAUNCH".equals(operationStr)) {        String packageName = getAppPackageByName(appName);        Toast.makeText(getApplicationContext(),packageName, Toast.LENGTH_SHORT).show();        if (!"com.tchip.carlauncher".equals(packageName)) {            String strAnswer = "正在启动:"+ appName;            tvAnswer.setText(strAnswer);            startSpeak(strAnswer);            startAppbyPackage(packageName);        } else {            String strAnswer = "未找到应用:"+ appName;            tvAnswer.setText(strAnswer);            startSpeak(strAnswer);        }    }} 

转载请注明出处:周木水的CSDN博客
http://blog.csdn.net/zhoumushui

  相关解决方案