Android语音识别连续服务

我试图创build一个服务来运行Android 4.2中的连续语音识别。 使用这个链接( Android语音识别作为Android 4.1和4.2的服务)的答案,我创build了一个从一个Activity运行的服务。 我的问题是,在handleMessage方法中访问mTarget.mAudioManagermTarget.mSpeechRecognizerIntent时,我得到空exception。 目标(和从它创build的mTarget对象) 不是null ,但它里面的所有对象都是。

我在这里做错了什么?

相关的活动代码(从activity中调用的静态方法,activityContext是调用此方法的活动):

 public static void init(Context context) { voiceCommandService = new VoiceCommandService(); activityContext = context; } public static void startContinuousListening() { Intent service = new Intent(activityContext, VoiceCommandService.class); activityContext.startService(service); Message msg = new Message(); msg.what = VoiceCommandService.MSG_RECOGNIZER_START_LISTENING; try { voiceCommandService.mServerMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } 

服务代码:

 public class VoiceCommandService extends Service { protected AudioManager mAudioManager; protected SpeechRecognizer mSpeechRecognizer; protected Intent mSpeechRecognizerIntent; protected final Messenger mServerMessenger = new Messenger(new IncomingHandler(this)); protected boolean mIsListening; protected volatile boolean mIsCountDownOn; static final int MSG_RECOGNIZER_START_LISTENING = 1; static final int MSG_RECOGNIZER_CANCEL = 2; @Override public void onCreate() { super.onCreate(); mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this); mSpeechRecognizer.setRecognitionListener(new SpeechRecognitionListener()); mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, this.getPackageName()); } protected static class IncomingHandler extends Handler { private WeakReference<VoiceCommandService> mtarget; IncomingHandler(VoiceCommandService target) { mtarget = new WeakReference<VoiceCommandService>(target); } @Override public void handleMessage(Message msg) { final VoiceCommandService target = mtarget.get(); switch (msg.what) { case MSG_RECOGNIZER_START_LISTENING: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // turn off beep sound target.mAudioManager.setStreamMute(AudioManager.STREAM_SYSTEM, true); } if (!target.mIsListening) { target.mSpeechRecognizer.startListening(target.mSpeechRecognizerIntent); target.mIsListening = true; //Log.d(TAG, "message start listening"); //$NON-NLS-1$ } break; case MSG_RECOGNIZER_CANCEL: target.mSpeechRecognizer.cancel(); target.mIsListening = false; //Log.d(TAG, "message canceled recognizer"); //$NON-NLS-1$ break; } } } // Count down timer for Jelly Bean work around protected CountDownTimer mNoSpeechCountDown = new CountDownTimer(5000, 5000) { @Override public void onTick(long millisUntilFinished) { // TODO Auto-generated method stub } @Override public void onFinish() { mIsCountDownOn = false; Message message = Message.obtain(null, MSG_RECOGNIZER_CANCEL); try { mServerMessenger.send(message); message = Message.obtain(null, MSG_RECOGNIZER_START_LISTENING); mServerMessenger.send(message); } catch (RemoteException e) { } } }; @Override public void onDestroy() { super.onDestroy(); if (mIsCountDownOn) { mNoSpeechCountDown.cancel(); } if (mSpeechRecognizer != null) { mSpeechRecognizer.destroy(); } } protected class SpeechRecognitionListener implements RecognitionListener { private static final String TAG = "SpeechRecognitionListener"; @Override public void onBeginningOfSpeech() { // speech input will be processed, so there is no need for count down anymore if (mIsCountDownOn) { mIsCountDownOn = false; mNoSpeechCountDown.cancel(); } //Log.d(TAG, "onBeginingOfSpeech"); //$NON-NLS-1$ } @Override public void onBufferReceived(byte[] buffer) { } @Override public void onEndOfSpeech() { //Log.d(TAG, "onEndOfSpeech"); //$NON-NLS-1$ } @Override public void onError(int error) { if (mIsCountDownOn) { mIsCountDownOn = false; mNoSpeechCountDown.cancel(); } mIsListening = false; Message message = Message.obtain(null, MSG_RECOGNIZER_START_LISTENING); try { mServerMessenger.send(message); } catch (RemoteException e) { } //Log.d(TAG, "error = " + error); //$NON-NLS-1$ } @Override public void onEvent(int eventType, Bundle params) { } @Override public void onPartialResults(Bundle partialResults) { } @Override public void onReadyForSpeech(Bundle params) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { mIsCountDownOn = true; mNoSpeechCountDown.start(); mAudioManager.setStreamMute(AudioManager.STREAM_SYSTEM, false); } Log.d(TAG, "onReadyForSpeech"); //$NON-NLS-1$ } @Override public void onResults(Bundle results) { //Log.d(TAG, "onResults"); //$NON-NLS-1$ } @Override public void onRmsChanged(float rmsdB) { } } @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null; } } 

Solutions Collecting From Web of "Android语音识别连续服务"

MainActivity中的类成员

 private int mBindFlag; private Messenger mServiceMessenger; 

onCreate()启动服务

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent service = new Intent(activityContext, VoiceCommandService.class); activityContext.startService(service); mBindFlag = Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH ? 0 : Context.BIND_ABOVE_CLIENT; } 

onStart()绑定服务

 @Override protected void onStart() { super.onStart(); bindService(new Intent(this, VoiceCommandService.class), mServiceConnection, mBindFlag); } @Override protected void onStop() { super.onStop(); if (mServiceMessenger != null) { unbindService(mServiceConnection); mServiceMessenger = null; } } 

mServiceConnection成员

 private final ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (DEBUG) {Log.d(TAG, "onServiceConnected");} //$NON-NLS-1$ mServiceMessenger = new Messenger(service); Message msg = new Message(); msg.what = VoiceCommandService.MSG_RECOGNIZER_START_LISTENING; try { mServiceMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { if (DEBUG) {Log.d(TAG, "onServiceDisconnected");} //$NON-NLS-1$ mServiceMessenger = null; } }; // mServiceConnection 

在服务中

 @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind"); //$NON-NLS-1$ return mServerMessenger.getBinder(); }