在科大讯飞开放平台——语音听写接口的使用这篇文章里介绍了科大讯飞语音听写接口的简单使用方法,但是在实际开发中发现仅仅那样做在使用起来还是不方便,于是想到把语音听写接口的调用、Json数据解析、听写结果的处理等操作进行封装,使用异步回调的方式进行调用,这样在使用到语音听写的地方只需创建一个监听接口并重写语音识别返回结果的处理方法即可。梳理了一下步骤如下:
(一)前期准备工作
注:将获取到的AppId
存到一个常量类里,后面便于管理:
public class GlobalConfig {
// 科大讯飞语音SDK AppID
public static final String IFLY_VOICE_SDK_APP_ID = "570657ad";
}
(二)封装工具类
创建用GSON解析Json数据的通用工具类GsonUtil,用于为解析语音听写服务器返回的Json格式数据做准备:
import java.util.ArrayList;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
/*
* 封装的GSON解析工具类,提供泛型参数方法
*
*/
public class GsonUtil {
// 将单条Json数据解析成相应的映射对象
public static <T> T parseJsonWithGson(String jsonData, Class<T> type) {
Gson gson = new Gson();
T result = gson.fromJson(jsonData, type);
return result;
}
// 将Json数组解析成相应的映射对象列表
public static <T> List<T> parseJsonArrayWithGson(String jsonData,
Class<T> type) {
Gson gson = new Gson();
List<T> result = new ArrayList<T>();
// 下面这句因为泛型在编译期类型会被擦除,从而导致如下错误:
// java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap
// cannot be cast to DictationResult
// List<T> result = gson.fromJson(jsonData, new TypeToken<List<T>>() {
// }.getType());
// 正确写法
JsonArray array = new JsonParser().parse(jsonData).getAsJsonArray();
for (final JsonElement elem : array) {
result.add(new Gson().fromJson(elem, type));
}
return result;
}
}
(三)创建语音听写结果解析工具类
创建专门解析语音听写结果Json数据的工具类DictationJsonParseUtil,用于解析科大讯飞语音听写服务器返回的Json数据:
import java.util.List;
/**
* 用于解析科大讯飞语音听写服务器返回的Json数据
*
* 语音识别结果Json数据格式:
* {"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}]}]}
*/
public class DictationJsonParseUtil {
// 解析服务器返回的语音听写结果Json格式数据的静态方法,返回值为语音的字符串
public static String parseJsonData(String jsonDataStr) {
String speechStr = "";
List<DictationResult> resultList = GsonUtil.parseJsonArrayWithGson(
jsonDataStr, DictationResult.class);
for (int i = 0; i < resultList.size() - 1; i++) { // 这里减1是因为最后有一组作为结尾的标点符号数据,要舍去
speechStr += resultList.get(i).toString();
}
return speechStr;
}
}
// 语音听写结果类
class DictationResult {
private String sn;
private String ls;
private String bg;
private String ed;
private List<Words> ws;
public static class Words {
private String bg;
private List<Cw> cw;
public static class Cw {
private String w;
private String sc;
public String getW() {
return w;
}
public void setW(String w) {
this.w = w;
}
public String getSc() {
return sc;
}
public void setSc(String sc) {
this.sc = sc;
}
@Override
public String toString() {
return w;
}
}
public String getBg() {
return bg;
}
public void setBg(String bg) {
this.bg = bg;
}
public List<Cw> getCw() {
return cw;
}
public void setCw(List<Cw> cw) {
this.cw = cw;
}
@Override
public String toString() {
String result = "";
for (Cw cwTmp : cw) {
result += cwTmp.toString();
}
return result;
}
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getLs() {
return ls;
}
public void setLs(String ls) {
this.ls = ls;
}
public String getBg() {
return bg;
}
public void setBg(String bg) {
this.bg = bg;
}
public String getEd() {
return ed;
}
public void setEd(String ed) {
this.ed = ed;
}
public List<Words> getWs() {
return ws;
}
public void setWs(List<Words> ws) {
this.ws = ws;
}
@Override
public String toString() {
String result = "";
for (Words wsTmp : ws) {
result += wsTmp.toString();
}
return result;
}
}
(四)创建DictationListener监听类
创建语音听写结果监听接口DictationListener,提供一个onDictationListener(String dictationResultStr)
方法,调用方可以重写该方法,对语音听写结果进行其他操作。
/**
* 科大讯飞语音解析结果返回监听接口
*
*/
public interface DictationListener {
public abstract void onDictationListener(String dictationResultStr);
}
(五)创建DictationUtil类
创建DictationUtil类,其showDictationDialog方法会弹出语音听写Dialog窗口,并对语音返回结果进行解析得到最终结果,最后用onDictationListener接口来将最终结果传送给调用方。
import android.content.Context;
import com.easydo.constant.GlobalConfig;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;
/**
* 语音听写工具类,用于弹出语音听写Dialog进行听写
*
*/
public class DictationUtil {
private static final String DICTATION_APPID = GlobalConfig.IFLY_VOICE_SDK_APP_ID;
private static SpeechRecognizer mIat;
private static RecognizerDialog iatDialog;
private static String dictationResultStr;
private static String finalResult;
public static void showDictationDialog(final Context context,
final DictationListener listener) {
// 初始化语音配置
initConfig(context);
// 开始听写
iatDialog.setListener(new RecognizerDialogListener() {
@Override
public void onResult(RecognizerResult results, boolean isLast) {
if (!isLast) {
dictationResultStr += results.getResultString() + ",";
} else {
dictationResultStr += results.getResultString() + "]";
finalResult = DictationJsonParseUtil
.parseJsonData(dictationResultStr);
listener.onDictationListener(finalResult);
}
}
@Override
public void onError(SpeechError error) {
error.getPlainDescription(true);
}
});
// 开始听写
iatDialog.show();
}
private static void initConfig(Context context) {
dictationResultStr = "[";
finalResult = "";
// 语音配置对象初始化
SpeechUtility.createUtility(context, SpeechConstant.APPID + "="
+ DICTATION_APPID);
// 1.创建SpeechRecognizer对象,第2个参数:本地听写时传InitListener
mIat = SpeechRecognizer.createRecognizer(context, null);
// 交互动画
iatDialog = new RecognizerDialog(context, null);
// 2.设置听写参数,详见《科大讯飞MSC API手册(Android)》SpeechConstant类
mIat.setParameter(SpeechConstant.DOMAIN, "iat"); // domain:域名
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
mIat.setParameter(SpeechConstant.ACCENT, "mandarin"); // mandarin:普通话
}
}
(六)最终调用
最后就是在需要语音听写的地方进行调用了,调用起来很简单,只需调用DictationUtil类的静态方法showDictationDialog
,第一个参数传入Context,第二个参数创建DictationListener匿名内部类,重写其onDictationListener
方法,在该方法中对语音听写最终结果进行处理即可(比如为EditText设置文本等)。
import com.easydo.util.DictationListener;
import com.easydo.util.DictationUtil;
import com.jiayongji.easydo.R;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ImageButton;
public class CreateScheduleActivity extends BaseActivity implements
OnClickListener {
// 日程内容et
private EditText createScheduleContentEt;
// 日程内容语音听写ib
private ImageButton createScheduleContentDictationIb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_schedule);
createScheduleContentEt = (EditText) findViewById(R.id.create_schedule_content_et);
createScheduleContentDictationIb = (ImageButton) findViewById(R.id.create_schedule_content_dictation_ib);
createScheduleContentDictationIb.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.create_schedule_content_dictation_ib:
DictationUtil.showDictationDialog(this, new DictationListener() {
@Override
public void onDictationListener(String dictationResultStr) {
createScheduleContentEt.setText(dictationResultStr);
createScheduleContentEt.requestFocus();
createScheduleContentEt.setSelection(dictationResultStr
.length());
}
});
break;
default:
break;
}
}
}
网友评论