这几天两个舍友都买了iPhone 6S,玩起了“Hey, Siri”,我依旧对个人Nexus 5喊着“OK,Google”。但种种缘由,国内的“OK,Google”并不能展现出他的所有威力,因而上网搜索国内Android平台的语音助手,我的以为评价最好的是讯飞的——灵犀语音助手。其实讯飞语音云平台早就注册过了,并下载了相应的SDK,只是没仔细研究。今天忽然想好好学习一下,以方便之后集成到本身开发的APP中,也能够方便你们参考。开发工具:Android Studio。
前端
好了,废话就说这些。先来看效果图:java
下面是具体的步骤。android
1,首先在讯飞开放平台注册开发者帐号,注册流程很简单,就不详细介绍。网址:http://www.xfyun.cn/。而后就是像各大平台同样的步骤:新建Android应用获取APPID—〉下载语音听写SDK。此处须要注意的是必定要新建本身的应用,别人的工程虽然能用,但不方便后续开发。json
2,解压下载的SDK目录,里面有详细的教程,可自行参考。而后新建工程,将MSC.jar(放入到libs文件夹下)和libmsc.so(放入到新建的jniLibs文件夹下)导入到本身的工程中(只有在线的全部功能,没有提供离线服务。)另外,讯飞提供了两种语音识别接口,一种是后台进行语音检测,没有界面UI提示;另外一种是带UI的接口,在录音、播放音频的时候,会有dialog弹出,并伴有相应的动画,相对来讲用户交互体验很不错。若是使用带UI接口时,请将assets下文件拷贝到项目中。这里注意的是每一个SDK下载的assets可能不同(没有亲自测试过,由于recognize.xml打开乱码),必定要将本身下载的SDK里的assets目录拷贝到XXX/src/main文件夹下。工程目录以下:后端
3,在AndroidManifest.xml文件中添加权限:
数组
<!-- 在工程 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" />
4,布局文件activity_main.xml网络
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <EditText android:id="@+id/content_rec" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="识别内容" /> <Button android:id="@+id/bt_start" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:onClick="startRec" android:text="开始" /> <Button android:id="@+id/btn_read" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/bt_start" android:layout_alignLeft="@+id/bt_start" android:layout_alignParentRight="true" android:onClick="read" android:text="朗读" /> </RelativeLayout>
5,Java代码:JsonParser.java 和 MainActivity.javaapp
(1),JsonParser.Java
ide
package com.xiaobailong24.xunfeiyun; 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(); } }
(2),MainActivity.java函数
package com.xiaobailong24.xunfeiyun; import android.app.Activity; import android.os.Environment; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.Toast; import com.iflytek.cloud.ErrorCode; import com.iflytek.cloud.InitListener; import com.iflytek.cloud.RecognizerListener; import com.iflytek.cloud.RecognizerResult; import com.iflytek.cloud.SpeechConstant; import com.iflytek.cloud.SpeechError; import com.iflytek.cloud.SpeechRecognizer; import com.iflytek.cloud.SpeechSynthesizer; import com.iflytek.cloud.SpeechUtility; import com.iflytek.cloud.SynthesizerListener; import com.iflytek.cloud.ui.RecognizerDialog; import com.iflytek.cloud.ui.RecognizerDialogListener; public class MainActivity extends Activity { private static String TAG = "MainActivity"; // 函数调用返回值 int ret = 0; // 语音听写对象 private SpeechRecognizer mIat; // 语音听写UI private RecognizerDialog iatDialog; // 听写结果内容 private EditText mResultText; // 语音合成对象 private SpeechSynthesizer mTts; // 默认发音人 private String voicer = "xiaoyan"; // 缓冲进度 private int mPercentForBuffering = 0; // 播放进度 private int mPercentForPlaying = 0; private Toast mToast; @Override public void onCreate(Bundle savedInstanceState) { Log.e(TAG, "onCreate"); super.onCreate(savedInstanceState); // this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); // 用于验证应用的key,将XXXXXXXX改成你申请的APPID SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID + "=XXXXXXXX"); // 建立语音听写对象 mIat = SpeechRecognizer.createRecognizer(this, mInitListener); // 初始化听写Dialog,若是只使用有UI听写功能,无需建立SpeechRecognizer // 建立语音听写UI iatDialog = new RecognizerDialog(MainActivity.this, mInitListener); // 建立语音合成对象 mTts = SpeechSynthesizer.createSynthesizer(this, mInitListener); mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT); content_rec)); } public void startRec(View view) { mResultText.setText(null); setParam(); boolean isShowDialog = true; if (isShowDialog) { // 显示听写对话框 iatDialog.setListener(recognizerDialogListener); iatDialog.show(); // showTip("begin"); } else { // 不显示听写对话框 ret = mIat.startListening(recognizerListener); if (ret != ErrorCode.SUCCESS) { // showTip("听写失败,错误码:" + ret); } else { // showTip("begin"); } } } public void read(View view) { String text = mResultText.getText().toString(); // 设置参数 setParam2(); //朗读 int code = mTts.startSpeaking(text, mTtsListener); if (code != ErrorCode.SUCCESS) { if (code == ErrorCode.ERROR_COMPONENT_NOT_INSTALLED) { // 未安装则跳转到提示安装页面 } else { showTip("语音合成失败,错误码: " + code); } } } /** * 参数设置 * * @param * @return */ private void setParam2() { Log.e(TAG, "setParam2"); // 设置合成 mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); // 设置发音人 mTts.setParameter(SpeechConstant.VOICE_NAME, voicer); // 设置语速 mTts.setParameter(SpeechConstant.SPEED, "50"); // 设置音调 mTts.setParameter(SpeechConstant.PITCH, "50"); // 设置音量 mTts.setParameter(SpeechConstant.VOLUME, "50"); // 设置播放器音频流类型 mTts.setParameter(SpeechConstant.STREAM_TYPE, "3"); } public void setParam() { Log.e(TAG, "setParam"); // 清空参数 mIat.setParameter(SpeechConstant.PARAMS, null); // 设置听写引擎 mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); // 设置语言 mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); // 设置语言区域 mIat.setParameter(SpeechConstant.ACCENT, "mandarin"); // 设置语音前端点 mIat.setParameter(SpeechConstant.VAD_BOS, "4000"); // 设置语音后端点 mIat.setParameter(SpeechConstant.VAD_EOS, "1000"); // 设置标点符号 1为有标点 0为没标点 mIat.setParameter(SpeechConstant.ASR_PTT, "0"); // 设置音频保存路径 mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/xiaobailong24/xunfeiyun"); } /** * 合成回调监听。 */ private SynthesizerListener mTtsListener = new SynthesizerListener() { @Override public void onSpeakBegin() { Log.e(TAG, "mTtsListener-->onSpeakBegin"); showTip("开始播放"); } @Override public void onSpeakPaused() { Log.e(TAG, "mTtsListener-->onSpeakPaused"); showTip("暂停播放"); } @Override public void onSpeakResumed() { Log.e(TAG, "mTtsListener-->onSpeakResumed"); showTip("继续播放"); } @Override public void onBufferProgress(int percent, int beginPos, int endPos, String info) { Log.e(TAG, "mTtsListener-->onBufferProgress"); mPercentForBuffering = percent; showTip(String.format(getString(R.string.tts_toast_format), mPercentForBuffering, mPercentForPlaying)); } @Override public void onSpeakProgress(int percent, int beginPos, int endPos) { Log.e(TAG, "mTtsListener-->onSpeakProgress"); mPercentForPlaying = percent; showTip(String.format(getString(R.string.tts_toast_format), mPercentForBuffering, mPercentForPlaying)); } @Override public void onCompleted(SpeechError error) { Log.e(TAG, "mTtsListener-->onCompleted"); if (error == null) { showTip("播放完成"); } else if (error != null) { showTip(error.getPlainDescription(true)); } } @Override public void onEvent(int eventType, int arg1, int arg2, Bundle obj) { Log.e(TAG, "mTtsListener-->onEvent"); } }; /** * 听写监听器。 */ private RecognizerListener recognizerListener = new RecognizerListener() { @Override public void onVolumeChanged(int i, byte[] bytes) { Log.e(TAG, "recognizerListener-->onVolumeChanged"); showTip("当前正在说话,音量大小:" + i); } @Override public void onBeginOfSpeech() { Log.e(TAG, "recognizerListener-->onBeginOfSpeech"); showTip("开始说话"); } @Override public void onEndOfSpeech() { Log.e(TAG, "recognizerListener-->onEndOfSpeech"); showTip("结束说话"); } @Override public void onResult(RecognizerResult results, boolean isLast) { Log.e(TAG, "recognizerListener-->onResult"); String text = JsonParser.parseIatResult(results.getResultString()); mResultText.append(text); mResultText.setSelection(mResultText.length()); if (isLast) { // TODO 最后的结果 } } @Override public void onEvent(int eventType, int arg1, int arg2, Bundle obj) { Log.e(TAG, "recognizerListener-->onEvent"); } @Override public void onError(SpeechError arg0) { Log.e(TAG, "recognizerListener-->onError"); // TODO Auto-generated method stub } }; /** * 听写UI监听器 */ private RecognizerDialogListener recognizerDialogListener = new RecognizerDialogListener() { public void onResult(RecognizerResult results, boolean isLast) { Log.e(TAG, "recognizerDialogListener-->onResult"); String text = JsonParser.parseIatResult(results.getResultString()); mResultText.append(text); mResultText.setSelection(mResultText.length()); } /** * 识别回调错误. */ public void onError(SpeechError error) { Log.e(TAG, "recognizerDialogListener-->onError"); showTip(error.getPlainDescription(true)); } }; private InitListener mInitListener = new InitListener() { @Override public void onInit(int code) { Log.e(TAG, "mInitListener-->onInit"); Log.d(TAG, "SpeechRecognizer init() code = " + code); if (code != ErrorCode.SUCCESS) { showTip("初始化失败,错误码:" + code); } } }; private void showTip(final String str) { Log.e(TAG, "showTip-->" + str); mToast.setText(str); mToast.show(); } @Override protected void onDestroy() { Log.e(TAG, "onDestroy"); super.onDestroy(); // 退出时释放链接 mIat.cancel(); mIat.destroy(); } @Override protected void onResume() { Log.e(TAG, "onResume"); super.onResume(); } @Override protected void onPause() { Log.e(TAG, "onPause"); super.onPause(); } }