編輯:關於android開發
原文標題:Use Voice Search to integrate with Google Now
原文鏈接:http://antonioleiva.com/voice_search_google_now/
原文作者:Antonio Leiva(http://antonioleiva.com/about/)
原文發布:2015-10-14
Android最棒的能力之一就是可以將我們的APP以不同的方式集成到它的生態鏈中。APP相互之間可以進行“交流”,這給予我們極大的靈活性來創建獨特的應用體驗。
集成Google應用就是一個典型的例子。有很多不同的特性可以幫助我們提升APP的知名度,如APP索引或一組強大的語音功能。
盡管,在APP中實現語音搜索的過程與任何其他語音功能類似,但是,在這篇文章中,我還是會聚焦在怎樣在APP中實現語音搜索功能。你也可以在Play Music中嘗試這個例子:
這句指令將在Play Music APP中開啟搜索Beatles。
當語音搜索啟動後,我們的APP將收到一個查詢文字的Intent,我們必須捕捉和分析這段文字。所以,這第一部分是指定哪個Activity接收這條Intent:
1 <activity android:name=".MainActivity" android:launchMode="singleTask" > 2 <intent-filter> 3 <action android:name="com.google.android.gms.actions.SEARCH_ACTION"/> 4 <category android:name="android.intent.category.DEFAULT"/> 5 </intent-filter> 6 </activity>
這個動作(action)稱為com.google.android.gms.actions.SEARCH_ACTION,所以我們說MainActivity是處理這類Intent。另外,我用singleTask啟動模式,這樣MainActivity就僅僅創建一次。否則,每次收到這條Intent就要創建一個新的Activity實例。
接下來的一步是要在MainActivity內進行處理它。當我們用singleTask模式時,在Activity的兩個不同位置上可以接收Intent:首先是用getIntent()創建Activity,接著是onNewIntent方法中。這樣就要創建一個處理方法在需要它的時候調用它:
1 private static final String ACTION_VOICE_SEARCH = "com.google.android.gms.actions.SEARCH_ACTION"; 2 ... 3 private void handleVoiceSearch(Intent intent) { 4 if (intent != null && ACTION_VOICE_SEARCH.equals(intent.getAction())) { 5 String query = intent.getStringExtra(SearchManager.QUERY); 6 setSearchViewVisible(true); 7 searchView.setQuery(query, true); 8 } 9 }
這個方法檢查Intent是否為空(null)或者是否是在收到查詢文字前要檢測的動作,它是Intent內部的額外動作。查詢的額外動作關鍵字是SearchManager.QUERY。
在searchView後,設置查詢,提交執行查詢。其方法是onNewIntent:
1 @Override protected void onNewIntent(Intent intent) { 2 super.onNewIntent(intent); 3 handleVoiceSearch(intent); 4 }
UI也准備好(在我們的例子中,當菜單彈出時,我們訪問SearchView),你稍後將看到。
在我的例子中,UI是基於工具欄(Toolbar)內部的SearchView。你可以在前面的文章中看到怎樣實現SearchView,不過我還是稍作解釋怎樣做。首先,產生菜單動作(menu action):
1 <menu xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:app="http://schemas.android.com/apk/res-auto"> 3 <item 4 android:id="@+id/action_search" 5 android:title="@string/action_search" 6 android:icon="@drawable/ic_search" 7 app:actionViewClass="android.support.v7.widget.SearchView" 8 app:showAsAction="ifRoom" /> 9 </menu>
然後,在菜單彈出時,你請求SearchView:
1 @Override public boolean onCreateOptionsMenu(Menu menu) { 2 getMenuInflater().inflate(R.menu.main, menu); 3 4 MenuItem searchItem = menu.findItem(R.id.action_search); 5 searchView = (SearchView) MenuItemCompat.getActionView(searchItem); 6 7 searchView.setOnSearchClickListener(new View.OnClickListener() { 8 @Override public void onClick(View v) { 9 setSearchViewVisible(true); 10 } 11 }); 12 13 searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { 14 @Override public boolean onQueryTextSubmit(String query) { 15 Toast.makeText(MainActivity.this, query, Toast.LENGTH_LONG).show(); 16 searchView.clearFocus(); 17 return true; 18 } 19 20 @Override public boolean onQueryTextChange(String newText) { 21 return false; 22 } 23 }); 24 25 handleVoiceSearch(getIntent()); 26 27 return true; 28 } 29 30 private void setSearchViewVisible(boolean visible) { 31 32 if (searchView.isIconified() == visible) { 33 searchView.setIconified(!visible); 34 } 35 36 if (getSupportActionBar() != null) { 37 getSupportActionBar().setDisplayHomeAsUpEnabled(visible); 38 } 39 }
由於APP需要發布到Play商店中,Google Now才能檢測到APP,所以我們還不能直接從Google Now嘗試這個例子。但是,我們可以用ADB來調試它。這條命令是:
對於從我的代碼庫下載的例子,就可以這樣做:
在APP完全關閉和啟動時,都可以嘗試本例了。這樣,就可以測試兩種可能的途徑了。
你可能知道,因為我認為Kotlin語言可以非常好替代Java語言,Kotlin可以使我們的代碼更簡潔、可讀性更好,所以這些天討論了許多Kotlin語言的特性。作為例子,我將簡化onCreateOptionsMenu,你可以在同一個代碼庫中找到完整的代碼。
實現擴展函數的能力可以幫助我們減少冗長代碼。例如,可以為Menu創建一個擴展函數,基於action id找到ActionView,返回層級視圖:
1 inline fun <reified T : View?> Menu.findCompatActionView(actionRes: Int): T { 2 val searchItem = findItem(actionRes) 3 return MenuItemCompat.getActionView(searchItem) as T 4 }
現在可以這樣做:
1 searchView = menu.findCompatActionView(R.id.action_search)
另一個擴展函數可以以清晰的方式幫助我們編寫OueryTextListener:
1 fun SearchView.onQueryText(submit: (String) -> Boolean = { false }, textChange: (String) -> Boolean = { false }) { 2 3 this.setOnQueryTextListener(object : SearchView.OnQueryTextListener { 4 5 override fun onQueryTextSubmit(query: String): Boolean = submit(query) 6 7 override fun onQueryTextChange(newText: String): Boolean = textChange(newText) 8 9 }) 10 }
這個函數接收一對函數,一個用於偵聽器中的每個方法,並給出它們的默認值。這樣我們僅需要定義我們要用的。如果我們僅僅要第一個函數(對於第二個我們用默認的),現在我就可以這樣做:
1 searchView.onQueryText ({ 2 longToast(it) 3 searchView.clearFocus() 4 true 5 })
最終,這個函數就是這樣的:
1 override fun onCreateOptionsMenu(menu: Menu): Boolean { 2 menuInflater.inflate(R.menu.main, menu) 3 4 searchView = menu.findCompatActionView(R.id.action_search) 5 searchView.setOnSearchClickListener { setSearchViewVisible(true) } 6 7 searchView.onQueryText ({ 8 longToast(it) 9 searchView.clearFocus() 10 true 11 }) 12 13 intent?.let { handleVoiceSearch(it) } 14 15 return true 16 }
如你所見,如果在這個位置上(例如:在一個常規activity創建上),Intent可以為null,就必須在使用它之前檢查它是否為null。用let函數,可以避免if條件的創建,在對象調用時不為null,就可只進入對象內部。
如果你對Kotlin有興趣,可以搜索Kotlin文章,或購買我編寫的《Android開發者的Kotlin》一書。
手機影音6--視頻播放器的基本功能(3),6--基本功能 1.自定義VideoView 1_自定義VideoView-增加設置視頻大小方法 public class V
iOS,Android網絡抓包教程之tcpdump 現在的移動端應用幾乎都會通過網絡請求來和服務器交互,通過抓包來診斷和網絡相關的bug是程序員的重要技能之一。抓包的
我的Android進階之旅------)關於使用CSDN-markdown編輯器來編寫博客 關於使用MarkDown編輯器的原因 其實前段時間就支持使用MarkDown
Android集成Facebook sdk,Key Hashes生成步驟 如上圖所示,使用facebook sdk進行login和share的時候,需要新建andr