样式:
1.集成科大讯飞:网上有很多集成方法。
2.写布局,注意帧布局有顺序谁在最上面,要在布局文件下面写。下面是我的布局,注意用Scrollview套,是因为要随键盘上下滑动。
<RelativeLayout
android:id="@+id/search_voice_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.8"
android:background="@color/white"
android:visibility="gone">
<TextView
android:id="@+id/search_voice_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="70dp"
android:textColor="#333333"
android:textSize="20sp"
android:visibility="gone" />
<TextView
android:id="@+id/voice_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/search_voice_msg"
android:layout_centerHorizontal="true"
android:textColor="#f7783f"
android:textSize="20sp"
android:visibility="gone" />
<RelativeLayout
android:id="@+id/search_voice_dialog"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_centerInParent="true"
android:background="@drawable/search_voice_dialog"
android:gravity="center"
android:visibility="gone">
<TextView
android:id="@+id/search_voice_dialog_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="10dp"
android:text="@string/search_voice_dialog_title"
android:textColor="#fff"
android:textSize="15sp" />
<ImageView
android:id="@+id/search_voice_dialog_mic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerInParent="true"
android:src="@drawable/tmsearch_voice"></ImageView>
<ImageView
android:id="@+id/search_sound_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/search_voice_dialog_mic"
android:layout_marginBottom="1dip"
android:layout_marginLeft="30dp"
android:background="@drawable/voice_1"></ImageView>
</RelativeLayout>
</RelativeLayout>
</FrameLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:background="#fafafa">
<ImageView
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="#d4d4d4" />
<RelativeLayout
android:id="@+id/search_voice_rl"
android:layout_width="280dp"
android:layout_height="37dp"
android:layout_centerInParent="true"
android:background="@drawable/search_top_bg">
<ImageView
android:id="@+id/voice_tube"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="30dp"
android:src="@drawable/search_icon" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/voice_tube"
android:text="@string/search_voice"
android:textColor="#444444"
android:textSize="18sp" />
</RelativeLayout>
</RelativeLayout>
</ScrollView>
3.代码部分:
1.
2.在/** * 语音搜索 */ @BindView(R.id.search_voice_rl) RelativeLayout voice_btn; @BindView(R.id.search_voice_bg) RelativeLayout voice_bg; @BindView(R.id.search_voice_msg) TextView voice_msg; @BindView(R.id.search_voice_dialog) RelativeLayout voice_dialog; @BindView(R.id.search_voice_dialog_tv) TextView dialog_title; @BindView(R.id.search_voice_dialog_mic) ImageView dialog_mic; @BindView(R.id.search_sound_progress) ImageView dialog_progress; @BindView(R.id.voice_result) TextView voice_result; /** * 语音听写对象 */ private SpeechRecognizer mIat; /** * 用HashMap存储听写结果 */ private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>(); /** * 引擎类型 */ private String mEngineType = SpeechConstant.TYPE_CLOUD; private Drawable[] progressImg = new Drawable[9]; private GestureDetector mGestureDetector; float mPosX, mPosY, mCurPosX, mCurPosY; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0: restoreState(); break; } } }; boolean isNetwork = false; HandlerUtil handerUtil; private static final int SHOW_TIME = 1500; private static final int SHOW_TIME_RESULT = 2500;
onCreate(Bundle savedInstanceState)
中:
keyWordRv = (RecyclerView) findViewById(R.id.search_leyWord_listView); //创建SpeechRecognizer对象,第二个参数:本地听写时传InitListener mIat = SpeechRecognizer.createRecognizer(this, null); searchVoice();3.
4./** * 语音搜索 */ private void searchVoice() { mGestureDetector = new GestureDetector(this, new MyOnGestureListener()); progressImg[0] = this.getResources().getDrawable(R.drawable.voice_1); progressImg[1] = this.getResources().getDrawable(R.drawable.voice_2); progressImg[2] = this.getResources().getDrawable(R.drawable.voice_3); progressImg[3] = this.getResources().getDrawable(R.drawable.voice_4); progressImg[4] = this.getResources().getDrawable(R.drawable.voice_5); progressImg[5] = this.getResources().getDrawable(R.drawable.voice_6); progressImg[6] = this.getResources().getDrawable(R.drawable.voice_7); progressImg[7] = this.getResources().getDrawable(R.drawable.voice_8); progressImg[8] = this.getResources().getDrawable(R.drawable.voice_9); voice_btn.setFocusable(true); voice_btn.setClickable(true); voice_btn.setLongClickable(true); voice_btn.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { //通知父控件勿拦截本控件touch事件 view.getParent().requestDisallowInterceptTouchEvent(true); mGestureDetector.onTouchEvent(motionEvent); switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: startState(); mPosX = motionEvent.getX(); mPosY = motionEvent.getY(); break; case MotionEvent.ACTION_MOVE: mCurPosX = motionEvent.getX(); mCurPosY = motionEvent.getY(); if (mCurPosY - mPosY < 0 && (Math.abs(mCurPosY - mPosY) > 100)) { dialog_progress.setVisibility(View.GONE); dialog_mic.setImageResource(R.drawable.tbsearch_repeal); dialog_title.setBackgroundResource(R.drawable.tmsearch_btn); dialog_title.setText(R.string.Loosen_the_fingers); startState(); } else if (mCurPosY - mPosY > 0 && (Math.abs(mCurPosY - mPosY) > 100)) { dialog_progress.setVisibility(View.GONE); dialog_mic.setImageResource(R.drawable.tbsearch_repeal); dialog_title.setBackgroundResource(R.drawable.tmsearch_btn); dialog_title.setText(R.string.Loosen_the_fingers); } else { dialog_progress.setVisibility(View.VISIBLE); dialog_mic.setImageResource(R.drawable.tmsearch_voice); dialog_title.setBackgroundColor(Color.parseColor("#222222")); dialog_title.setText(R.string.search_voice_dialog_title); } break; case MotionEvent.ACTION_UP: voice_btn.setBackgroundResource(R.drawable.get_code_bg); if (mCurPosY - mPosY > 0 && (Math.abs(mCurPosY - mPosY) > 100)) { //向下滑动 mIat.cancel(); voice_msg.setText(R.string.voice_search_has_been_cancelled); resultState(); handerUtil.sendMessage(SHOW_TIME); } else if (mCurPosY - mPosY < 0 && (Math.abs(mCurPosY - mPosY) > 100)) { //向上滑动 mIat.cancel(); voice_msg.setText(R.string.voice_search_has_been_cancelled); resultState(); handerUtil.sendMessage(SHOW_TIME); } else { voice_dialog.setVisibility(View.GONE); mIat.stopListening(); } break; } return true; } }); }
5这基本就和淘宝的语音搜索差不多了private void setParam() { // 清空参数 mIat.setParameter(SpeechConstant.PARAMS, null); // 引擎 mIat.setParameter(SpeechConstant.DOMAIN, "iat"); // 设置语言 mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); // 普通话 mIat.setParameter(SpeechConstant.ACCENT, "mandarin"); // 设置听写引擎 mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType); // 设置返回结果格式 mIat.setParameter(SpeechConstant.RESULT_TYPE, "json"); // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理 mIat.setParameter(SpeechConstant.VAD_BOS, "4000"); // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音 mIat.setParameter(SpeechConstant.VAD_EOS, "4000"); // 语音输入超时时间 mIat.setParameter(SpeechConstant.KEY_SPEECH_TIMEOUT, "10000"); // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点 mIat.setParameter(SpeechConstant.ASR_PTT, "0"); // 开始听写 mIat.startListening(mRecognizerListener); } /** * 听写监听器 */ private RecognizerListener mRecognizerListener = new RecognizerListener() { @Override public void onVolumeChanged(int i, byte[] bytes) { volumeChanged(i); } @Override public void onBeginOfSpeech() { // 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入 } @Override public void onEndOfSpeech() { // 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入 } @Override public void onResult(RecognizerResult recognizerResult, boolean isLast) { String lastResult = null; if (recognizerResult != null) { lastResult = printResult(recognizerResult); } if (isLast) { // 最后的结果 recognitionState(); final String finalLastResult = lastResult; //有时语音搜索会识别出“。”或空的时候,为避免这种情况的发生故做此判断,如果出现这种情况显示未识别状态 if (finalLastResult.equals("。") || StringUtils.isEmpty(finalLastResult)) { unidentified(); mIat.cancel(); handerUtil.sendMessage(SHOW_TIME); return; } mIat.stopListening(); handerUtil.postDelayed(new Runnable() { @Override public void run() { voice_msg.setText(R.string.is_the_search_for_you); voice_result.setText(finalLastResult); voice_result.setVisibility(View.VISIBLE); resultState(); } }, SHOW_TIME); handerUtil.postDelayed(new Runnable() { @Override public void run() { handerUtil.sendMessage(1000); toSearchResultActivity(finalLastResult); } }, SHOW_TIME_RESULT); } } @Override public void onError(SpeechError speechError) { if (speechError.getErrorCode() == 10118 || speechError.getErrorCode() == 10114) { // 可能是录音机权限被禁,需要提示用户打开应用的录音权限。 unidentified(); mIat.cancel(); handerUtil.sendMessage(500); } else { isNetwork = true; voice_msg.setText(R.string.voice_search_no_internet); resultState(); handerUtil.sendMessage(SHOW_TIME); } } @Override public void onEvent(int i, int i1, int i2, Bundle bundle) { } }; /** * 声音改变方法(当前音量值,范围[0-30]) */ private void volumeChanged(int decibel) { switch (decibel) { case 0: case 1: case 2: dialog_progress.setBackgroundDrawable(progressImg[0]); break; case 3: case 4: case 5: dialog_progress.setBackgroundDrawable(progressImg[1]); break; case 6: case 7: case 8: dialog_progress.setBackgroundDrawable(progressImg[2]); break; case 9: case 10: case 11: dialog_progress.setBackgroundDrawable(progressImg[3]); break; case 12: case 13: case 14: dialog_progress.setBackgroundDrawable(progressImg[4]); break; case 15: case 16: case 17: case 18: dialog_progress.setBackgroundDrawable(progressImg[5]); break; case 19: case 20: case 21: case 22: dialog_progress.setBackgroundDrawable(progressImg[6]); break; case 23: case 24: case 25: case 26: dialog_progress.setBackgroundDrawable(progressImg[7]); break; case 27: case 28: case 29: case 30: dialog_progress.setBackgroundDrawable(progressImg[8]); break; } } /** * 语音返回结果 */ private String printResult(RecognizerResult results) { String text = null; String sn = null; if (results != null) { text = JsonParser.parseIatResult(results.getResultString()); } // 读取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)); } return resultBuffer.toString(); } class MyOnGestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { if (!isNetwork) { mIat.cancel(); restoreState(); } return true; } @Override public void onLongPress(MotionEvent e) { // 清空显示内容 if (!isNetwork) { voice_msg.setText(null); mIatResults.clear(); startState(); } } @Override public void onShowPress(MotionEvent e) { voice_btn.setBackgroundResource(R.drawable.gray_round_bg); startState(); } @Override public boolean onDown(MotionEvent e) { isNetwork = false; dialog_progress.setVisibility(View.VISIBLE); dialog_mic.setImageResource(R.drawable.tmsearch_voice); dialog_title.setText(R.string.search_voice_dialog_title); dialog_title.setBackgroundColor(Color.parseColor("#222222")); startState(); setParam(); return false; } } /** * 开始听写状态 */ private void startState() { voice_bg.setVisibility(View.VISIBLE); voice_dialog.setVisibility(View.VISIBLE); voice_msg.setVisibility(View.GONE); voice_result.setVisibility(View.GONE); } /** * 识别中状态 */ private void recognitionState() { voice_bg.setVisibility(View.VISIBLE); voice_msg.setText(R.string.search_voice_msg); voice_msg.setVisibility(View.VISIBLE); voice_dialog.setVisibility(View.GONE); } /** * 未识别状态 */ private void unidentified() { voice_bg.setVisibility(View.VISIBLE); voice_result.setVisibility(View.GONE); voice_dialog.setVisibility(View.GONE); voice_msg.setText(R.string.voice_search_error); voice_msg.setVisibility(View.VISIBLE); } /** * 显示结果状态 */ private void resultState() { voice_bg.setVisibility(View.VISIBLE); voice_msg.setVisibility(View.VISIBLE); voice_dialog.setVisibility(View.GONE); } /** * 恢复原状状态 */ private void restoreState() { voice_bg.setVisibility(View.GONE); voice_msg.setVisibility(View.GONE); voice_dialog.setVisibility(View.GONE); }