How to register a custom speech recognition service?
android, android-service
Solution
If you want `queryIntentActivities(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0)` to pick up your activity (`VoiceServiceStarterActivity`) then you have to declare in your app's Manifest that this activity handles `RecognizerIntent.ACTION_RECOGNIZE_SPEECH`, like this
<activity android:name="VoiceServiceStarterActivity">
<intent-filter>
<action android:name="android.speech.action.RECOGNIZE_SPEECH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
...
</activity>
For more concrete code have a look at the project Kõnele (source code) which is essentially an open source implementation of the interfaces via which speech recognition is provided on Android, i.e. it covers:
- ACTION_RECOGNIZE_SPEECH
- ACTION_WEB_SEARCH
- RecognitionService
and uses open source speech recognition servers.
Problem
I created a simple speech recognition service: for this purpose I created a subclass of `android.speech.RecognitionService` and I created an activity to start and stop this service. My custom speech recognition service trivially uses the default speech recognizer, because my goal is simply to understand how the `RecognitionService` and `RecognitionService.Callback` classes work. ``` public class SimpleVoiceService extends RecognitionService { private SpeechRecognizer m_EngineSR; @Override public void onCreate() { super.onCreate(); Log.i("SimpleVoiceService", "Service started"); } @Override public void onDestroy() { super.onDestroy(); Log.i("SimpleVoiceService", "Service stopped"); } @Override protected void onCancel(Callback listener) { m_EngineSR.cancel(); } @Override protected void onStartListening(Intent recognizerIntent, Callback listener) { m_EngineSR.setRecognitionListener(new VoiceResultsListener(listener)); m_EngineSR.startListening(recognizerIntent); } @Override protected void onStopListening(Callback listener) { m_EngineSR.stopListening(); } /** * */ private class VoiceResultsListener implements RecognitionListener { private Callback m_UserSpecifiedListener; /** * * @param userSpecifiedListener */ public VoiceResultsListener(Callback userSpecifiedListener) { m_UserSpecifiedListener = userSpecifiedListener; } @Override public void onBeginningOfSpeech() { try { m_UserSpecifiedListener.beginningOfSpeech(); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onBufferReceived(byte[] buffer) { try { m_UserSpecifiedListener.bufferReceived(buffer); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onEndOfSpeech() { try { m_UserSpecifiedListener.endOfSpeech(); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onError(int error) { try { m_UserSpecifiedListener.error(error); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onEvent(int eventType, Bundle params) { ; } @Override public void onPartialResults(Bundle partialResults) { try { m_UserSpecifiedListener.partialResults(partialResults); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onReadyForSpeech(Bundle params) { try { m_UserSpecifiedListener.readyForSpeech(params); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onResults(Bundle results) { try { m_UserSpecifiedListener.results(results); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onRmsChanged(float rmsdB) { try { m_UserSpecifiedListener.rmsChanged(rmsdB); } catch (RemoteException e) { e.printStackTrace(); } } } } ``` I start and stop the service using the following activity. ``` public class VoiceServiceStarterActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Button startButton = new Button(this); startButton.setText("Start the service"); startButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startVoiceService(); } }); Button stopButton = new Button(this); stopButton.setText("Stop the service"); stopButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopVoiceService(); } }); LinearLayout layout = new LinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); layout.addView(startButton); layout.addView(stopButton); setContentView(layout); } private void startVoiceService() { startService(new Intent(this, SimpleVoiceService.class)); } private void stopVoiceService() { stopService(new Intent(this, SimpleVoiceService.class)); } } ``` Finally I declared my service on the `AndroidManifest.xml` (see VoiceRecognition sample within Android SDK folder). ``` <service android:name="SimpleVoiceService" android:label="@string/service_name" > <intent-filter> <action android:name="android.speech.RecognitionService" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service> ``` Then I installed this application on an Android device and I start it: - when I start the service, it starts properly; - when I stop it, it stops properly. But if I launch the following code in a another activity, the `activities` `List` contains only an element, which is the default speech recognizer. ``` PackageManager pm = getPackageManager(); List<ResolveInfo> activities = pm.queryIntentActivities( new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0); ``` Why is my speech recognizer not returned among those present in the system?