179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov/* 279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * Copyright (C) 2010 The Android Open Source Project 379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * 479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * Licensed under the Apache License, Version 2.0 (the "License"); 579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * you may not use this file except in compliance with the License. 679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * You may obtain a copy of the License at 779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * 879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * http://www.apache.org/licenses/LICENSE-2.0 979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * 1079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * Unless required by applicable law or agreed to in writing, software 1179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * distributed under the License is distributed on an "AS IS" BASIS, 1279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * See the License for the specific language governing permissions and 1479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * limitations under the License. 1579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 1679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 1779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsovpackage android.speech; 1879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 1979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsovimport android.content.ComponentName; 2079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsovimport android.content.Context; 2179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsovimport android.content.Intent; 2279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsovimport android.content.ServiceConnection; 2379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsovimport android.content.pm.ResolveInfo; 2479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsovimport android.os.Bundle; 253da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsovimport android.os.Handler; 2679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsovimport android.os.IBinder; 273da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsovimport android.os.Looper; 283da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsovimport android.os.Message; 2979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsovimport android.os.RemoteException; 305d34e9b63d5305934dcedac11e8dd658ae23c174Mike LeBeauimport android.provider.Settings; 315d34e9b63d5305934dcedac11e8dd658ae23c174Mike LeBeauimport android.text.TextUtils; 3279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsovimport android.util.Log; 3379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 343da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsovimport java.util.LinkedList; 3579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsovimport java.util.List; 363da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsovimport java.util.Queue; 3779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 3879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov/** 3979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * This class provides access to the speech recognition service. This service allows access to the 4079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * speech recognizer. Do not instantiate this class directly, instead, call 412a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * {@link SpeechRecognizer#createSpeechRecognizer(Context)}. This class's methods must be 423da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * invoked only from the main application thread. Please note that the application must have 433da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * {@link android.Manifest.permission#RECORD_AUDIO} permission to use this class. 4479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 452a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivipublic class SpeechRecognizer { 4679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** DEBUG value to enable verbose debug prints */ 4779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov private final static boolean DBG = false; 4879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 4979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** Log messages identifier */ 502a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi private static final String TAG = "SpeechRecognizer"; 5179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 5279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 5379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * Used to retrieve an {@code ArrayList<String>} from the {@link Bundle} passed to the 5479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * {@link RecognitionListener#onResults(Bundle)} and 5579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * {@link RecognitionListener#onPartialResults(Bundle)} methods. These strings are the possible 5679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * recognition results, where the first element is the most likely candidate. 5779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 583da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final String RESULTS_RECOGNITION = "results_recognition"; 5979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 6079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** Network operation timed out. */ 613da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_NETWORK_TIMEOUT = 1; 6279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 6379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** Other network related errors. */ 643da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_NETWORK = 2; 6579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 6679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** Audio recording error. */ 673da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_AUDIO = 3; 6879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 6979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** Server sends error status. */ 703da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_SERVER = 4; 7179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 7279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** Other client side errors. */ 733da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_CLIENT = 5; 7479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 7579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** No speech input */ 763da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_SPEECH_TIMEOUT = 6; 7779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 7879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** No recognition result matched. */ 793da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_NO_MATCH = 7; 8079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 8179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** RecognitionService busy. */ 823da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_RECOGNIZER_BUSY = 8; 833da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 843da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** Insufficient permissions */ 853da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_INSUFFICIENT_PERMISSIONS = 9; 863da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 873da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** action codes */ 883da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_START = 1; 893da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_STOP = 2; 903da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_CANCEL = 3; 913da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_CHANGE_LISTENER = 4; 923da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 933da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** The actual RecognitionService endpoint */ 943da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private IRecognitionService mService; 953da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 963da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** The connection to the actual service */ 973da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private Connection mConnection; 983da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 993da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** Context with which the manager was created */ 1003da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final Context mContext; 10179375f761922b208e2e50ff13a63552c9d01567bMike LeBeau 10279375f761922b208e2e50ff13a63552c9d01567bMike LeBeau /** Component to direct service intent to */ 10379375f761922b208e2e50ff13a63552c9d01567bMike LeBeau private final ComponentName mServiceComponent; 1043da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 1053da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** Handler that will execute the main tasks */ 1063da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private Handler mHandler = new Handler() { 1073da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov @Override 1083da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void handleMessage(Message msg) { 1093da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov switch (msg.what) { 1103da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_START: 1113da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov handleStartListening((Intent) msg.obj); 1123da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 1133da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_STOP: 1143da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov handleStopMessage(); 1153da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 1163da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_CANCEL: 1173da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov handleCancelMessage(); 1183da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 1193da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_CHANGE_LISTENER: 1203da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov handleChangeListener((RecognitionListener) msg.obj); 1213da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 1223da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 1233da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 1243da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov }; 12579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 12679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 1273da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * Temporary queue, saving the messages until the connection will be established, afterwards, 1283da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * only mHandler will receive the messages 12979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 1303da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final Queue<Message> mPendingTasks = new LinkedList<Message>(); 1313da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 1323da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** The Listener that will receive all the callbacks */ 1333da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final InternalListener mListener = new InternalListener(); 13479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 13579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 1362a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * The right way to create a {@code SpeechRecognizer} is by using 1372a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * {@link #createSpeechRecognizer} static factory method 13879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 1392a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi private SpeechRecognizer(final Context context, final ComponentName serviceComponent) { 14079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov mContext = context; 14179375f761922b208e2e50ff13a63552c9d01567bMike LeBeau mServiceComponent = serviceComponent; 14279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 14379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 14479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 1453da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * Basic ServiceConnection that records the mService variable. Additionally, on creation it 1463da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * invokes the {@link IRecognitionService#startListening(Intent, IRecognitionListener)}. 14779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 14879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov private class Connection implements ServiceConnection { 14979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 1503da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void onServiceConnected(final ComponentName name, final IBinder service) { 1513da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov // always done on the application main thread, so no need to send message to mHandler 15279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov mService = IRecognitionService.Stub.asInterface(service); 15379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (DBG) Log.d(TAG, "onServiceConnected - Success"); 1543da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov while (!mPendingTasks.isEmpty()) { 1553da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mHandler.sendMessage(mPendingTasks.poll()); 1563da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 15779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 15879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 15979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onServiceDisconnected(final ComponentName name) { 1603da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov // always done on the application main thread, so no need to send message to mHandler 16179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov mService = null; 16279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov mConnection = null; 1633da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mPendingTasks.clear(); 16479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (DBG) Log.d(TAG, "onServiceDisconnected - Success"); 16579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 16679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 16779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 16879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 16979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * Checks whether a speech recognition service is available on the system. If this method 1702a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * returns {@code false}, {@link SpeechRecognizer#createSpeechRecognizer(Context)} will 1713da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * fail. 17279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * 1732a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * @param context with which {@code SpeechRecognizer} will be created 17479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * @return {@code true} if recognition is available, {@code false} otherwise 17579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 17679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public static boolean isRecognitionAvailable(final Context context) { 17779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov final List<ResolveInfo> list = context.getPackageManager().queryIntentServices( 178cccd63c8e8e989a55cbeeb6c7d253a709139c223Valentin Kravtsov new Intent(RecognitionService.SERVICE_INTERFACE), 0); 17979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov return list != null && list.size() != 0; 18079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 18179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 18279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 1832a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * Factory method to create a new {@code SpeechRecognizer}. Please note that 1841168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * {@link #setRecognitionListener(RecognitionListener)} should be called before dispatching any 1852a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * command to the created {@code SpeechRecognizer}, otherwise no notifications will be 1861168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * received. 1871168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * 1882a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * @param context in which to create {@code SpeechRecognizer} 1892a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * @return a new {@code SpeechRecognizer} 19079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 1912a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi public static SpeechRecognizer createSpeechRecognizer(final Context context) { 1922a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi return createSpeechRecognizer(context, null); 19379375f761922b208e2e50ff13a63552c9d01567bMike LeBeau } 19479375f761922b208e2e50ff13a63552c9d01567bMike LeBeau 19579375f761922b208e2e50ff13a63552c9d01567bMike LeBeau /** 1962a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * Factory method to create a new {@code SpeechRecognizer}. Please note that 1971168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * {@link #setRecognitionListener(RecognitionListener)} should be called before dispatching any 1982a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * command to the created {@code SpeechRecognizer}, otherwise no notifications will be 1991168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * received. 2001168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * 20179375f761922b208e2e50ff13a63552c9d01567bMike LeBeau * Use this version of the method to specify a specific service to direct this 2022a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * {@link SpeechRecognizer} to. Normally you would not use this; use 2032a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * {@link #createSpeechRecognizer(Context)} instead to use the system default recognition 2041168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * service. 20579375f761922b208e2e50ff13a63552c9d01567bMike LeBeau * 2062a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * @param context in which to create {@code SpeechRecognizer} 20779375f761922b208e2e50ff13a63552c9d01567bMike LeBeau * @param serviceComponent the {@link ComponentName} of a specific service to direct this 2082a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * {@code SpeechRecognizer} to 2092a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * @return a new {@code SpeechRecognizer} 21079375f761922b208e2e50ff13a63552c9d01567bMike LeBeau */ 2112a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi public static SpeechRecognizer createSpeechRecognizer(final Context context, 21279375f761922b208e2e50ff13a63552c9d01567bMike LeBeau final ComponentName serviceComponent) { 2133da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov if (context == null) { 2143da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov throw new IllegalArgumentException("Context cannot be null)"); 21579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 2163da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov checkIsCalledFromMainThread(); 2172a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi return new SpeechRecognizer(context, serviceComponent); 21879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 21979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 22079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 2213da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * Sets the listener that will receive all the callbacks. The previous unfinished commands will 2223da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * be executed with the old listener, while any following command will be executed with the new 2233da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * listener. 2243da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * 2253da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * @param listener listener that will receive all the callbacks from the created 2262a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * {@link SpeechRecognizer}, this must not be null. 22779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 2283da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void setRecognitionListener(RecognitionListener listener) { 2293da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov checkIsCalledFromMainThread(); 2303da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov putMessage(Message.obtain(mHandler, MSG_CHANGE_LISTENER, listener)); 23179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 23279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 23379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 2343da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * Starts listening for speech. Please note that 2351168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise 2361168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * no notifications will be received. 2371168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * 23879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * @param recognizerIntent contains parameters for the recognition to be performed. The intent 2393da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * may also contain optional extras, see {@link RecognizerIntent}. If these values are 2403da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * not set explicitly, default values will be used by the recognizer. 24179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 2423da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void startListening(final Intent recognizerIntent) { 24379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (recognizerIntent == null) { 2443da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov throw new IllegalArgumentException("intent must not be null"); 24579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 2463da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov checkIsCalledFromMainThread(); 2473da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov if (mConnection == null) { // first time connection 2483da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mConnection = new Connection(); 2495d34e9b63d5305934dcedac11e8dd658ae23c174Mike LeBeau 250cb0be8a530d6fefdb05f009980c029c4da14bf98Mike LeBeau Intent serviceIntent = new Intent(RecognitionService.SERVICE_INTERFACE); 2515d34e9b63d5305934dcedac11e8dd658ae23c174Mike LeBeau 25279375f761922b208e2e50ff13a63552c9d01567bMike LeBeau if (mServiceComponent == null) { 25379375f761922b208e2e50ff13a63552c9d01567bMike LeBeau String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(), 25479375f761922b208e2e50ff13a63552c9d01567bMike LeBeau Settings.Secure.VOICE_RECOGNITION_SERVICE); 25579375f761922b208e2e50ff13a63552c9d01567bMike LeBeau 25679375f761922b208e2e50ff13a63552c9d01567bMike LeBeau if (TextUtils.isEmpty(serviceComponent)) { 25779375f761922b208e2e50ff13a63552c9d01567bMike LeBeau Log.e(TAG, "no selected voice recognition service"); 25879375f761922b208e2e50ff13a63552c9d01567bMike LeBeau mListener.onError(ERROR_CLIENT); 25979375f761922b208e2e50ff13a63552c9d01567bMike LeBeau return; 26079375f761922b208e2e50ff13a63552c9d01567bMike LeBeau } 26179375f761922b208e2e50ff13a63552c9d01567bMike LeBeau 26279375f761922b208e2e50ff13a63552c9d01567bMike LeBeau serviceIntent.setComponent(ComponentName.unflattenFromString(serviceComponent)); 26379375f761922b208e2e50ff13a63552c9d01567bMike LeBeau } else { 26479375f761922b208e2e50ff13a63552c9d01567bMike LeBeau serviceIntent.setComponent(mServiceComponent); 2655d34e9b63d5305934dcedac11e8dd658ae23c174Mike LeBeau } 2665d34e9b63d5305934dcedac11e8dd658ae23c174Mike LeBeau 2675d34e9b63d5305934dcedac11e8dd658ae23c174Mike LeBeau if (!mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE)) { 2683da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Log.e(TAG, "bind to recognition service failed"); 2693da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mConnection = null; 2703da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mService = null; 2713da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mListener.onError(ERROR_CLIENT); 2723da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov return; 2733da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 27479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 2753da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent)); 27679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 27779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 27879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 27979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * Stops listening for speech. Speech captured so far will be recognized as if the user had 28079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * stopped speaking at this point. Note that in the default case, this does not need to be 28179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * called, as the speech endpointer will automatically stop the recognizer listening when it 28279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * determines speech has completed. However, you can manipulate endpointer parameters directly 28379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * using the intent extras defined in {@link RecognizerIntent}, in which case you may sometimes 2843da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * want to manually call this method to stop listening sooner. Please note that 2851168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise 2861168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * no notifications will be received. 28779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 28879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void stopListening() { 2893da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov checkIsCalledFromMainThread(); 2903da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov putMessage(Message.obtain(mHandler, MSG_STOP)); 2913da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 2923da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 2933da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** 2943da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * Cancels the speech recognition. Please note that 2951168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise 2961168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * no notifications will be received. 2973da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov */ 2983da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void cancel() { 2993da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov checkIsCalledFromMainThread(); 3003da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov putMessage(Message.obtain(mHandler, MSG_CANCEL)); 3013da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3023da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 3033da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private static void checkIsCalledFromMainThread() { 3043da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov if (Looper.myLooper() != Looper.getMainLooper()) { 3053da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov throw new RuntimeException( 3062a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi "SpeechRecognizer should be used only from the application's main thread"); 3073da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3083da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3093da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 3103da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private void putMessage(Message msg) { 31179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (mService == null) { 3123da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mPendingTasks.offer(msg); 3133da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } else { 3143da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mHandler.sendMessage(msg); 3153da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3163da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3173da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 3183da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** sends the actual message to the service */ 3193da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private void handleStartListening(Intent recognizerIntent) { 3207a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov if (!checkOpenConnection()) { 3217a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov return; 3227a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov } 3233da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov try { 3243da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mService.startListening(recognizerIntent, mListener); 3253da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov if (DBG) Log.d(TAG, "service start listening command succeded"); 3263da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } catch (final RemoteException e) { 3273da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Log.e(TAG, "startListening() failed", e); 3283da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mListener.onError(ERROR_CLIENT); 32979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 3303da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3313da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 3323da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** sends the actual message to the service */ 3333da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private void handleStopMessage() { 3347a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov if (!checkOpenConnection()) { 3357a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov return; 3367a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov } 33779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov try { 3383da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mService.stopListening(mListener); 33979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (DBG) Log.d(TAG, "service stop listening command succeded"); 34079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } catch (final RemoteException e) { 34179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov Log.e(TAG, "stopListening() failed", e); 3423da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mListener.onError(ERROR_CLIENT); 34379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 34479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 34579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 3463da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** sends the actual message to the service */ 3473da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private void handleCancelMessage() { 3487a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov if (!checkOpenConnection()) { 3497a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov return; 3507a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov } 35179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov try { 3523da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mService.cancel(mListener); 35379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (DBG) Log.d(TAG, "service cancel command succeded"); 35479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } catch (final RemoteException e) { 35579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov Log.e(TAG, "cancel() failed", e); 3563da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mListener.onError(ERROR_CLIENT); 35779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 35879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 3597a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov 3607a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov private boolean checkOpenConnection() { 3617a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov if (mService != null) { 3627a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov return true; 3637a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov } 3647a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov mListener.onError(ERROR_CLIENT); 3657a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov Log.e(TAG, "not connected to the recognition service"); 3667a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov return false; 3677a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov } 36879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 3693da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** changes the listener */ 3703da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private void handleChangeListener(RecognitionListener listener) { 3713da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov if (DBG) Log.d(TAG, "handleChangeListener, listener=" + listener); 3723da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mListener.mInternalListener = listener; 3733da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3743da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 37579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 3762a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * Destroys the {@code SpeechRecognizer} object. 37779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 37879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void destroy() { 37979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (mConnection != null) { 38079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov mContext.unbindService(mConnection); 38179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 3823da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mPendingTasks.clear(); 38379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov mService = null; 3843da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mConnection = null; 3851c3cca0abed55516d2c67f2f11fc888a6a66f341Valentin Kravtsov mListener.mInternalListener = null; 38679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 38779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 38879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 3893da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * Internal wrapper of IRecognitionListener which will propagate the results to 3903da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * RecognitionListener 39179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 3923da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private class InternalListener extends IRecognitionListener.Stub { 3933da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private RecognitionListener mInternalListener; 3943da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 3953da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_BEGINNING_OF_SPEECH = 1; 3963da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_BUFFER_RECEIVED = 2; 3973da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_END_OF_SPEECH = 3; 3983da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_ERROR = 4; 3993da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_READY_FOR_SPEECH = 5; 4003da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_RESULTS = 6; 4013da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_PARTIAL_RESULTS = 7; 4023da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_RMS_CHANGED = 8; 4033da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_ON_EVENT = 9; 4043da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 4053da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final Handler mInternalHandler = new Handler() { 4063da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov @Override 4073da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void handleMessage(Message msg) { 4083da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov if (mInternalListener == null) { 4093da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov return; 4103da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 4113da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov switch (msg.what) { 4123da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_BEGINNING_OF_SPEECH: 4133da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onBeginningOfSpeech(); 4143da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4153da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_BUFFER_RECEIVED: 4163da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onBufferReceived((byte[]) msg.obj); 4173da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4183da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_END_OF_SPEECH: 4193da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onEndOfSpeech(); 4203da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4213da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_ERROR: 4223da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onError((Integer) msg.obj); 4233da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4243da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_READY_FOR_SPEECH: 4253da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onReadyForSpeech((Bundle) msg.obj); 4263da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4273da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_RESULTS: 4283da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onResults((Bundle) msg.obj); 4293da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4303da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_PARTIAL_RESULTS: 4313da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onPartialResults((Bundle) msg.obj); 4323da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4333da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_RMS_CHANGED: 4343da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onRmsChanged((Float) msg.obj); 4353da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4363da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_ON_EVENT: 4373da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onEvent(msg.arg1, (Bundle) msg.obj); 4383da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4393da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 4403da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 4413da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov }; 44279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 44379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onBeginningOfSpeech() { 4443da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_BEGINNING_OF_SPEECH).sendToTarget(); 44579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 44679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 44779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onBufferReceived(final byte[] buffer) { 4483da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_BUFFER_RECEIVED, buffer).sendToTarget(); 44979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 45079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 45179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onEndOfSpeech() { 4523da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_END_OF_SPEECH).sendToTarget(); 45379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 45479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 45579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onError(final int error) { 4563da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_ERROR, error).sendToTarget(); 45779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 45879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 45979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onReadyForSpeech(final Bundle noiseParams) { 4603da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_READY_FOR_SPEECH, noiseParams).sendToTarget(); 46179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 46279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 46379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onResults(final Bundle results) { 4643da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_RESULTS, results).sendToTarget(); 46579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 46679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 46779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onPartialResults(final Bundle results) { 4683da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_PARTIAL_RESULTS, results).sendToTarget(); 46979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 47079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 47179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onRmsChanged(final float rmsdB) { 4723da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_RMS_CHANGED, rmsdB).sendToTarget(); 4733da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 4743da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 4753da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void onEvent(final int eventType, final Bundle params) { 4763da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_ON_EVENT, eventType, eventType, params) 4773da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov .sendToTarget(); 47879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 47979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 48079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov} 481