xRay
xRay

Reputation: 801

SpeechRecognizer will be repeated, instead of running permanently

I'm trying to develop something similar to Google Assistant. So when I say "OK app", it should handle. So I have just created a service that is running in the background:

public class SttService extends Service implements RecognitionListener {
    private static final String TAG = "SstService";
    SpeechRecognizer mSpeech;

    private void speak() {
        mSpeech = SpeechRecognizer.createSpeechRecognizer(SttService.this);
        mSpeech.setRecognitionListener(SttService.this);

        Intent intent1 = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        intent1.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "en");

        mSpeech.startListening(intent1);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand: I am running");

        speak();

        return START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind: ");
        return null;
    }

    @Override
    public void onReadyForSpeech(Bundle params) {
        Log.e(TAG, "onReadyForSpeech: ");
    }

    @Override
    public void onBeginningOfSpeech() {
        Log.e(TAG, "onBeginningOfSpeech: ");
    }

    @Override
    public void onRmsChanged(float rmsdB) {
        // Log.e(TAG, "onRmsChanged: ");
    }

    @Override
    public void onBufferReceived(byte[] buffer) {
        Log.e(TAG, "onBufferReceived: ");
    }

    @Override
    public void onEndOfSpeech() {
        Log.e(TAG, "onEndOfSpeech: ");
    }

    @Override
    public void onError(int error) {
        Log.e(TAG, "onError: " + error);
        if (error == 7) {
            speak();
        }
    }

    @Override
    public void onResults(Bundle results) {
        ArrayList<String> resultsStringArrayList = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
        String mainResult = resultsStringArrayList.get(0);
        Log.e(TAG, "onResults: " + mainResult);

        if (mainResult.equalsIgnoreCase("Okay App")) {
            System.out.println("What's up?");
        }

        mSpeech.destroy();
        mSpeech = null;
        speak();

    }

    @Override
    public void onPartialResults(Bundle partialResults) {
        Log.e(TAG, "onPartialResults: ");
    }

    @Override
    public void onEvent(int eventType, Bundle params) {
        Log.e(TAG, "onEvent: ");
    }
}

My problem is that the app is not listening permanently. It starts listening and then there is a result. When I don't say anything, it will be listening for about 2 seconds, then SpeechRecognizer will be destroyed, so another speech can begin. So in the time when it is getting destroyed, there is a break and when I say something in the meantime, it will not be recognized.

My app is not doing what I want. Probably I am doing it completely the wrong way. So what I am trying to achieve is a SpeechRecognizer that runs permanently and only handles when I say "Okay App". How can I do this?

Upvotes: 0

Views: 88

Answers (1)

Gabe Sechan
Gabe Sechan

Reputation: 93559

That's how SpeechRecognizer is designed. It's not meant for permanent background listening, it's meant for short term immediate responses. Like when someone hits the mic button in the search bar. If you want permanent background listening, you're going to have to go lower level and do it yourself.

Upvotes: 1

Related Questions