alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Android example source code file (RecognitionService.java)

This example Android source code file (RecognitionService.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Android by Example" TM.

Java - Android tags/keywords

android, annotate, annotations, app, callback, content, dbg, handler, intent, irecognitionlistener, msg_cancel, msg_start_listening, msg_stop_listening, os, override, recognitionservicebinder, record_audio, remoteexception, startlisteningargs, string

The RecognitionService.java Android example source code

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package android.speech;

import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;

/**
 * This class provides a base class for recognition service implementations. This class should be
 * extended only in case you wish to implement a new speech recognizer. Please note that the
 * implementation of this service is stateless.
 */
public abstract class RecognitionService extends Service {
    /**
     * The {@link Intent} that must be declared as handled by the service.
     */
    @SdkConstant(SdkConstantType.SERVICE_ACTION)
    public static final String SERVICE_INTERFACE = "android.speech.RecognitionService";
    
    /**
     * Name under which a RecognitionService component publishes information about itself.
     * This meta-data should reference an XML resource containing a
     * <code><{@link android.R.styleable#RecognitionService recognition-service}> tag.
     */
    public static final String SERVICE_META_DATA = "android.speech";

    /** Log messages identifier */
    private static final String TAG = "RecognitionService";

    /** Debugging flag */
    private static final boolean DBG = false;

    /** Binder of the recognition service */
    private RecognitionServiceBinder mBinder = new RecognitionServiceBinder(this);

    /**
     * The current callback of an application that invoked the
     * {@link RecognitionService#onStartListening(Intent, Callback)} method
     */
    private Callback mCurrentCallback = null;

    private static final int MSG_START_LISTENING = 1;

    private static final int MSG_STOP_LISTENING = 2;

    private static final int MSG_CANCEL = 3;

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_START_LISTENING:
                    StartListeningArgs args = (StartListeningArgs) msg.obj;
                    dispatchStartListening(args.mIntent, args.mListener);
                    break;
                case MSG_STOP_LISTENING:
                    dispatchStopListening((IRecognitionListener) msg.obj);
                    break;
                case MSG_CANCEL:
                    dispatchCancel((IRecognitionListener) msg.obj);
            }
        }
    };

    private void dispatchStartListening(Intent intent, IRecognitionListener listener) {
        if (mCurrentCallback == null) {
            if (DBG) Log.d(TAG, "created new mCurrentCallback, listener = " + listener.asBinder());
            mCurrentCallback = new Callback(listener);
            RecognitionService.this.onStartListening(intent, mCurrentCallback);
        } else {
            try {
                listener.onError(SpeechRecognizer.ERROR_RECOGNIZER_BUSY);
            } catch (RemoteException e) {
                Log.d(TAG, "onError call from startListening failed");
            }
            Log.i(TAG, "concurrent startListening received - ignoring this call");
        }
    }

    private void dispatchStopListening(IRecognitionListener listener) {
        try {
            if (mCurrentCallback == null) {
                listener.onError(SpeechRecognizer.ERROR_CLIENT);
                Log.w(TAG, "stopListening called with no preceding startListening - ignoring");
            } else if (mCurrentCallback.mListener.asBinder() != listener.asBinder()) {
                listener.onError(SpeechRecognizer.ERROR_RECOGNIZER_BUSY);
                Log.w(TAG, "stopListening called by other caller than startListening - ignoring");
            } else { // the correct state
                RecognitionService.this.onStopListening(mCurrentCallback);
            }
        } catch (RemoteException e) { // occurs if onError fails
            Log.d(TAG, "onError call from stopListening failed");
        }
    }

    private void dispatchCancel(IRecognitionListener listener) {
        if (mCurrentCallback == null) {
            if (DBG) Log.d(TAG, "cancel called with no preceding startListening - ignoring");
        } else if (mCurrentCallback.mListener.asBinder() != listener.asBinder()) {
            Log.w(TAG, "cancel called by client who did not call startListening - ignoring");
        } else { // the correct state
            RecognitionService.this.onCancel(mCurrentCallback);
            mCurrentCallback = null;
            if (DBG) Log.d(TAG, "canceling - setting mCurrentCallback to null");
        }
    }

    private class StartListeningArgs {
        public final Intent mIntent;

        public final IRecognitionListener mListener;

        public StartListeningArgs(Intent intent, IRecognitionListener listener) {
            this.mIntent = intent;
            this.mListener = listener;
        }
    }

    /**
     * Checks whether the caller has sufficient permissions
     * 
     * @param listener to send the error message to in case of error
     * @return {@code true} if the caller has enough permissions, {@code false} otherwise
     */
    private boolean checkPermissions(IRecognitionListener listener) {
        if (DBG) Log.d(TAG, "checkPermissions");
        if (RecognitionService.this.checkCallingOrSelfPermission(android.Manifest.permission.
                RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
            return true;
        }
        try {
            Log.e(TAG, "call for recognition service without RECORD_AUDIO permissions");
            listener.onError(SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
        } catch (RemoteException re) {
            Log.e(TAG, "sending ERROR_INSUFFICIENT_PERMISSIONS message failed", re);
        }
        return false;
    }

    /**
     * Notifies the service that it should start listening for speech.
     * 
     * @param recognizerIntent contains parameters for the recognition to be performed. The intent
     *        may also contain optional extras, see {@link RecognizerIntent}. If these values are
     *        not set explicitly, default values should be used by the recognizer.
     * @param listener that will receive the service's callbacks
     */
    protected abstract void onStartListening(Intent recognizerIntent, Callback listener);

    /**
     * Notifies the service that it should cancel the speech recognition.
     */
    protected abstract void onCancel(Callback listener);

    /**
     * Notifies the service that it should stop listening for speech. Speech captured so far should
     * be recognized as if the user had stopped speaking at this point. This method is only called
     * if the application calls it explicitly.
     */
    protected abstract void onStopListening(Callback listener);

    @Override
    public final IBinder onBind(final Intent intent) {
        if (DBG) Log.d(TAG, "onBind, intent=" + intent);
        return mBinder;
    }

    @Override
    public void onDestroy() {
        if (DBG) Log.d(TAG, "onDestroy");
        mCurrentCallback = null;
        mBinder.clearReference();
        super.onDestroy();
    }

    /**
     * This class receives callbacks from the speech recognition service and forwards them to the
     * user. An instance of this class is passed to the
     * {@link RecognitionService#onStartListening(Intent, Callback)} method. Recognizers may call
     * these methods on any thread.
     */
    public class Callback {
        private final IRecognitionListener mListener;

        private Callback(IRecognitionListener listener) {
            mListener = listener;
        }

        /**
         * The service should call this method when the user has started to speak.
         */
        public void beginningOfSpeech() throws RemoteException {
            if (DBG) Log.d(TAG, "beginningOfSpeech");
            mListener.onBeginningOfSpeech();
        }

        /**
         * The service should call this method when sound has been received. The purpose of this
         * function is to allow giving feedback to the user regarding the captured audio.
         * 
         * @param buffer a buffer containing a sequence of big-endian 16-bit integers representing a
         *        single channel audio stream. The sample rate is implementation dependent.
         */
        public void bufferReceived(byte[] buffer) throws RemoteException {
            mListener.onBufferReceived(buffer);
        }

        /**
         * The service should call this method after the user stops speaking.
         */
        public void endOfSpeech() throws RemoteException {
            mListener.onEndOfSpeech();
        }

        /**
         * The service should call this method when a network or recognition error occurred.
         * 
         * @param error code is defined in {@link SpeechRecognizer}
         */
        public void error(int error) throws RemoteException {
            mCurrentCallback = null;
            mListener.onError(error);
        }

        /**
         * The service should call this method when partial recognition results are available. This
         * method can be called at any time between {@link #beginningOfSpeech()} and
         * {@link #results(Bundle)} when partial results are ready. This method may be called zero,
         * one or multiple times for each call to {@link SpeechRecognizer#startListening(Intent)},
         * depending on the speech recognition service implementation.
         * 
         * @param partialResults the returned results. To retrieve the results in
         *        ArrayList<String> format use {@link Bundle#getStringArrayList(String)} with
         *        {@link SpeechRecognizer#RESULTS_RECOGNITION} as a parameter
         */
        public void partialResults(Bundle partialResults) throws RemoteException {
            mListener.onPartialResults(partialResults);
        }

        /**
         * The service should call this method when the endpointer is ready for the user to start
         * speaking.
         * 
         * @param params parameters set by the recognition service. Reserved for future use.
         */
        public void readyForSpeech(Bundle params) throws RemoteException {
            mListener.onReadyForSpeech(params);
        }

        /**
         * The service should call this method when recognition results are ready.
         * 
         * @param results the recognition results. To retrieve the results in {@code
         *        ArrayList<String>} format use {@link Bundle#getStringArrayList(String)} with
         *        {@link SpeechRecognizer#RESULTS_RECOGNITION} as a parameter
         */
        public void results(Bundle results) throws RemoteException {
            mCurrentCallback = null;
            mListener.onResults(results);
        }

        /**
         * The service should call this method when the sound level in the audio stream has changed.
         * There is no guarantee that this method will be called.
         * 
         * @param rmsdB the new RMS dB value
         */
        public void rmsChanged(float rmsdB) throws RemoteException {
            mListener.onRmsChanged(rmsdB);
        }
    }

    /** Binder of the recognition service */
    private static class RecognitionServiceBinder extends IRecognitionService.Stub {
        private RecognitionService mInternalService;

        public RecognitionServiceBinder(RecognitionService service) {
            mInternalService = service;
        }

        public void startListening(Intent recognizerIntent, IRecognitionListener listener) {
            if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder());
            if (mInternalService != null && mInternalService.checkPermissions(listener)) {
                mInternalService.mHandler.sendMessage(Message.obtain(mInternalService.mHandler,
                        MSG_START_LISTENING, mInternalService.new StartListeningArgs(
                                recognizerIntent, listener)));
            }
        }

        public void stopListening(IRecognitionListener listener) {
            if (DBG) Log.d(TAG, "stopListening called by:" + listener.asBinder());
            if (mInternalService != null && mInternalService.checkPermissions(listener)) {
                mInternalService.mHandler.sendMessage(Message.obtain(mInternalService.mHandler,
                        MSG_STOP_LISTENING, listener));
            }
        }

        public void cancel(IRecognitionListener listener) {
            if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder());
            if (mInternalService != null && mInternalService.checkPermissions(listener)) {
                mInternalService.mHandler.sendMessage(Message.obtain(mInternalService.mHandler,
                        MSG_CANCEL, listener));
            }
        }

        public void clearReference() {
            mInternalService = null;
        }
    }
}

Other Android examples (source code examples)

Here is a short list of links related to this Android RecognitionService.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.