blob: cd73ba85063183334f0d5f1dcdbe9e6f68d3d19e [file] [log] [blame]
Valentin Kravtsov79896bd2010-01-15 11:56:03 +00001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.speech;
18
19import android.content.ComponentName;
20import android.content.Context;
21import android.content.Intent;
22import android.content.ServiceConnection;
23import android.content.pm.ResolveInfo;
24import android.os.Bundle;
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +000025import android.os.Handler;
Valentin Kravtsov79896bd2010-01-15 11:56:03 +000026import android.os.IBinder;
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +000027import android.os.Looper;
28import android.os.Message;
Valentin Kravtsov79896bd2010-01-15 11:56:03 +000029import android.os.RemoteException;
Mike LeBeau5d34e9b2010-02-10 19:34:56 -080030import android.provider.Settings;
31import android.text.TextUtils;
Valentin Kravtsov79896bd2010-01-15 11:56:03 +000032import android.util.Log;
33
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +000034import java.util.LinkedList;
Valentin Kravtsov79896bd2010-01-15 11:56:03 +000035import java.util.List;
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +000036import java.util.Queue;
Valentin Kravtsov79896bd2010-01-15 11:56:03 +000037
38/**
39 * This class provides access to the speech recognition service. This service allows access to the
40 * speech recognizer. Do not instantiate this class directly, instead, call
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -070041 * {@link SpeechRecognizer#createSpeechRecognizer(Context)}. This class's methods must be
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +000042 * invoked only from the main application thread. Please note that the application must have
43 * {@link android.Manifest.permission#RECORD_AUDIO} permission to use this class.
Valentin Kravtsov79896bd2010-01-15 11:56:03 +000044 */
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -070045public class SpeechRecognizer {
Valentin Kravtsov79896bd2010-01-15 11:56:03 +000046 /** DEBUG value to enable verbose debug prints */
47 private final static boolean DBG = false;
48
49 /** Log messages identifier */
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -070050 private static final String TAG = "SpeechRecognizer";
Valentin Kravtsov79896bd2010-01-15 11:56:03 +000051
52 /**
Ben Dodson4e8620f2010-08-25 10:55:47 -070053 * Used to retrieve an {@code ArrayList<String>} from the {@link Bundle} passed to the
Valentin Kravtsov79896bd2010-01-15 11:56:03 +000054 * {@link RecognitionListener#onResults(Bundle)} and
55 * {@link RecognitionListener#onPartialResults(Bundle)} methods. These strings are the possible
56 * recognition results, where the first element is the most likely candidate.
57 */
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +000058 public static final String RESULTS_RECOGNITION = "results_recognition";
59
60 /** Network operation timed out. */
61 public static final int ERROR_NETWORK_TIMEOUT = 1;
62
63 /** Other network related errors. */
64 public static final int ERROR_NETWORK = 2;
65
66 /** Audio recording error. */
67 public static final int ERROR_AUDIO = 3;
68
69 /** Server sends error status. */
70 public static final int ERROR_SERVER = 4;
71
72 /** Other client side errors. */
73 public static final int ERROR_CLIENT = 5;
74
75 /** No speech input */
76 public static final int ERROR_SPEECH_TIMEOUT = 6;
77
78 /** No recognition result matched. */
79 public static final int ERROR_NO_MATCH = 7;
80
81 /** RecognitionService busy. */
82 public static final int ERROR_RECOGNIZER_BUSY = 8;
83
84 /** Insufficient permissions */
85 public static final int ERROR_INSUFFICIENT_PERMISSIONS = 9;
86
87 /** action codes */
88 private final static int MSG_START = 1;
89 private final static int MSG_STOP = 2;
90 private final static int MSG_CANCEL = 3;
91 private final static int MSG_CHANGE_LISTENER = 4;
Valentin Kravtsov79896bd2010-01-15 11:56:03 +000092
93 /** The actual RecognitionService endpoint */
94 private IRecognitionService mService;
95
96 /** The connection to the actual service */
97 private Connection mConnection;
98
99 /** Context with which the manager was created */
100 private final Context mContext;
Mike LeBeau79375f72010-02-18 19:01:47 -0800101
102 /** Component to direct service intent to */
103 private final ComponentName mServiceComponent;
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000104
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000105 /** Handler that will execute the main tasks */
106 private Handler mHandler = new Handler() {
107 @Override
108 public void handleMessage(Message msg) {
109 switch (msg.what) {
110 case MSG_START:
111 handleStartListening((Intent) msg.obj);
112 break;
113 case MSG_STOP:
114 handleStopMessage();
115 break;
116 case MSG_CANCEL:
117 handleCancelMessage();
118 break;
119 case MSG_CHANGE_LISTENER:
120 handleChangeListener((RecognitionListener) msg.obj);
121 break;
122 }
123 }
124 };
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000125
126 /**
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000127 * Temporary queue, saving the messages until the connection will be established, afterwards,
128 * only mHandler will receive the messages
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000129 */
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000130 private final Queue<Message> mPendingTasks = new LinkedList<Message>();
131
132 /** The Listener that will receive all the callbacks */
133 private final InternalListener mListener = new InternalListener();
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000134
135 /**
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700136 * The right way to create a {@code SpeechRecognizer} is by using
137 * {@link #createSpeechRecognizer} static factory method
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000138 */
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700139 private SpeechRecognizer(final Context context, final ComponentName serviceComponent) {
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000140 mContext = context;
Mike LeBeau79375f72010-02-18 19:01:47 -0800141 mServiceComponent = serviceComponent;
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000142 }
143
144 /**
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000145 * Basic ServiceConnection that records the mService variable. Additionally, on creation it
146 * invokes the {@link IRecognitionService#startListening(Intent, IRecognitionListener)}.
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000147 */
148 private class Connection implements ServiceConnection {
149
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000150 public void onServiceConnected(final ComponentName name, final IBinder service) {
151 // always done on the application main thread, so no need to send message to mHandler
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000152 mService = IRecognitionService.Stub.asInterface(service);
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000153 if (DBG) Log.d(TAG, "onServiceConnected - Success");
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000154 while (!mPendingTasks.isEmpty()) {
155 mHandler.sendMessage(mPendingTasks.poll());
156 }
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000157 }
158
159 public void onServiceDisconnected(final ComponentName name) {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000160 // always done on the application main thread, so no need to send message to mHandler
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000161 mService = null;
162 mConnection = null;
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000163 mPendingTasks.clear();
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000164 if (DBG) Log.d(TAG, "onServiceDisconnected - Success");
165 }
166 }
167
168 /**
169 * Checks whether a speech recognition service is available on the system. If this method
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700170 * returns {@code false}, {@link SpeechRecognizer#createSpeechRecognizer(Context)} will
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000171 * fail.
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000172 *
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700173 * @param context with which {@code SpeechRecognizer} will be created
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000174 * @return {@code true} if recognition is available, {@code false} otherwise
175 */
176 public static boolean isRecognitionAvailable(final Context context) {
177 final List<ResolveInfo> list = context.getPackageManager().queryIntentServices(
Valentin Kravtsovcccd63c2010-02-12 14:19:11 +0000178 new Intent(RecognitionService.SERVICE_INTERFACE), 0);
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000179 return list != null && list.size() != 0;
180 }
181
182 /**
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700183 * Factory method to create a new {@code SpeechRecognizer}. Please note that
Valentin Kravtsov11686222010-03-18 07:41:38 +0000184 * {@link #setRecognitionListener(RecognitionListener)} should be called before dispatching any
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700185 * command to the created {@code SpeechRecognizer}, otherwise no notifications will be
Valentin Kravtsov11686222010-03-18 07:41:38 +0000186 * received.
187 *
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700188 * @param context in which to create {@code SpeechRecognizer}
189 * @return a new {@code SpeechRecognizer}
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000190 */
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700191 public static SpeechRecognizer createSpeechRecognizer(final Context context) {
192 return createSpeechRecognizer(context, null);
Mike LeBeau79375f72010-02-18 19:01:47 -0800193 }
194
195 /**
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700196 * Factory method to create a new {@code SpeechRecognizer}. Please note that
Valentin Kravtsov11686222010-03-18 07:41:38 +0000197 * {@link #setRecognitionListener(RecognitionListener)} should be called before dispatching any
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700198 * command to the created {@code SpeechRecognizer}, otherwise no notifications will be
Valentin Kravtsov11686222010-03-18 07:41:38 +0000199 * received.
200 *
Mike LeBeau79375f72010-02-18 19:01:47 -0800201 * Use this version of the method to specify a specific service to direct this
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700202 * {@link SpeechRecognizer} to. Normally you would not use this; use
203 * {@link #createSpeechRecognizer(Context)} instead to use the system default recognition
Valentin Kravtsov11686222010-03-18 07:41:38 +0000204 * service.
Mike LeBeau79375f72010-02-18 19:01:47 -0800205 *
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700206 * @param context in which to create {@code SpeechRecognizer}
Mike LeBeau79375f72010-02-18 19:01:47 -0800207 * @param serviceComponent the {@link ComponentName} of a specific service to direct this
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700208 * {@code SpeechRecognizer} to
209 * @return a new {@code SpeechRecognizer}
Mike LeBeau79375f72010-02-18 19:01:47 -0800210 */
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700211 public static SpeechRecognizer createSpeechRecognizer(final Context context,
Mike LeBeau79375f72010-02-18 19:01:47 -0800212 final ComponentName serviceComponent) {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000213 if (context == null) {
214 throw new IllegalArgumentException("Context cannot be null)");
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000215 }
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000216 checkIsCalledFromMainThread();
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700217 return new SpeechRecognizer(context, serviceComponent);
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000218 }
219
220 /**
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000221 * Sets the listener that will receive all the callbacks. The previous unfinished commands will
222 * be executed with the old listener, while any following command will be executed with the new
223 * listener.
224 *
225 * @param listener listener that will receive all the callbacks from the created
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700226 * {@link SpeechRecognizer}, this must not be null.
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000227 */
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000228 public void setRecognitionListener(RecognitionListener listener) {
229 checkIsCalledFromMainThread();
230 putMessage(Message.obtain(mHandler, MSG_CHANGE_LISTENER, listener));
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000231 }
232
233 /**
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000234 * Starts listening for speech. Please note that
Valentin Kravtsov11686222010-03-18 07:41:38 +0000235 * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise
236 * no notifications will be received.
237 *
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000238 * @param recognizerIntent contains parameters for the recognition to be performed. The intent
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000239 * may also contain optional extras, see {@link RecognizerIntent}. If these values are
240 * not set explicitly, default values will be used by the recognizer.
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000241 */
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000242 public void startListening(final Intent recognizerIntent) {
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000243 if (recognizerIntent == null) {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000244 throw new IllegalArgumentException("intent must not be null");
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000245 }
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000246 checkIsCalledFromMainThread();
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000247 if (mConnection == null) { // first time connection
248 mConnection = new Connection();
Mike LeBeau5d34e9b2010-02-10 19:34:56 -0800249
Mike LeBeaucb0be8a2010-02-11 15:01:27 -0800250 Intent serviceIntent = new Intent(RecognitionService.SERVICE_INTERFACE);
Mike LeBeau5d34e9b2010-02-10 19:34:56 -0800251
Mike LeBeau79375f72010-02-18 19:01:47 -0800252 if (mServiceComponent == null) {
253 String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(),
254 Settings.Secure.VOICE_RECOGNITION_SERVICE);
255
256 if (TextUtils.isEmpty(serviceComponent)) {
257 Log.e(TAG, "no selected voice recognition service");
258 mListener.onError(ERROR_CLIENT);
259 return;
260 }
261
262 serviceIntent.setComponent(ComponentName.unflattenFromString(serviceComponent));
263 } else {
264 serviceIntent.setComponent(mServiceComponent);
Mike LeBeau5d34e9b2010-02-10 19:34:56 -0800265 }
266
Mike LeBeau5d34e9b2010-02-10 19:34:56 -0800267 if (!mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE)) {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000268 Log.e(TAG, "bind to recognition service failed");
269 mConnection = null;
270 mService = null;
271 mListener.onError(ERROR_CLIENT);
272 return;
273 }
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000274 }
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000275 putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent));
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000276 }
277
278 /**
279 * Stops listening for speech. Speech captured so far will be recognized as if the user had
280 * stopped speaking at this point. Note that in the default case, this does not need to be
281 * called, as the speech endpointer will automatically stop the recognizer listening when it
282 * determines speech has completed. However, you can manipulate endpointer parameters directly
283 * using the intent extras defined in {@link RecognizerIntent}, in which case you may sometimes
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000284 * want to manually call this method to stop listening sooner. Please note that
Valentin Kravtsov11686222010-03-18 07:41:38 +0000285 * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise
286 * no notifications will be received.
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000287 */
288 public void stopListening() {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000289 checkIsCalledFromMainThread();
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000290 putMessage(Message.obtain(mHandler, MSG_STOP));
291 }
292
293 /**
294 * Cancels the speech recognition. Please note that
Valentin Kravtsov11686222010-03-18 07:41:38 +0000295 * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise
296 * no notifications will be received.
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000297 */
298 public void cancel() {
299 checkIsCalledFromMainThread();
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000300 putMessage(Message.obtain(mHandler, MSG_CANCEL));
301 }
302
303 private static void checkIsCalledFromMainThread() {
304 if (Looper.myLooper() != Looper.getMainLooper()) {
305 throw new RuntimeException(
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700306 "SpeechRecognizer should be used only from the application's main thread");
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000307 }
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000308 }
309
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000310 private void putMessage(Message msg) {
311 if (mService == null) {
312 mPendingTasks.offer(msg);
313 } else {
314 mHandler.sendMessage(msg);
315 }
316 }
317
318 /** sends the actual message to the service */
319 private void handleStartListening(Intent recognizerIntent) {
Valentin Kravtsov7a3c9d32010-02-05 16:26:04 +0000320 if (!checkOpenConnection()) {
321 return;
322 }
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000323 try {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000324 mService.startListening(recognizerIntent, mListener);
325 if (DBG) Log.d(TAG, "service start listening command succeded");
326 } catch (final RemoteException e) {
327 Log.e(TAG, "startListening() failed", e);
328 mListener.onError(ERROR_CLIENT);
329 }
330 }
331
332 /** sends the actual message to the service */
333 private void handleStopMessage() {
Valentin Kravtsov7a3c9d32010-02-05 16:26:04 +0000334 if (!checkOpenConnection()) {
335 return;
336 }
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000337 try {
338 mService.stopListening(mListener);
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000339 if (DBG) Log.d(TAG, "service stop listening command succeded");
340 } catch (final RemoteException e) {
341 Log.e(TAG, "stopListening() failed", e);
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000342 mListener.onError(ERROR_CLIENT);
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000343 }
344 }
345
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000346 /** sends the actual message to the service */
347 private void handleCancelMessage() {
Valentin Kravtsov7a3c9d32010-02-05 16:26:04 +0000348 if (!checkOpenConnection()) {
349 return;
350 }
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000351 try {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000352 mService.cancel(mListener);
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000353 if (DBG) Log.d(TAG, "service cancel command succeded");
354 } catch (final RemoteException e) {
355 Log.e(TAG, "cancel() failed", e);
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000356 mListener.onError(ERROR_CLIENT);
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000357 }
358 }
Valentin Kravtsov7a3c9d32010-02-05 16:26:04 +0000359
360 private boolean checkOpenConnection() {
361 if (mService != null) {
362 return true;
363 }
364 mListener.onError(ERROR_CLIENT);
365 Log.e(TAG, "not connected to the recognition service");
366 return false;
367 }
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000368
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000369 /** changes the listener */
370 private void handleChangeListener(RecognitionListener listener) {
371 if (DBG) Log.d(TAG, "handleChangeListener, listener=" + listener);
372 mListener.mInternalListener = listener;
373 }
374
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000375 /**
Jean-Michel Trivi2a5d9f92010-03-29 18:31:19 -0700376 * Destroys the {@code SpeechRecognizer} object.
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000377 */
378 public void destroy() {
379 if (mConnection != null) {
380 mContext.unbindService(mConnection);
381 }
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000382 mPendingTasks.clear();
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000383 mService = null;
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000384 mConnection = null;
Valentin Kravtsov1c3cca02010-04-21 22:27:05 +0100385 mListener.mInternalListener = null;
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000386 }
387
388 /**
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000389 * Internal wrapper of IRecognitionListener which will propagate the results to
390 * RecognitionListener
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000391 */
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000392 private class InternalListener extends IRecognitionListener.Stub {
393 private RecognitionListener mInternalListener;
394
395 private final static int MSG_BEGINNING_OF_SPEECH = 1;
396 private final static int MSG_BUFFER_RECEIVED = 2;
397 private final static int MSG_END_OF_SPEECH = 3;
398 private final static int MSG_ERROR = 4;
399 private final static int MSG_READY_FOR_SPEECH = 5;
400 private final static int MSG_RESULTS = 6;
401 private final static int MSG_PARTIAL_RESULTS = 7;
402 private final static int MSG_RMS_CHANGED = 8;
403 private final static int MSG_ON_EVENT = 9;
404
405 private final Handler mInternalHandler = new Handler() {
406 @Override
407 public void handleMessage(Message msg) {
408 if (mInternalListener == null) {
409 return;
410 }
411 switch (msg.what) {
412 case MSG_BEGINNING_OF_SPEECH:
413 mInternalListener.onBeginningOfSpeech();
414 break;
415 case MSG_BUFFER_RECEIVED:
416 mInternalListener.onBufferReceived((byte[]) msg.obj);
417 break;
418 case MSG_END_OF_SPEECH:
419 mInternalListener.onEndOfSpeech();
420 break;
421 case MSG_ERROR:
422 mInternalListener.onError((Integer) msg.obj);
423 break;
424 case MSG_READY_FOR_SPEECH:
425 mInternalListener.onReadyForSpeech((Bundle) msg.obj);
426 break;
427 case MSG_RESULTS:
428 mInternalListener.onResults((Bundle) msg.obj);
429 break;
430 case MSG_PARTIAL_RESULTS:
431 mInternalListener.onPartialResults((Bundle) msg.obj);
432 break;
433 case MSG_RMS_CHANGED:
434 mInternalListener.onRmsChanged((Float) msg.obj);
435 break;
436 case MSG_ON_EVENT:
437 mInternalListener.onEvent(msg.arg1, (Bundle) msg.obj);
438 break;
439 }
440 }
441 };
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000442
443 public void onBeginningOfSpeech() {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000444 Message.obtain(mInternalHandler, MSG_BEGINNING_OF_SPEECH).sendToTarget();
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000445 }
446
447 public void onBufferReceived(final byte[] buffer) {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000448 Message.obtain(mInternalHandler, MSG_BUFFER_RECEIVED, buffer).sendToTarget();
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000449 }
450
451 public void onEndOfSpeech() {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000452 Message.obtain(mInternalHandler, MSG_END_OF_SPEECH).sendToTarget();
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000453 }
454
455 public void onError(final int error) {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000456 Message.obtain(mInternalHandler, MSG_ERROR, error).sendToTarget();
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000457 }
458
459 public void onReadyForSpeech(final Bundle noiseParams) {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000460 Message.obtain(mInternalHandler, MSG_READY_FOR_SPEECH, noiseParams).sendToTarget();
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000461 }
462
463 public void onResults(final Bundle results) {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000464 Message.obtain(mInternalHandler, MSG_RESULTS, results).sendToTarget();
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000465 }
466
467 public void onPartialResults(final Bundle results) {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000468 Message.obtain(mInternalHandler, MSG_PARTIAL_RESULTS, results).sendToTarget();
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000469 }
470
471 public void onRmsChanged(final float rmsdB) {
Valentin Kravtsov3da3cad2010-01-28 14:53:41 +0000472 Message.obtain(mInternalHandler, MSG_RMS_CHANGED, rmsdB).sendToTarget();
473 }
474
475 public void onEvent(final int eventType, final Bundle params) {
476 Message.obtain(mInternalHandler, MSG_ON_EVENT, eventType, eventType, params)
477 .sendToTarget();
Valentin Kravtsov79896bd2010-01-15 11:56:03 +0000478 }
479 }
480}