前言

语音识别在现在的APP中是常见的,但是通常小的项目中我们不会去费心思自己去做这一块的业务功能开发,常规的是接入第三方的SDK快速实现功能,比如百度、讯飞之类的,百度语音识别之前我已经写过了,本着雨露均沾的原则的,写这篇讯飞的SDK对接步骤,开始吧~
效果图

点击

识别中,识别到之后

源码在文章最后面

正文

首先呢,你先去注册讯飞的开发者账号,点击讯飞开放平台前往注册,

注册好之后你可以选择实名认证或者不认证都可以,然后登录进入控制台或者我的应用
创建一个应用


填写信息然后提交

点击这个应用名称查看详细信息

右边的是对接过程需要用到的值,APPID用SDK中,APIKey或APISecret适用于WebAPI调用方式,这两者有什么区别呢?SDK的话很好理解,复制一些文件到你的项目中,然后添加依赖,你就可以使用讯飞的SDK中的语音识别功能了,而WebAPI调用顾名思义是通过网络接口携带参数的方式去实现的,需要自己去做网络请求,本文中目前使用SDK的方式进行对接实现功能,如果有想看WebAPI调用方式的请在评论区留言,

OK,现在滑动到下面下载Android SDK

下载到本地,然后解压,打开文件目录如下:

然后就是创建你自己项目了,打开AS

① 配置资源文件

我取名是XFASRDemo,然后Finish,等待项目创建好之后,复制文件中libs里面的三个文件,到项目的libs中


右键Mac.jar添加Add As Library


点击OK添加,添加好之后你的jar包就会有一个三角箭头,可以展开,这个时候你就可以使用里面的方法了。

然后复制资源文件到main下面

② 配置项目

创建SpeechApplication.java

package com.llw.xfasrdemo;import android.app.Application;import com.iflytek.cloud.SpeechUtility;public class SpeechApplication extends Application {@Overridepublic void onCreate() {//   5ef048e1  为在开放平台注册的APPID  注意没有空格,直接替换即可SpeechUtility.createUtility(SpeechApplication.this, "appid=5ef048e1");super.onCreate();}
}

打开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"/>

配置SpeechApplication和注册权限


然后修改app模块下面的build.gradle

 sourceSets {main {jniLibs.srcDirs = ['libs']}}
implementation files('libs/Msc.jar')

改完记得Sync一下

然后修改布局activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:id="@+id/tv_result"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="识别到的内容"android:textColor="#000" /><Buttonandroid:id="@+id/btn_start"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:text="开始识别" />
</LinearLayout>

接下来就是MainActivity了

③ 编码

一、声明变量和初始化

 private static final String TAG = "MainActivity";private SpeechRecognizer mIat;// 语音听写对象private RecognizerDialog mIatDialog;// 语音听写UI// 用HashMap存储听写结果private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();private SharedPreferences mSharedPreferences;//缓存private String mEngineType = SpeechConstant.TYPE_CLOUD;// 引擎类型private String language = "zh_cn";//识别语言private TextView tvResult;//识别结果private Button btnStart;//开始识别private String resultType = "json";//结果内容数据格式

同时你要实现这个点击事件的监听


实现一个方法

 @Overridepublic void onClick(View v) {//写入点击之后处理逻辑}
 @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tvResult = findViewById(R.id.tv_result);btnStart = findViewById(R.id.btn_start);btnStart.setOnClickListener(this);//实现点击监听}

二、动态权限请求

 /*** android 6.0 以上需要动态申请权限*/private void initPermission() {String permissions[] = {Manifest.permission.RECORD_AUDIO,Manifest.permission.ACCESS_NETWORK_STATE,Manifest.permission.INTERNET,Manifest.permission.WRITE_EXTERNAL_STORAGE};ArrayList<String> toApplyList = new ArrayList<String>();for (String perm : permissions) {if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, perm)) {toApplyList.add(perm);}}String tmpList[] = new String[toApplyList.size()];if (!toApplyList.isEmpty()) {ActivityCompat.requestPermissions(this, toApplyList.toArray(tmpList), 123);}}/*** 权限申请回调,可以作进一步处理** @param requestCode* @param permissions* @param grantResults*/@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {// 此处为android 6.0以上动态授权的回调,用户自行实现。}

在onCreate方法中调用

initPermission();//权限请求

三、语音监听

 /*** 初始化监听器。*/private InitListener mInitListener = new InitListener() {@Overridepublic void onInit(int code) {Log.d(TAG, "SpeechRecognizer init() code = " + code);if (code != ErrorCode.SUCCESS) {showMsg("初始化失败,错误码:" + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");}}};/*** 听写UI监听器*/private RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {public void onResult(RecognizerResult results, boolean isLast) {printResult(results);//结果数据解析}/*** 识别回调错误.*/public void onError(SpeechError error) {showMsg(error.getPlainDescription(true));}};/*** 提示消息* @param msg*/private void showMsg(String msg) {Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();}

里面用到一个方法,用于解析监听到的结果

四、数据解析

 /*** 数据解析** @param results*/private void printResult(RecognizerResult results) {String text = JsonParser.parseIatResult(results.getResultString());String sn = null;// 读取json结果中的sn字段try {JSONObject resultJson = new JSONObject(results.getResultString());sn = resultJson.optString("sn");} catch (JSONException e) {e.printStackTrace();}mIatResults.put(sn, text);StringBuffer resultBuffer = new StringBuffer();for (String key : mIatResults.keySet()) {resultBuffer.append(mIatResults.get(key));}tvResult.setText(resultBuffer.toString());//听写结果显示}

里面用到一个JsonParser的工具类,需要手动去创建一个

代码如下:

package com.llw.xfasrdemo;import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;/*** Json结果解析类*/
public class JsonParser {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"));
//              如果需要多候选结果,解析数组其他字段
//              for(int j = 0; j < items.length(); j++)
//              {//                  JSONObject obj = items.getJSONObject(j);
//                  ret.append(obj.getString("w"));
//              }}} catch (Exception e) {e.printStackTrace();} return ret.toString();}public static String parseGrammarResult(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");for(int j = 0; j < items.length(); j++){JSONObject obj = items.getJSONObject(j);if(obj.getString("w").contains("nomatch")){ret.append("没有匹配结果.");return ret.toString();}ret.append("【结果】" + obj.getString("w"));ret.append("【置信度】" + obj.getInt("sc"));ret.append("\n");}}} catch (Exception e) {e.printStackTrace();ret.append("没有匹配结果.");} return ret.toString();}public static String parseLocalGrammarResult(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");for(int j = 0; j < items.length(); j++){JSONObject obj = items.getJSONObject(j);if(obj.getString("w").contains("nomatch")){ret.append("没有匹配结果.");return ret.toString();}ret.append("【结果】" + obj.getString("w"));ret.append("\n");}}ret.append("【置信度】" + joResult.optInt("sc"));} catch (Exception e) {e.printStackTrace();ret.append("没有匹配结果.");} return ret.toString();}public static String parseTransResult(String json,String key) {StringBuffer ret = new StringBuffer();try {JSONTokener tokener = new JSONTokener(json);JSONObject joResult = new JSONObject(tokener);String errorCode = joResult.optString("ret");if(!errorCode.equals("0")) {return joResult.optString("errmsg");}JSONObject transResult = joResult.optJSONObject("trans_result");ret.append(transResult.optString(key));/*JSONArray words = joResult.getJSONArray("results");for (int i = 0; i < words.length(); i++) {JSONObject obj = words.getJSONObject(i);ret.append(obj.getString(key));}*/} catch (Exception e) {e.printStackTrace();}return ret.toString();}
}

五、参数配置

 /*** 参数设置** @return*/public void setParam() {// 清空参数mIat.setParameter(SpeechConstant.PARAMS, null);// 设置听写引擎mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);// 设置返回结果格式mIat.setParameter(SpeechConstant.RESULT_TYPE, resultType);if (language.equals("zh_cn")) {String lag = mSharedPreferences.getString("iat_language_preference","mandarin");Log.e(TAG, "language:" + language);// 设置语言mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");// 设置语言区域mIat.setParameter(SpeechConstant.ACCENT, lag);} else {mIat.setParameter(SpeechConstant.LANGUAGE, language);}Log.e(TAG, "last language:" + mIat.getParameter(SpeechConstant.LANGUAGE));//此处用于设置dialog中不显示错误码信息//mIat.setParameter("view_tips_plain","false");// 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理mIat.setParameter(SpeechConstant.VAD_BOS, mSharedPreferences.getString("iat_vadbos_preference", "4000"));// 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音mIat.setParameter(SpeechConstant.VAD_EOS, mSharedPreferences.getString("iat_vadeos_preference", "1000"));// 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点mIat.setParameter(SpeechConstant.ASR_PTT, mSharedPreferences.getString("iat_punc_preference", "1"));// 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限mIat.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/iat.wav");}

六、代码组装

在onCreate中增加如下代码,进行初始化

     // 使用SpeechRecognizer对象,可根据回调消息自定义界面;mIat = SpeechRecognizer.createRecognizer(MainActivity.this, mInitListener);// 使用UI听写功能,请根据sdk文件目录下的notice.txt,放置布局文件和图片资源mIatDialog = new RecognizerDialog(MainActivity.this, mInitListener);mSharedPreferences = getSharedPreferences("ASR",Activity.MODE_PRIVATE);

然后再onClick中

 @Overridepublic void onClick(View v) {if( null == mIat ){// 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688showMsg( "创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化" );return;}mIatResults.clear();//清除数据setParam(); // 设置参数mIatDialog.setListener(mRecognizerDialogListener);//设置监听mIatDialog.show();// 显示对话框}

最后在onDestory中

 @Overrideprotected void onDestroy() {super.onDestroy();if (null != mIat) {// 退出时释放连接mIat.cancel();mIat.destroy();}}

这样逻辑就很清楚了

七、运行效果图


点击

识别中,识别到之后

APK下载二维码

④ 梳理

从平台创建应用之后的到一个appid,然后新建一个项目,先配置AndroidManifest.xml,配置了静态权限和Application,在Application中对讯飞语音插件进行初始化,这样就可以影响到全局,而不是在某一个Activity的中onCreate进行初始化,当然你也可以这样做。然后初始化控件和讯飞的一些工具类,并实现点击监听,之后进行动态权限的获取,成功之后,进行语音监听(包括UI对话框)的接口实现,在返回值中做数据解析,得到需要的数据显示在页面的TextView上,然后再配置一些需要在调用语音识别之前需要的参数,比如语言类型和结果类型之类的,之后就是点击出现语音识别的UI对话框,当你说完之后会消失,并识别到你说的内容解析显示在页面上。至此,语音识别完成。

尾声

这里无非就是一些感想而已,其实实现功能的方法有很多,文章中只是其中之一而已,欢迎留言讨论,我是初学者-Study,山高水长,后会有期~

项目源码:XFASRDemo

温馨提示:请在自己的手机(真机)上运行,别用Android的虚拟器或者任何其他的模拟器,你会出现如评论区的朋友所遇到相同的问题:“创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化”。原因就是虚拟机cpu是x86的,在讯飞的SDK中没有x86对应的libmsc.so。所以你会报错。但是如果你用真机还是报这个错的话,那你可以理直气壮的去讯飞的官网上提问。让他们开发人员给你解决。

Android 科大讯飞语音识别(详细步骤+源码)相关推荐

  1. Android 百度语音识别(详细步骤+源码)

    前言 因为项目中用到了语音识别的技术,但是项目源码我不能公开,所以,重新写一个简单的集成教程,不喜可不看,不做键盘侠,文明你我他. 效果图 识别结果 最终效果 源码在文章最后,不需要下载积分什么的,哪 ...

  2. 实战 | 用Python和MediaPipe搭建一个嗜睡检测系统 (详细步骤 + 源码)

    导读 本文将使用Python和MediaPipe搭建一个嗜睡检测系统 (包含详细步骤 + 源码). 背景介绍 疲劳驾驶的危害不堪设想,据了解,21%的交通事故都因此而生,尤其是高速路上,大多数车辆都是 ...

  3. 实战 | 基于OpenCV的停车场空余车位实时监测系统(详细步骤 + 源码)

    导  读 本文主要介绍如何使用Python和OpenCV实现一个停车场空余车位实时监测系统,并包含详细步骤和源码. 背景介绍 介绍实现步骤之前,先来看看测试视频(小型停车场实时监控画面): ,时长00 ...

  4. Android 腾讯位置服务使用(详细步骤+源码)

    腾讯位置服务使用 前言 正文 一.注册腾讯位置服务账号 二.创建平台应用Appkey 三.创建并配置AS工程 四.定位 ① 连续定位 ② 单次定位 ③ 后台定位 ④ 地理围栏 五.地图 ① 基础地图 ...

  5. Android 百度语音合成 (含离线、在线、API合成方式,详细步骤+源码)

    百度语音合成 声明 前言 正文 一.创建项目 二.离线语音合成 1. 配置AndroidManifest.xml 2. 配置SDK 3. 离线SDK初始化 4. 导包 5. 运行 三.在线语音合成 - ...

  6. Android 高德地图API(详细步骤+源码)

    高德地图API使用详解 前言 正文 一.创建应用 ① 获取PackageName ② 获取调试版安全码SHA1 ③ 获取发布版安全码SHA1 二.配置Android Studio工程 ① 导入SDK ...

  7. Android 百度文字识别(详细步骤+源码)

    运行效果图 识别到的内容: {"words_result":[{"words":"突然间有想看书的冲动"},{"words&quo ...

  8. 使用Keras和OpenCV实时预测年龄、性别和情绪 (详细步骤+源码)

    来源 | https://towardsdatascience.com/real-time-age-gender-and-emotion-prediction-from-webcam-with-ker ...

  9. 基于OpenCV实现简单人脸面具、眼镜、胡须、鼻子特效(详细步骤 + 源码)

    点击下方卡片,关注"OpenCV与AI深度学习"公众号! 视觉/图像重磅干货,第一时间送达! 导读 本文给大家分享一个基于OpenCV实现简单人脸面具.眼镜.胡须.鼻子特效的实例, ...

  10. OpenCvSharp (C# OpenCV)实现纺织物缺陷检测->脏污、油渍、线条破损(详细步骤 + 源码)

    点击下方卡片,关注" OpenCV与AI深度学习" 视觉/图像重磅干货,第一时间送达! 导读 本文将介绍使用OpenCV实现纺织物缺陷检测(脏污.油渍.线条破损缺陷)的详细步骤 + ...

最新文章

  1. 【yolov4目标检测】(4) opencv+yolov4-tiny 实现选择性目标检测,附python完整代码
  2. fedora上ARM-LINUX-GCC 编译器安装
  3. 【C 语言】文件操作 ( 配置文件读写 | 框架搭建 | 头文件定义 | 头文件导入限制 | 兼容 C++ 语言 | 函数形参输入输出属性注释)
  4. Java培训分享:零基础怎么学习Java?
  5. debug idea js_IntelliJ IDEA 配置chrome插件调试js代码 - 狂奔的熊二 - 博客园
  6. wangEditor-3.1.1 自己扩展的, 扩展图片添加alt标签
  7. Python获取代理IP地址
  8. 微课|中学生可以这样学Python(例5.3):报数游戏
  9. 使用Google的项目(源码)托管服务(转)
  10. 【Linux】解决Wesnoth中文乱码问题
  11. (转)Palantir: 神秘的大数据公司
  12. sql-labs超详细教程
  13. 诺基亚c7微信 服务器忙,诺基亚C7怎么刷机
  14. delphi在linux运行,实现了delphi unigui跑在linux上
  15. Oracle Redo log 状态及工作原理解析
  16. 夏令营一部分数学试题
  17. thinkphp6手册_ThinkPHP6.0完全开发手册(官方版)
  18. PC客户端中的网页----问题集合(未完待续)
  19. 乐优商城之后台管理系统
  20. python画圆形螺旋线_用Python一秒生成复古像素图片

热门文章

  1. 怎么知道他人的 IP
  2. 数据库系统原理——概述
  3. 初识C语言答案,《明解C语言》第1章 初识C语言练习题答案(3页)-原创力文档...
  4. C语言小游戏 |100行代码实现扫雷
  5. 追赶法matlab算法,追赶法matlab程序
  6. win7创建mysql odbc数据源_Win7下如何创建odbc数据源
  7. # 创业计划书-样例参考五千套(一)
  8. live2d_Live2D | CubismSdkForUnity4r.1简介(上)
  9. 【毕业设计】 python小游戏设计 - 走迷宫游戏设计与实现
  10. Python基础语句