前言

最近需要对接语音识别业务,毕竟现在是AI时代,一个产品如果能通过AI能力给用户带来全新的体验,也是很值得尝试的。技术对接上选择的是科大讯飞开放平台,也算是国内最早一批做语音识别的企业了,文档方面都比较全面,对接起来也很方便。

技术基础

开发技术栈为Cordova+Angular+Ionic,这篇分享会介绍如何从头开始创建Cordova插件,并实现科大讯飞Android sdk与App端的数据交互。

Apache Cordova是一个开源的移动开发框架。允许你用标准的web技术——HTML5,CSS3和JavaScript做跨平台开发。 应用在每个平台的具体执行被封装了起来,并依靠符合标准的API绑定去访问每个设备的功能,比如说:传感器、数据、网络状态等。

在继续阅读之前,应该确保你有通过Cordova创建并打包一个简单Hybrid App的经验,感兴趣的童鞋可以到Ionic官网和Cordova官网学习下。

创建Cordova插件

全局安装plugman

plugman用于创建Cordova插件,在项目目录下执行cnpm i -g plugman

创建插件

创建一个插件并添加android平台,并生成package.json,插件名xFeiVoice,插件idcom.qinsilk.xFeiVoice,版本号为0.01

plugman create --name xFeiVoice --plugin_id com.qinsilk.xFeiVoice --plugin_version 0.0.1
cd xFeiVoice
plugman createpackagejson ./
plugman platform add --platform_name android
复制代码

创建成功可以看到对应目录如下

  • src目录存放原生代码,此处为java文件
  • www目录存放js暴露给设备的接口,如下
var exec = require('cordova/exec');exports.coolMethod = function (arg0, success, error) {exec(success, error, 'xFeiVoice', 'coolMethod', [arg0]);
};
复制代码

此时我们做下修改,让参数名跟业务命名更加相关。

var exec = require('cordova/exec');exports.record = function (arg0, success, error) {exec(success, error, 'xFeiVoice', 'record', [arg0]);
};
复制代码

安装插件

执行cordova plugin add xFeiVoice,再执行cordova plugin ls可以查看当前App安装的插件。

此时用Android Studio打开项目,可以看到这个插件已经添加成功。 到这里我们的准备工作就完成了。

对接语音识别

导入sdk

Android sdk可以去科大讯飞开放平台下载。将在官网下载的Android SDK 压缩包中libs目录下所有子文件拷贝至Android工程的libs目录下。如下图所示:

添加权限

在工程 AndroidManifest.xml 文件中添加如下权限:

<!--连接网络权限,用于执行云端语音能力 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--读取网络信息状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--获取当前wifi状态 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--允许程序改变网络连接状态 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<!--读取手机信息权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--读取联系人权限,上传联系人需要用到此权限 -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!--外存储写权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--外存储读权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--配置权限,用来记录应用配置信息 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<!--手机定位信息,用来为语义等功能提供定位,提供更精准的服务-->
<!--定位信息是敏感信息,可通过Setting.setLocationEnable(false)关闭定位请求 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--如需使用人脸识别,还要添加:摄相头权限,拍照需要用到 -->
<uses-permission android:name="android.permission.CAMERA" />
复制代码

初始化语音识别对象

此处调用的是60秒语音听写功能。excute是在开发插件时,用户的自定义方法,当页面调用插件时系统首先将会运行此方法。

@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {this.callbackContext = callbackContext;if (action.equals("record")) {// 初始化语音识别对象SpeechUtility.createUtility(cordova.getActivity(), "appid=yourAppid,force_login=true");// 使用SpeechRecognizer对象,可根据回调消息自定义界面;mIat = SpeechRecognizer.createRecognizer(cordova.getActivity(), mInitListener);// 设置参数setParam();// 监听事件mIat.startListening(mRecognizerListener);return true;}return false;
}
复制代码

初始化监听器

private InitListener mInitListener = new InitListener() {@Overridepublic void onInit(int code) {Log.d(LOG_TAG, "SpeechRecognizer init() code = " + code);if (code != ErrorCode.SUCCESS) {Log.d(LOG_TAG, "初始化失败,错误码:" + code);}}
};
复制代码

设置参数

public void setParam() {// 清空参数mIat.setParameter(SpeechConstant.PARAMS, null);// 设置听写引擎mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);// 设置返回结果格式mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");// 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理mIat.setParameter(SpeechConstant.VAD_BOS, "4000");// 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音mIat.setParameter(SpeechConstant.VAD_EOS, "1000");// 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点mIat.setParameter(SpeechConstant.ASR_PTT, "0");// 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限// 注:AUDIO_FORMAT参数语记需要更新版本才能生效mIat.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/iat.wav");
}
复制代码

识别监听器

private RecognizerListener mRecognizerListener = new RecognizerListener() {@Overridepublic void onVolumeChanged(int volume, byte[] data) {// showTip("当前正在说话,音量大小:" + volume);Log.d(LOG_TAG, "返回音频数据:"+data.length);}@Overridepublic void onResult(final RecognizerResult result, boolean isLast) {//此处有坑,isLast为true时会返回标点符号if (null != result && !isLast) {String text = parseIatResult(result.getResultString());JSONObject obj = new JSONObject();try {obj.put("searchText", text);} catch (JSONException e) {Log.d(LOG_TAG, "This should never happen");}if( null != mIat ){// 退出时释放连接mIat.cancel();mIat.destroy();}getSearchText(obj);} else {Log.d(LOG_TAG, "recognizer result : null");}}@Overridepublic void onEndOfSpeech() {// 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入Log.d(LOG_TAG, "结束说话");}@Overridepublic void onBeginOfSpeech() {// 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入Log.d(LOG_TAG, "开始说话");}@Overridepublic void onError(SpeechError error) {Log.d(LOG_TAG, "onError Code:"  + error.getErrorCode());}@Overridepublic void onEvent(int eventType, int arg1, int arg2, Bundle obj) {// 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因// 若使用本地能力,会话id为null}};
复制代码

处理结果并返回App端

// 处理结果
public static String parseIatResult(String json) {StringBuffer ret = new StringBuffer();try {JSONTokener tokener = new JSONTokener(json);JSONObject joResult = new JSONObject(tokener);JSONArray words = joResult.getJSONArray("ws");for (int i = 0; i < words.length(); i++) {// 转写结果词,默认使用第一个结果JSONArray items = words.getJSONObject(i).getJSONArray("cw");JSONObject obj = items.getJSONObject(0);ret.append(obj.getString("w"));}} catch (Exception e) {e.printStackTrace();}return ret.toString();
}
//将结果通过callbackContext返回App端
public void getSearchText(JSONObject obj) {this.callbackContext.success(obj);
}
复制代码

App端调用sdk并监听数据返回

//语音识别
$scope.record = function () {if (window.cordova && window.cordova.plugins) {if(!$scope.recording){//调用sdkcordova.plugins.xFeiVoice.record({}, function (result) {if(result){//返回识别结果$scope.search.goodKey = result.searchText;$scope.openModal();$scope.recording = false;}console.log('success');}, function (result) {console.log('fail');});}else{//$scope.recordMedia.stopRecord();}$scope.recording = !$scope.recording;}
};
复制代码

结语

插件代码我已经上传到github了,有需要的可以clone。走过路过给个star吧~

让你的Hybrid App听懂你的话(Android篇)相关推荐

  1. native app 集成 cocos-2dx-js 3.11 (Android篇)

    接上篇,android的集成相对麻烦一些,其中涉及到修改引擎底层功能,以下只记录一些其过程中关键步骤,有时间在写ndkgdb debug问题定位处理等等填坑过程. 1.添加引擎java部分 2.添加编 ...

  2. 开发Hybrid App的技术选型

    一.前言 如果我们把Hybrid App理解为运行在android或者ios以及其他移动终端设备上的应用,也可以叫做H5 APP,这种开发应用的模式结合web开发技术与Native开发的部分技术,通常 ...

  3. 修图动口不动手,有人把StyleGAN和CLIP组了个CP,能听懂修图指令那种

    点击上方,选择星标或置顶,不定期资源大放送! 阅读大概需要5分钟 Follow小博主,每天更新前沿干货 「求帮忙把背景 P 成五彩斑斓的黑,可以吗?」 有人认为,自然语言将是软件的下一代接口:你有什么 ...

  4. 让机器听懂人话的自然语言处理技术究竟神奇在哪里?

    https://www.toutiao.com/a6680059274095231501/ 一提到"AI"人工智能,很多人脑袋中就会自动冒出"科幻"电影中变幻莫 ...

  5. 人工智能时代,如何让机器狗听懂你说的话?

    [引子]我的专辑<DuerOS 的AI 实战>涵盖了DuerOS应用中较多方向的内容,有点有面,已经有39篇文字,本文是第40篇.四十不惑,如果读者目前还无法掌握DuerOS的应用全貌,或 ...

  6. Hybrid App开发实战

    Hybrid App开发实战 [引言]近年来随着移动设备类型的变多,操作系统的变多,用户需求的增加,对于每个项目启动前,大家都会考虑到的成本,团队成员,技术成熟度,时间,项目需求等一堆的因素.因此,开 ...

  7. 混合开发Hybrid App为何成为热门?

    纵观当前的移动开发,混合开发(Hybird App)的热度日益上升,那么导致这一趋势的是何原因呢? 实际上,除了混合开发,移动端的开发方式还有纯原生(Native App)和网页应用(Web App) ...

  8. Hybrid App 发展史

    目录 1 概述 2 Cordova 平台 3 Web 发展史 3.1 静态网页 3.2 动态网页 3.3 客户端异步交互 3.4 开发效率提速阶段 3.5 移动平台 4 Hybrid App 分类一 ...

  9. AI能听懂你的情绪了,人机交互会变得更好吗?

    作者:小豪来源:脑极体(ID:unity007) 第一次使用手机语音助手的时候,这个令我新奇不已的玩意儿,总是会在我兴冲冲地问一个问题之后,令人失望地回答一句:"我好想听不懂你在说什么--& ...

  10. 「经济理财」32堂你能听懂的理财课

    之前学了一下基金投资课程,作为以后财富管理的积累,可以出门右转看「银行螺丝钉的基金投资课」.但还是觉得应该系统了解一下理财,从小白到理财达人,我需要半年来学习和实践,比较好的是接触到简七理财,结合简七 ...

最新文章

  1. 【opencv系列01】OpenCV4.X介绍与安装
  2. Java实现单链表的反转
  3. JavaScript操作DOM对象
  4. PyTorch-图像分类演示
  5. 并发编程中的重重量级模型和轻量级模型
  6. [Python]学习基础篇:面向对象编程
  7. oracle10g最快安装教程,史上最详细Oracle 10g安装教程
  8. 编译原理-陈火旺-第三版-课后习题第八章123题
  9. 锐捷交换机虚拟化配置
  10. artifactory 误删除恢复
  11. 计算机设备运行频率单位,计算机常见计量单位解析
  12. 戴尔7040linux改装win7,戴尔OptiPlex 7040台式机win10怎么改win7
  13. 超详细dns劫持解决办法分享
  14. Error while extracting response for type
  15. 每日分享 环境报错:Exception in thread “main“ java.lang.RuntimeException: Cannot create staging directory
  16. Python读取和写入excel文件
  17. 超微服务端重装系统简要记录
  18. DataStream API【3】
  19. 安卓和苹果上线流程:
  20. UTXO:未使用的交易输出

热门文章

  1. 我也是不得不说我的学习能力下降了,这两天都没有完成一个模块
  2. 基于PCA的特征提取
  3. ModBus通信协议的【Modbus RTU 协议使用汇总】
  4. 【1.0】忘记mysql 密码 如何修改之后
  5. Effective C++ 读书笔记之Part6.Inheritance and Object-Oriented Design
  6. 配置linux danted socks服务
  7. 如何让用户留在生态系统里?向苹果学习!【转载】
  8. 【codevs5037】线段树练习4加强版
  9. QueryRunner类常用的方法
  10. 仿写京东商品详情页面