SpeechRecognizer.java revision 2921cee3048f7e64ba6645d50a1c1705ef9658f8
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 422921cee3048f7e64ba6645d50a1c1705ef9658f8Marc Wilson * invoked only from the main application thread. 432921cee3048f7e64ba6645d50a1c1705ef9658f8Marc Wilson * 442921cee3048f7e64ba6645d50a1c1705ef9658f8Marc Wilson * <p>The implementation of this API is likely to stream audio to remote servers to perform speech 452921cee3048f7e64ba6645d50a1c1705ef9658f8Marc Wilson * recognition. As such this API is not intended to be used for continuous recognition, which would 462921cee3048f7e64ba6645d50a1c1705ef9658f8Marc Wilson * consume a significant amount of battery and bandwidth. 472921cee3048f7e64ba6645d50a1c1705ef9658f8Marc Wilson * 482921cee3048f7e64ba6645d50a1c1705ef9658f8Marc Wilson * <p>Please note that the application must have {@link android.Manifest.permission#RECORD_AUDIO} 492921cee3048f7e64ba6645d50a1c1705ef9658f8Marc Wilson * permission to use this class. 5079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 512a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivipublic class SpeechRecognizer { 5279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** DEBUG value to enable verbose debug prints */ 5379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov private final static boolean DBG = false; 5479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 5579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** Log messages identifier */ 562a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi private static final String TAG = "SpeechRecognizer"; 5779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 5879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 59bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau * Key used to retrieve an {@code ArrayList<String>} from the {@link Bundle} passed to the 6079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * {@link RecognitionListener#onResults(Bundle)} and 6179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * {@link RecognitionListener#onPartialResults(Bundle)} methods. These strings are the possible 6279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * recognition results, where the first element is the most likely candidate. 6379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 643da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final String RESULTS_RECOGNITION = "results_recognition"; 65bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau 66bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau /** 67bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau * Key used to retrieve a float array from the {@link Bundle} passed to the 68bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau * {@link RecognitionListener#onResults(Bundle)} and 69bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau * {@link RecognitionListener#onPartialResults(Bundle)} methods. The array should be 70bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau * the same size as the ArrayList provided in {@link #RESULTS_RECOGNITION}, and should contain 71bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau * values ranging from 0.0 to 1.0, or -1 to represent an unavailable confidence score. 72bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau * <p> 73bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau * Confidence values close to 1.0 indicate high confidence (the speech recognizer is confident 74bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau * that the recognition result is correct), while values close to 0.0 indicate low confidence. 75bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau * <p> 76bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau * This value is optional and might not be provided. 77bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau */ 78bb7cf916b23c78dc640f8bdfb7ad5cd6b09c3636Mike LeBeau public static final String CONFIDENCE_SCORES = "confidence_scores"; 7979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 8079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** Network operation timed out. */ 813da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_NETWORK_TIMEOUT = 1; 8279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 8379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** Other network related errors. */ 843da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_NETWORK = 2; 8579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 8679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** Audio recording error. */ 873da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_AUDIO = 3; 8879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 8979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** Server sends error status. */ 903da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_SERVER = 4; 9179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 9279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** Other client side errors. */ 933da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_CLIENT = 5; 9479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 9579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** No speech input */ 963da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_SPEECH_TIMEOUT = 6; 9779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 9879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** No recognition result matched. */ 993da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_NO_MATCH = 7; 10079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 10179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** RecognitionService busy. */ 1023da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_RECOGNIZER_BUSY = 8; 1033da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 1043da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** Insufficient permissions */ 1053da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public static final int ERROR_INSUFFICIENT_PERMISSIONS = 9; 1063da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 1073da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** action codes */ 1083da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_START = 1; 1093da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_STOP = 2; 1103da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_CANCEL = 3; 1113da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_CHANGE_LISTENER = 4; 1123da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 1133da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** The actual RecognitionService endpoint */ 1143da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private IRecognitionService mService; 1153da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 1163da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** The connection to the actual service */ 1173da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private Connection mConnection; 1183da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 1193da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** Context with which the manager was created */ 1203da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final Context mContext; 12179375f761922b208e2e50ff13a63552c9d01567bMike LeBeau 12279375f761922b208e2e50ff13a63552c9d01567bMike LeBeau /** Component to direct service intent to */ 12379375f761922b208e2e50ff13a63552c9d01567bMike LeBeau private final ComponentName mServiceComponent; 1243da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 1253da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** Handler that will execute the main tasks */ 1263da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private Handler mHandler = new Handler() { 1273da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov @Override 1283da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void handleMessage(Message msg) { 1293da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov switch (msg.what) { 1303da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_START: 1313da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov handleStartListening((Intent) msg.obj); 1323da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 1333da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_STOP: 1343da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov handleStopMessage(); 1353da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 1363da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_CANCEL: 1373da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov handleCancelMessage(); 1383da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 1393da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_CHANGE_LISTENER: 1403da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov handleChangeListener((RecognitionListener) msg.obj); 1413da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 1423da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 1433da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 1443da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov }; 14579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 14679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 1473da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * Temporary queue, saving the messages until the connection will be established, afterwards, 1483da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * only mHandler will receive the messages 14979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 1503da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final Queue<Message> mPendingTasks = new LinkedList<Message>(); 1513da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 1523da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** The Listener that will receive all the callbacks */ 1533da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final InternalListener mListener = new InternalListener(); 15479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 15579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 1562a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * The right way to create a {@code SpeechRecognizer} is by using 1572a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * {@link #createSpeechRecognizer} static factory method 15879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 1592a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi private SpeechRecognizer(final Context context, final ComponentName serviceComponent) { 16079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov mContext = context; 16179375f761922b208e2e50ff13a63552c9d01567bMike LeBeau mServiceComponent = serviceComponent; 16279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 16379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 16479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 1653da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * Basic ServiceConnection that records the mService variable. Additionally, on creation it 1663da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * invokes the {@link IRecognitionService#startListening(Intent, IRecognitionListener)}. 16779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 16879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov private class Connection implements ServiceConnection { 16979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 1703da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void onServiceConnected(final ComponentName name, final IBinder service) { 1713da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov // always done on the application main thread, so no need to send message to mHandler 17279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov mService = IRecognitionService.Stub.asInterface(service); 17379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (DBG) Log.d(TAG, "onServiceConnected - Success"); 1743da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov while (!mPendingTasks.isEmpty()) { 1753da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mHandler.sendMessage(mPendingTasks.poll()); 1763da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 17779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 17879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 17979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onServiceDisconnected(final ComponentName name) { 1803da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov // always done on the application main thread, so no need to send message to mHandler 18179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov mService = null; 18279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov mConnection = null; 1833da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mPendingTasks.clear(); 18479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (DBG) Log.d(TAG, "onServiceDisconnected - Success"); 18579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 18679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 18779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 18879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 18979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * Checks whether a speech recognition service is available on the system. If this method 1902a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * returns {@code false}, {@link SpeechRecognizer#createSpeechRecognizer(Context)} will 1913da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * fail. 19279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * 1932a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * @param context with which {@code SpeechRecognizer} will be created 19479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * @return {@code true} if recognition is available, {@code false} otherwise 19579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 19679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public static boolean isRecognitionAvailable(final Context context) { 19779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov final List<ResolveInfo> list = context.getPackageManager().queryIntentServices( 198cccd63c8e8e989a55cbeeb6c7d253a709139c223Valentin Kravtsov new Intent(RecognitionService.SERVICE_INTERFACE), 0); 19979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov return list != null && list.size() != 0; 20079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 20179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 20279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 2032a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * Factory method to create a new {@code SpeechRecognizer}. Please note that 2041168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * {@link #setRecognitionListener(RecognitionListener)} should be called before dispatching any 2052a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * command to the created {@code SpeechRecognizer}, otherwise no notifications will be 2061168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * received. 2071168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * 2082a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * @param context in which to create {@code SpeechRecognizer} 2092a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * @return a new {@code SpeechRecognizer} 21079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 2112a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi public static SpeechRecognizer createSpeechRecognizer(final Context context) { 2122a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi return createSpeechRecognizer(context, null); 21379375f761922b208e2e50ff13a63552c9d01567bMike LeBeau } 21479375f761922b208e2e50ff13a63552c9d01567bMike LeBeau 21579375f761922b208e2e50ff13a63552c9d01567bMike LeBeau /** 2162a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * Factory method to create a new {@code SpeechRecognizer}. Please note that 2171168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * {@link #setRecognitionListener(RecognitionListener)} should be called before dispatching any 2182a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * command to the created {@code SpeechRecognizer}, otherwise no notifications will be 2191168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * received. 2201168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * 22179375f761922b208e2e50ff13a63552c9d01567bMike LeBeau * Use this version of the method to specify a specific service to direct this 2222a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * {@link SpeechRecognizer} to. Normally you would not use this; use 2232a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * {@link #createSpeechRecognizer(Context)} instead to use the system default recognition 2241168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * service. 22579375f761922b208e2e50ff13a63552c9d01567bMike LeBeau * 2262a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * @param context in which to create {@code SpeechRecognizer} 22779375f761922b208e2e50ff13a63552c9d01567bMike LeBeau * @param serviceComponent the {@link ComponentName} of a specific service to direct this 2282a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * {@code SpeechRecognizer} to 2292a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * @return a new {@code SpeechRecognizer} 23079375f761922b208e2e50ff13a63552c9d01567bMike LeBeau */ 2312a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi public static SpeechRecognizer createSpeechRecognizer(final Context context, 23279375f761922b208e2e50ff13a63552c9d01567bMike LeBeau final ComponentName serviceComponent) { 2333da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov if (context == null) { 2343da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov throw new IllegalArgumentException("Context cannot be null)"); 23579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 2363da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov checkIsCalledFromMainThread(); 2372a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi return new SpeechRecognizer(context, serviceComponent); 23879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 23979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 24079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 2413da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * Sets the listener that will receive all the callbacks. The previous unfinished commands will 2423da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * be executed with the old listener, while any following command will be executed with the new 2433da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * listener. 2443da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * 2453da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * @param listener listener that will receive all the callbacks from the created 2462a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * {@link SpeechRecognizer}, this must not be null. 24779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 2483da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void setRecognitionListener(RecognitionListener listener) { 2493da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov checkIsCalledFromMainThread(); 2503da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov putMessage(Message.obtain(mHandler, MSG_CHANGE_LISTENER, listener)); 25179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 25279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 25379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 2543da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * Starts listening for speech. Please note that 2551168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise 2561168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * no notifications will be received. 2571168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * 25879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * @param recognizerIntent contains parameters for the recognition to be performed. The intent 2593da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * may also contain optional extras, see {@link RecognizerIntent}. If these values are 2603da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * not set explicitly, default values will be used by the recognizer. 26179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 2623da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void startListening(final Intent recognizerIntent) { 26379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (recognizerIntent == null) { 2643da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov throw new IllegalArgumentException("intent must not be null"); 26579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 2663da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov checkIsCalledFromMainThread(); 2673da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov if (mConnection == null) { // first time connection 2683da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mConnection = new Connection(); 2695d34e9b63d5305934dcedac11e8dd658ae23c174Mike LeBeau 270cb0be8a530d6fefdb05f009980c029c4da14bf98Mike LeBeau Intent serviceIntent = new Intent(RecognitionService.SERVICE_INTERFACE); 2715d34e9b63d5305934dcedac11e8dd658ae23c174Mike LeBeau 27279375f761922b208e2e50ff13a63552c9d01567bMike LeBeau if (mServiceComponent == null) { 27379375f761922b208e2e50ff13a63552c9d01567bMike LeBeau String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(), 27479375f761922b208e2e50ff13a63552c9d01567bMike LeBeau Settings.Secure.VOICE_RECOGNITION_SERVICE); 27579375f761922b208e2e50ff13a63552c9d01567bMike LeBeau 27679375f761922b208e2e50ff13a63552c9d01567bMike LeBeau if (TextUtils.isEmpty(serviceComponent)) { 27779375f761922b208e2e50ff13a63552c9d01567bMike LeBeau Log.e(TAG, "no selected voice recognition service"); 27879375f761922b208e2e50ff13a63552c9d01567bMike LeBeau mListener.onError(ERROR_CLIENT); 27979375f761922b208e2e50ff13a63552c9d01567bMike LeBeau return; 28079375f761922b208e2e50ff13a63552c9d01567bMike LeBeau } 28179375f761922b208e2e50ff13a63552c9d01567bMike LeBeau 28279375f761922b208e2e50ff13a63552c9d01567bMike LeBeau serviceIntent.setComponent(ComponentName.unflattenFromString(serviceComponent)); 28379375f761922b208e2e50ff13a63552c9d01567bMike LeBeau } else { 28479375f761922b208e2e50ff13a63552c9d01567bMike LeBeau serviceIntent.setComponent(mServiceComponent); 2855d34e9b63d5305934dcedac11e8dd658ae23c174Mike LeBeau } 2865d34e9b63d5305934dcedac11e8dd658ae23c174Mike LeBeau 2875d34e9b63d5305934dcedac11e8dd658ae23c174Mike LeBeau if (!mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE)) { 2883da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Log.e(TAG, "bind to recognition service failed"); 2893da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mConnection = null; 2903da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mService = null; 2913da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mListener.onError(ERROR_CLIENT); 2923da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov return; 2933da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 29479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 2953da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov putMessage(Message.obtain(mHandler, MSG_START, recognizerIntent)); 29679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 29779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 29879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 29979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * Stops listening for speech. Speech captured so far will be recognized as if the user had 30079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * stopped speaking at this point. Note that in the default case, this does not need to be 30179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * called, as the speech endpointer will automatically stop the recognizer listening when it 30279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * determines speech has completed. However, you can manipulate endpointer parameters directly 30379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov * using the intent extras defined in {@link RecognizerIntent}, in which case you may sometimes 3043da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * want to manually call this method to stop listening sooner. Please note that 3051168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise 3061168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * no notifications will be received. 30779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 30879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void stopListening() { 3093da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov checkIsCalledFromMainThread(); 3103da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov putMessage(Message.obtain(mHandler, MSG_STOP)); 3113da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3123da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 3133da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** 3143da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * Cancels the speech recognition. Please note that 3151168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * {@link #setRecognitionListener(RecognitionListener)} should be called beforehand, otherwise 3161168622bce0a8ab51362daadf4a22ea43dd46c10Valentin Kravtsov * no notifications will be received. 3173da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov */ 3183da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void cancel() { 3193da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov checkIsCalledFromMainThread(); 3203da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov putMessage(Message.obtain(mHandler, MSG_CANCEL)); 3213da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3223da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 3233da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private static void checkIsCalledFromMainThread() { 3243da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov if (Looper.myLooper() != Looper.getMainLooper()) { 3253da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov throw new RuntimeException( 3262a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi "SpeechRecognizer should be used only from the application's main thread"); 3273da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3283da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3293da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 3303da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private void putMessage(Message msg) { 33179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (mService == null) { 3323da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mPendingTasks.offer(msg); 3333da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } else { 3343da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mHandler.sendMessage(msg); 3353da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3363da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3373da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 3383da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** sends the actual message to the service */ 3393da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private void handleStartListening(Intent recognizerIntent) { 3407a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov if (!checkOpenConnection()) { 3417a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov return; 3427a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov } 3433da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov try { 3443da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mService.startListening(recognizerIntent, mListener); 3453da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov if (DBG) Log.d(TAG, "service start listening command succeded"); 3463da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } catch (final RemoteException e) { 3473da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Log.e(TAG, "startListening() failed", e); 3483da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mListener.onError(ERROR_CLIENT); 34979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 3503da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3513da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 3523da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** sends the actual message to the service */ 3533da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private void handleStopMessage() { 3547a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov if (!checkOpenConnection()) { 3557a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov return; 3567a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov } 35779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov try { 3583da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mService.stopListening(mListener); 35979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (DBG) Log.d(TAG, "service stop listening command succeded"); 36079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } catch (final RemoteException e) { 36179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov Log.e(TAG, "stopListening() failed", e); 3623da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mListener.onError(ERROR_CLIENT); 36379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 36479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 36579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 3663da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** sends the actual message to the service */ 3673da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private void handleCancelMessage() { 3687a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov if (!checkOpenConnection()) { 3697a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov return; 3707a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov } 37179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov try { 3723da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mService.cancel(mListener); 37379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (DBG) Log.d(TAG, "service cancel command succeded"); 37479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } catch (final RemoteException e) { 37579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov Log.e(TAG, "cancel() failed", e); 3763da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mListener.onError(ERROR_CLIENT); 37779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 37879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 3797a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov 3807a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov private boolean checkOpenConnection() { 3817a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov if (mService != null) { 3827a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov return true; 3837a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov } 3847a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov mListener.onError(ERROR_CLIENT); 3857a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov Log.e(TAG, "not connected to the recognition service"); 3867a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov return false; 3877a3c9d31bbc57f76d18d465eca605f28dc206f00Valentin Kravtsov } 38879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 3893da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov /** changes the listener */ 3903da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private void handleChangeListener(RecognitionListener listener) { 3913da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov if (DBG) Log.d(TAG, "handleChangeListener, listener=" + listener); 3923da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mListener.mInternalListener = listener; 3933da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 3943da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 39579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 3962a5d9f9b577376768372837723f0f42098aba13bJean-Michel Trivi * Destroys the {@code SpeechRecognizer} object. 39779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 39879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void destroy() { 39979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov if (mConnection != null) { 40079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov mContext.unbindService(mConnection); 40179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 4023da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mPendingTasks.clear(); 40379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov mService = null; 4043da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mConnection = null; 4051c3cca0abed55516d2c67f2f11fc888a6a66f341Valentin Kravtsov mListener.mInternalListener = null; 40679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 40779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 40879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov /** 4093da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * Internal wrapper of IRecognitionListener which will propagate the results to 4103da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov * RecognitionListener 41179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov */ 4123da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private class InternalListener extends IRecognitionListener.Stub { 4133da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private RecognitionListener mInternalListener; 4143da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 4153da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_BEGINNING_OF_SPEECH = 1; 4163da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_BUFFER_RECEIVED = 2; 4173da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_END_OF_SPEECH = 3; 4183da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_ERROR = 4; 4193da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_READY_FOR_SPEECH = 5; 4203da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_RESULTS = 6; 4213da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_PARTIAL_RESULTS = 7; 4223da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_RMS_CHANGED = 8; 4233da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final static int MSG_ON_EVENT = 9; 4243da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 4253da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov private final Handler mInternalHandler = new Handler() { 4263da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov @Override 4273da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void handleMessage(Message msg) { 4283da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov if (mInternalListener == null) { 4293da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov return; 4303da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 4313da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov switch (msg.what) { 4323da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_BEGINNING_OF_SPEECH: 4333da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onBeginningOfSpeech(); 4343da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4353da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_BUFFER_RECEIVED: 4363da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onBufferReceived((byte[]) msg.obj); 4373da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4383da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_END_OF_SPEECH: 4393da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onEndOfSpeech(); 4403da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4413da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_ERROR: 4423da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onError((Integer) msg.obj); 4433da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4443da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_READY_FOR_SPEECH: 4453da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onReadyForSpeech((Bundle) msg.obj); 4463da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4473da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_RESULTS: 4483da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onResults((Bundle) msg.obj); 4493da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4503da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_PARTIAL_RESULTS: 4513da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onPartialResults((Bundle) msg.obj); 4523da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4533da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_RMS_CHANGED: 4543da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onRmsChanged((Float) msg.obj); 4553da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4563da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov case MSG_ON_EVENT: 4573da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov mInternalListener.onEvent(msg.arg1, (Bundle) msg.obj); 4583da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov break; 4593da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 4603da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 4613da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov }; 46279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 46379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onBeginningOfSpeech() { 4643da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_BEGINNING_OF_SPEECH).sendToTarget(); 46579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 46679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 46779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onBufferReceived(final byte[] buffer) { 4683da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_BUFFER_RECEIVED, buffer).sendToTarget(); 46979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 47079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 47179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onEndOfSpeech() { 4723da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_END_OF_SPEECH).sendToTarget(); 47379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 47479896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 47579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onError(final int error) { 4763da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_ERROR, error).sendToTarget(); 47779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 47879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 47979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onReadyForSpeech(final Bundle noiseParams) { 4803da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_READY_FOR_SPEECH, noiseParams).sendToTarget(); 48179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 48279896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 48379896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onResults(final Bundle results) { 4843da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_RESULTS, results).sendToTarget(); 48579896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 48679896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 48779896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onPartialResults(final Bundle results) { 4883da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_PARTIAL_RESULTS, results).sendToTarget(); 48979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 49079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov 49179896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov public void onRmsChanged(final float rmsdB) { 4923da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_RMS_CHANGED, rmsdB).sendToTarget(); 4933da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov } 4943da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov 4953da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov public void onEvent(final int eventType, final Bundle params) { 4963da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov Message.obtain(mInternalHandler, MSG_ON_EVENT, eventType, eventType, params) 4973da3cad97269d694a6153771fb4a0c3775ca6ab5Valentin Kravtsov .sendToTarget(); 49879896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 49979896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov } 50079896bd123aa3bc69c6455d4e2ddf2b2b555e6e5Valentin Kravtsov} 501