標籤:
引言
由於為期半年的項目結束了,進入了一段“療養”的真空期,因此有時間可以去歸納整理項目的經驗,學習新的姿勢與技巧,對自己技術水平也是一種提升。另外,個人懶癌症嚴重,為強迫自己努力學習,立了一些福來閣(比如沒有寫出部落格女裝什麼的咳咳,我一定會拔旗成功的,哼),總體來說督促效果還是挺不錯的。
項目中使用的Android和linux進行用戶端的開發,結合項目的實戰經驗,七月份寫的部落格內容主要圍繞Android開發進行,研究的內容預定為:Android中Google語音搜尋功能探究(開篇),app應用意外關閉後MediaPlayer進行斷點播放(預計兩到三章左右)
為何選擇AndroidGoogle語音搜尋作為第一篇正式的博文?第一實現功能較為簡單,代碼量很小,可以為後續的文章熱熱身;第二語音搜尋這個功能強大的,尤其是Google作為IT巨頭,語音搜尋體感非常棒,識別快而精準。Google的語音搜尋可以廣泛應用與基於LBS的Android應用程式中,調用Googleapi擷取搜尋結果,然後根據這個結果做自己想要的功能。
言歸正傳,下面開始正式介紹Google的語音搜尋。
Google語音搜尋基礎
語音辨識是Google在API Level3,也就是SDK1.5中引入的。根據官方的SDK的資料,語音檢索的模式行為(action)有4種:
ACTION_GET_LANGUAGE_DETAILS ---> API Level8引入
ACTION_RECOGNIZE_SPEECH ---> API Level3引入
ACTION_VOICE_SEARCH_HANDS_FREE ---> API Level16引入
ACTION_WEB_SEARCH ---> API Level3引入
大致的功能為:
ACTION_GET_LANGUAGE_DETAILS:一個廣播性質的intent,用於擷取meta-data, 不常用。
ACTION_RECOGNIZE_SPEECH:起一個activity將使用者所說的內容發送至語音辨識器,結果將會從onActivityResult中返回。(注: 官方不再支援startActivity的方式起intent, 改為startActivityResult)。該部分是核心功能。
ACTION_VOICE_SEARCH_HANDS_FREE:API16中新引入的功能,不常用,目的是讓使用者在不使用用戶端的情況下也能進行語音搜尋,例如處於鎖屏的安全模式中。如果要想使用該模式必須在manifest中加入如下:
1 <action android:name="android.speech.action.VOICE_SEARCH_HANDS_FREE" />
ACTION_WEB_SEARCH:通過Web網路檢索來實現。
自訂設定項(Option)主要有以下3個:
EXTRA_LANGUAGE_MODEL:語音辨識的語言設定
EXTRA_PROMPT: 語音輸入時顯示的提示文字
EXTRA_MAX_RESULTS: 語音搜尋結果最大值設定
此外需要注意一點,在沒有Google服務的地區是不能進行GoogleVoice Messaging Service的,括弧笑。而且手機不支援語音搜尋的話,本地需要預先安裝一個語音包:Voice_Search_2.1.4.apk, 這個版本非常老,2011年出的一直沒有更新,原生態的皮膚令人懷念。如果沒有在google-market中下載到,可以到如下網址下載:
http://www.coolapk.com/apk/com.google.android.voicesearch
Google語音搜尋的實現
實現的方法可以概括為以下四步:
1 起一個名為RecognizerIntent的Intent活動
2 putExtra中填入語音搜尋的常量設定
3 startActivityResult
4 onActivityResult等待搜尋結果。
核心程式碼範例:
添加一個RadiaGroup, 設定3種常用的語音搜尋模式。
<RadioGroup android:id="@+id/search_group" android:orientation="vertical" android:layout_marginLeft="90dp" android:layout_width="wrap_content" android:layout_height="wrap_content"> <RadioButton android:checked="true" android:text="ACTION_RECOGNIZE_SPEECH" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <RadioButton android:text="ACTION_WEB_SEARCH" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <RadioButton android:text="ACTION_VOICE_SEARCH_HANDS_FREE" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RadioGroup>
在MainActivity中擷取RadioGroup所選的內容,代碼如下
1 private String getRecognizerMode() { 2 3 for (int i=0; i<radioBtn.getChildCount(); i++) { 4 5 RadioButton btn = (RadioButton) radioBtn.getChildAt(i); 6 7 if (btn.isChecked()) { 8 9 if (btn.getText().equals(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)) {10 11 return RecognizerIntent.ACTION_RECOGNIZE_SPEECH;12 13 } else if (btn.getText().equals(RecognizerIntent.ACTION_WEB_SEARCH)) {14 15 return RecognizerIntent.ACTION_WEB_SEARCH;16 17 } else if (btn.getText().equals(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE)) {18 19 return RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE;20 21 }22 23 else {24 25 return null;26 27 }28 29 }30 31 }32 33 return null;34 35 }
然後是點擊語音按鈕後,執行startVoiceRecognition這個方法起intent操作
1 private void startVoiceRecognition(String mode) { 2 3 try { 4 5 Intent intent = new Intent(mode); 6 7 intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 8 9 RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);10 11 intent.putExtra(RecognizerIntent.EXTRA_PROMPT, R.string.voice_begin);12 13 intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "zh-HK");14 15 startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);16 17 } catch (Exception e) {18 19 e.printStackTrace();20 21 Toast.makeText(this, "No Google Voice app, plz download.", Toast.LENGTH_SHORT).show();22 23 }24 25 }
在測試中發現,語音搜尋所識別的內容依賴於機器的系統內容,如果是中文系統識別出的是中文的搜尋內容,如果是日文系統的則是日文的搜尋內容。RecognizerIntent.EXTRA_LANGUAGE這個屬性似乎沒有什麼亂用。
最後是onActivityResult回調結果部分
protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Log.d("lsy", "onActivityResult --> requestCode: " + requestCode + " resultCode: " + resultCode); if (requestCode == VOICE_RECOGNITION_REQUEST_CODE && resultCode == RESULT_OK) { ArrayList<String > results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); if (results.size() > 0) { String result = results.get(0).toString().trim(); if (null != result && result.length() > 0) { searchResult.setText(result);// 擷取所有檢索結果// for (String str : results) {// searchResult.append(str + "/n");// } } else { Toast.makeText(this, "Voice Content Fail", Toast.LENGTH_SHORT).show(); } } else { Log.d("lsy", "onActivityResult --> Voice Content Fail"); Toast.makeText(this, "Voice Content Fail", Toast.LENGTH_SHORT).show(); } } }
所有搜尋的結果儲存在一個ArrayList的列表中,第一個資料是匹配值最高,代碼中因為需要拿最匹配的值去做地圖搜尋才會選擇第一個資料。注釋部分可以列印出所有滿足搜尋條件的值。
總結
Google的語音搜尋可以協助我們實現在LBS類應用中進行語音定位,其搜尋精度高,速度快,只是不可描述的存在限制了這個好用的功能,很是可惜。後續基於Google語音開發的內容可以包括:曆史語音搜尋記錄、語音聯想功能、與自主開發導航軟體的協同工作等,由於時間倉促沒有來的及實現,有興趣的朋友可以實驗下。
本文對網上關於Google語音搜尋的文章進行總結和部分拓展,做了點微小的貢獻,甚是慚愧。
參考博文
http://blog.csdn.net/h7870181/article/details/11151773
http://blog.csdn.net/gumanren/article/details/6771265
Android中Google語音辨識應用探究