1、账号准备工作

首先要有一个讯飞的账号啦,为后面申请APPID、APPKey等东西做准备。顺带一提:讯飞对不同认证类型用户开

放的SDK的使用次数是有不同的,详情如下图。

账号申请完成后,需要去你自己的控制台注册你的应用,同时也可以看到你的应用对应的 APPID 等属性,开通的功能,调用量剩余次数等信息。

本文介绍的是Android SDK的接入,这是Android SDK的下载地址,可以根据项目的具体需求具体分析。

2、SDK集成准备工作

如果参照官方文档中或者官方DEMO的做法,需要把对应架构的文件拷贝到 Android工程的libs目录下 。

而官方提供的DEMO中,它只拷贝了armeabi-v7a架构。如下图所示(我信了它的邪,在我第一次接入时,就因为参考了官方DEMO只导入了armeabi-v7a架构,导致出了一大堆毛病?)

为了避免这个坑,我的建议是:把提供的架构都拷贝到工程里。(有特殊设备需求的除外)

然后在build.gradle文件中,添加SDK的依赖

    implementation files('libs/Msc.jar')

如果将SDK导入到lib文件夹后,可能还会有无法识别的错误。

可以试下在build.gradle(app)中注释掉以下的代码(玄学操作~~),再继续排查。

//        ndk {
// //选择要添加的对应cpu类型的.so库。
// abiFilters 'armeabi-v7a', 'armeabi'
// } // sourceSets {
// main{
// jniLibs.srcDirs = ['libs']
// }
// }

3、在 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" />

不过,静态申请了权限,还不够哦。对于现在的手机,很大部分都已经是Android版本678910的了,应用是需要动态申请权限的,得让用户确认同意了,APP才可以使用这些权限。

动态申请权限的方法有很多,也有很多开源的项目,这里就不做介绍了。

4、SDK初始化

SDK初始化建议放在程序入口处(如Application、Activity的onCreate方法),非常简单,就一行语句。

初始化代码如下:

//将“1234567”替换成您申请的APPID
SpeechUtility.createUtility(context, SpeechConstant.APPID +"=1234567");

注意:SpeechConstant.APPID +"=1234567" 采用的是拼接的方式,所以不可以在“=”与appid之间添加任何空字符或者转义符。

5、调用语音听写功能

最重要的来了,前面铺垫这么久,就是为了能调用它的语音听写啊。

离线听写方式,需要购买且下载特定的离线识别SDK,故这里使用的是在线听写。

在线听写的SDK,提供了两种识别方式,分别是带语音对话框识别和无UI识别。

一.无UI识别

//初始化识别无UI识别对象
//使用SpeechRecognizer对象,可根据回调消息自定义界面--自己的语音识别UI
mIat = SpeechRecognizer.createRecognizer(IatDemo.this, mInitListener); //设置语法ID和 SUBJECT 为空,以免因之前有语法调用而设置了此参数;或直接清空所有参数,具体可参考 DEMO 的示例。
mIat.setParameter( SpeechConstant.CLOUD_GRAMMAR, null );
mIat.setParameter( SpeechConstant.SUBJECT, null );
//设置返回结果格式,目前支持json,xml以及plain 三种格式,其中plain为纯听写文本内容
mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");
//此处engineType为“cloud”
mIat.setParameter( SpeechConstant.ENGINE_TYPE, engineType );
//设置语音输入语言,zh_cn为简体中文
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
//设置结果返回语言
mIat.setParameter(SpeechConstant.ACCENT, "mandarin");
// 设置语音前端点:静音超时时间,单位ms,即用户多长时间不说话则当做超时处理
//取值范围{1000~10000}
mIat.setParameter(SpeechConstant.VAD_BOS, "4000");
//设置语音后端点:后端点静音检测时间,单位ms,即用户停止说话多长时间内即认为不再输入,
//自动停止录音,范围{0~10000}
mIat.setParameter(SpeechConstant.VAD_EOS, "1000");
//设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
mIat.setParameter(SpeechConstant.ASR_PTT,"1");
//开始识别,并设置监听器
mIat.startListening(mRecogListener);

二.带语音对话框识别(SDK自带)

// 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer
// 使用UI听写功能,请根据sdk文件目录下的notice.txt,放置布局文件和图片资源
mIatDialog = new RecognizerDialog(IatDemo.this, mInitListener); //以下为dialog设置听写参数
mIatDialog.setParameter(SpeechConstant.RESULT_TYPE, "json");
//设置语音输入语言,zh_cn为简体中文
mIatDialog.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
//设置结果返回语言
mIatDialog.setParameter(SpeechConstant.ACCENT, "mandarin");
// 设置语音前端点:静音超时时间,单位ms,即用户多长时间不说话则当做超时处理
//取值范围{1000~10000}
mIatDialog.setParameter(SpeechConstant.VAD_BOS, "4500");
//设置语音后端点:后端点静音检测时间,单位ms,即用户停止说话多长时间内即认为不再输入,
//自动停止录音,范围{0~10000}
mIatDialog.setParameter(SpeechConstant.VAD_EOS, "1500");
//开始识别并设置监听器
mIatDialog.setListener(mRecognizerDialogListener); //开始识别并设置语音UI监听器
mIatDialog.setListener(mRecognizerDialogListener);
//显示听写对话框,show方法实际是内部调用无UI识别方式
mIatDialog.show();

重点来了,也是很多人很困扰的一步,官方文档的说法是使用这个SDK自带的语音识别对话框,需要把对应的布局文件和图片资源放入工程中。然而,很多人这样做了之后, mIatDialog.show(); 调用了还是会出现空指针的异常。。例如:?

java.lang.NullPointerException
at com.iflytek.cloud.ui.a.a(Unknown Source)
at com.iflytek.cloud.ui.RecognizerDialog.setParameter(Unknown Source)
atcom.example.mediaplayer.activity.SearchActivity.setParam(SearchActivity.java:111)
at com.example.mediaplayer.activity.SearchActivity.onClick(SearchActivity.java:86)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5045)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)

解决方法,如下:

首先,在asset文件内,放入所需的资源。注意:asset文件夹的位置,是要在src/main/ 的下一级,然后在与

asset文件夹同级的地方创建 jniLibs 文件夹,把 libs/文件夹的对应SDK文件拷贝到 jniLibs 中,如图:

同时检查下,SDK初始化的 APPId 有无出错的可能。

获取数据

解决了空指针的问题后,接下来调用 show 方法,就可以在自定义的监听器里愉快地获取到返回的听写数据了

 //创建语音识别UI对话框
mIatDialog = new RecognizerDialog(getActivity(), searchViewModel.mInitListener); /**
* 初始化听写事件监听器。
*/
public InitListener mInitListener = new InitListener() { @Override
public void onInit(int code) {
if (code != ErrorCode.SUCCESS) {
//Todo
}
}
};
/**
* 听写UI监听器 讯飞
*/
public RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() { /**
* 接收语音听写回调信息
* @param recognizerResult 回调结果
* @param b 是否翻译
*/
@Override
public void onResult(com.iflytek.cloud.RecognizerResult recognizerResult, boolean b) {
//返回的数据
String data = recognizerResult.getResultString();
}
/**
* 识别回调错误.
*/
public void onError(SpeechError error) {
if(error.getErrorCode() == 14002) {
//Todo
} else {
//Todo
}
} };

修改默认对话框的文字

//动态更换了讯飞自带对话框的底部文字,必须在dialog的show执行后更换,否则空指针报错
TextView recorderDialogTextView = (TextView) mIatDialog.getWindow().getDecorView().findViewWithTag("textlink"); recorderDialogTextView.setText(R.string.recorder_dialog_textview_text);

返回的听写数据实例,用于创建实体类:

{
"sn": 1,
"ls": true,
"bg": 0,
"ed": 0,
"ws": [
{
"bg": 0,
"cw": [
{
"w": "今天",
"sc": 0
}
]
},
{
"bg": 0,
"cw": [
{
"w": "的",
"sc": 0
}
]
},
{
"bg": 0,
"cw": [
{
"w": "天气",
"sc": 0
}
]
},
{
"bg": 0,
"cw": [
{
"w": "怎么样",
"sc": 0
}
]
},
{
"bg": 0,
"cw": [
{
"w": "。",
"sc": 0
}
]
}
]
}

注意:若在SDK中开通了 动态修正的功能,返回的数据会出现格式不一致的情况。官方的说法如下:

动态修正:
  • 未开启动态修正:实时返回识别结果,每次返回的结果都是对之前结果的追加;
  • 开启动态修正:实时返回识别结果,每次返回的结果有可能是对之前结果的的追加,也有可能是要替换之前某次返回的结果(即修正);
  • 开启动态修正,相较于未开启,返回结果的颗粒度更小,视觉冲击效果更佳;
  • 使用动态修正功能需到控制台-流式听写-高级功能处点击开通,并设置相应参数方可使用,参数设置方法:mIat.setParameter(“dwa”, “wpgs”); ;
  • 动态修正功能仅 中文 支持;
  • 未开启与开启返回的结果格式不同,详见下方;

若开通了动态修正功能并设置了dwa=wpgs(仅中文支持),会有如下字段返回:

参数 类型 描述
pgs string 开启wpgs会有此字段 取值为 “apd"时表示该片结果是追加到前面的最终结果;取值为"rpl” 时表示替换前面的部分结果,替换范围为rg字段
rg array 替换范围,开启wpgs会有此字段 假设值为[2,5],则代表要替换的是第2次到第5次返回的结果

PS:一般项目中的语音听写需求,完全可以不使用动态修正功能,但若要使用同步显示语音识别结果或者比较需要比较精准的结果,可以考虑使用此功能。

总结

讯飞语音听写SDK,坑点不少,但是都不是很难,还是适项目快速接入语音听写需求的。。?

如果要更多操作和功能,请参考讯飞语音听写SDK官方文档

Android 讯飞语音听写SDK快速接入(附空指针解决和修改对话框文字方法)的更多相关文章

  1. Android讯飞语音云语音听写学习

    讯飞语音云语音听写学习         这几天两个舍友都买了iPhone 6S,玩起了"Hey, Siri",我依旧对我的Nexus 5喊着"OK,Google" ...

  2. android讯飞语音开发常遇到的问题

    场景:android项目中共使用了3个语音组件:在线语音听写.离线语音合成.离线语音识别 11208:遇到这个错误,授权应用失败,先检查装机量(3台测试权限),以及appid的申请时间(35天期限), ...

  3. 讯飞语音唤醒SDK集成流程

    唤醒功能,顾名思义,通过语音,唤醒服务,做我们想做的事情. 效果图(开启应用后说讯飞语音或者讯飞语点唤醒) 源码下载 地址:http://download.csdn.net/detail/q48788 ...

  4. Android 讯飞语音之语音合成(在线有声朗读)

    原文:http://www.cnblogs.com/scetopcsa/p/3845427.html 在线语音合成的使用方法: 首先下载相关的sdk,这个网址里有多种版本,我选择的Android. h ...

  5. Android自带语音播报+讯飞语音播报封装(直接用)

    一.Android自带的语音播报 1.查看是否支持中文,在测试的设备中打开‘设置’ -->找到 '语言和输入法'-->查看语音选项,是否支持中文,默认仅支持英文. 使用如下: public ...

  6. cocos2dx实现android的对讯飞语音的合成(语言朗读的实现)

    事实上非常easy,只是有些细节须要注意. 关于讯飞语音在android上的应用,大家须要自己去下载SDK,然后依照讯飞语音提供的api在自己的android的Demo上执行成功,那东西也相当的简单. ...

  7. 关于讯飞语音SDK开发学习

    前奏,浑浑噩噩已经工作一年多,这一年多收获还是挺多的.逛园子应该有两年多了,工作后基本上是天天都会来园子逛逛,园子 里还是有很多牛人写了一些不错的博客,帮我解决很多问题.但是一直没写过博客,归根到底一 ...

  8. 继《关于讯飞语音SDK开发学习》之打包过程中遇到小问题

    关于讯飞语音SDK开发学习 使用vs自带打包,具体怎么操作就不说了,网上关于这方面的资料挺多的.例如:winform 打包部署,VS2010程序打包操作(超详细的),关键是桌面上创建快捷方式中的&qu ...

  9. UNITY 接讯飞语音过程总结

    11:13 2017/3/141,安装问题:JDK与ECLIPSE位数一定要对应,32位对64位会出现 java was returned ....code 13的弹框错误.版本号可以不一致.2,EC ...

随机推荐

  1. NullPointerException的处理新方式,Java14真的太香了

    在Java语言中,处理空指针往往是一件很头疼的事情,一不小心,说不定就搞出个线上Bug,让你的绩效考核拿到3.25.最近新出的Java14,相信大家都有所耳闻,那么今天就来看看,面对NullPoint ...

  2. MySQL REPLACE INTO 的使用

    前段时间写游戏合服工具时出现过一个问题,源DB和目标DB角色表中主键全部都不相同,从源DB取出玩家数据再使用 replace into 写入目标DB中,结果总有几条数据插入时会导致目标DB中原有的角色 ...

  3. springboot项目war包部署及出现的问题Failed to bind properties under 'mybatis.configuration.mapped-statements[0].

    1.修改pom文件 修改打包方式 为war: 添加tomcat使用范围,provided的意思即在发布的时候有外部提供,内置的tomcat就不会打包进去 <groupId>com.scho ...

  4. Html5移动端弹幕动画实现示例代码

    已知20条内容要有弹幕效果,分成三层,速度随机. 先来看看效果: 所以这里不考虑填写生成的.只是一个展现的效果. 如果要看填写生成的,请不要浪费Time 思路 把单个内容编辑好,计算自身宽度,确定初始 ...

  5. python这门语言为什么要起这个名字

    我只是一只可爱的小虫 前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:Liz喵 PS:如有需要Python学习资料的小 ...

  6. day18作业

    作业: # 1.编写课上讲解的有参装饰器准备明天默写 def auth(file_type): def outer(func): def inter(*args,**kwargs): if file_ ...

  7. Laravel路由不生效,除了首页全部404解决方案Nginx环境

    原因: 请求根目录/ (http://www.xxx.com/public/),会请求public/index.php 输入其他路由地址时,会把你的请求定位到:http://www.xxx.com/i ...

  8. JS-Array-新增方法

    1. filter( ) var arr = [5,4,3,2,1]; newarr = arr.filter((item)=>{ return item<3 }) ;  // => ...

  9. [linux] 小问题:管道符,换行问题等;[nginx]启动,重启,关闭命令;以及升级nginx切换命令

    Lniux换行问题 后面回车不会马上执行本条命令而是换行继续. : 是运行完前面就继续后面的, && 同样是前面正确就运行后面, || 是前面运行不正确就运行后面. | 管道符“|”将 ...

  10. [GO] mac安装GO 初次尝试

    其实试了好多方法,我用的是下面这种方法,简单快捷! 安装homebrew 在终端输入命令 ruby -e "$(curl -fsSL https://raw.githubuserconten ...