Activity has leaked ServiceConnection android.spee

2019-08-05 16:31发布

问题:

I'm trying to make a function in google glass that allows me to navigate between the cards without having to say the hotword "ok glass".

I tried creating a SpeechRecognizer that will constantly listen if something is being said or not and if the correct "command" is being mentioned the app will act accordingly.

However the onError method tells me

Error occured: RecognitionService busy.

and it's throwing a error that says

Activity com.example.sw_stage.topfinder.MainActivity has leaked ServiceConnection android.speech.SpeechRecognizer$Connection@41d79530 that was originally bound here
android.app.ServiceConnectionLeaked: Activity com.example.sw_stage.topfinder.MainActivity has leaked ServiceConnection android.speech.SpeechRecognizer$Connection@41d79530 that was originally bound here
        at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:970)
        at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:864)
        at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1575)
        at android.app.ContextImpl.bindService(ContextImpl.java:1558)
        at android.content.ContextWrapper.bindService(ContextWrapper.java:517)
        at android.speech.SpeechRecognizer.startListening(SpeechRecognizer.java:287)
        at com.example.sw_stage.topfinder.SpeechDetector.<init>(SpeechDetector.java:35)
        at com.example.sw_stage.topfinder.MainActivity.onCreate(MainActivity.java:58)
        at android.app.Activity.performCreate(Activity.java:5235)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1089)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2188)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2273)
        at android.app.ActivityThread.access$800(ActivityThread.java:138)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1236)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:149)
        at android.app.ActivityThread.main(ActivityThread.java:5045)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
        at dalvik.system.NativeStart.main(Native Method)

I'm currently using this project to test some of the functions I want to have in my final application. Currently I'm using

  • Head Gestures to navigate
  • A combination of a live card and immersion
  • A class to use shell commands in order to simulate touch gestures

Here is the class I wrote for the SpeechRecognizer

package com.example.sw_stage.topfinder;

import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.util.Log;

import java.util.ArrayList;


public class SpeechDetector {
AudioManager mAudioManager;
SpeechRecognizer mSpeechRecognizer;
Intent intent;
issueKey mIssueKey = new issueKey();

public SpeechDetector(Context context)
{
    Log.i("speechdetector", "calling speech detector");
    mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

    mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(context);
    mSpeechRecognizer.setRecognitionListener(new listener(context));

    intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
    Log.i("package name", context.getPackageName());
    intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, context.getPackageName());
    mSpeechRecognizer.startListening(intent);
    Log.i("111111","11111111"+"in");
}

class listener implements RecognitionListener
{
    Context context1;
    public listener(Context context)
    {
        context1 = context;
    }

    @Override
    public void onReadyForSpeech(Bundle bundle) {

    }

    @Override
    public void onBeginningOfSpeech() {

    }

    @Override
    public void onRmsChanged(float v) {

    }

    @Override
    public void onBufferReceived(byte[] bytes) {

    }

    @Override
    public void onEndOfSpeech() {
        mSpeechRecognizer.startListening(intent);
    }

    @Override
    public void onError(int i) {
        //3 Audio recording error.
        //5 Other client side errors.
        //6 - No speech input
        //7 -No recognition result matched.
        //8 RecognitionService busy.
        //9 - vInsufficient permissions


        if(i == 1 || i == 2 || i == 3 || i == 4 || i == 5 || i == 6 || i == 7 || i == 8 || i == 9)
        {
            Log.wtf("Error occured", "Error " + i);
            mSpeechRecognizer.startListening(intent);
        }
    }

    @Override
    public void onResults(Bundle bundle) {
        ArrayList data = bundle.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
        String result = "enter";
        String reslt = "";
        for (int i = 0; i < data.size(); i++)
        {
            reslt = reslt + " " + data.get(i);
        }
        switch(result)
        {
            case "next":  mIssueKey.issueKey(22);
                break;
            case "previous": mIssueKey.issueKey(21);
                break;
            case "enter": mIssueKey.issueKey(23);
                break;
            case "leave": mIssueKey.issueKey(4);
        }

    }

    @Override
    public void onPartialResults(Bundle bundle) {

    }

    @Override
    public void onEvent(int i, Bundle bundle) {

    }
}

}

I'm calling this class in my MainActivity onCreate() method.

private SpeechDetector mSpeechDetector;

@Override
protected void onCreate(Bundle bundle) {
    super.onCreate(bundle);

    mIssueKey = new issueKey();
    mSpeechDetector = new SpeechDetector(getApplicationContext());

I changed

new SpeechDetector(MainActivity.this);

to

new SpeechDetector(getApplicationContext());

and I'm not getting the leaked error anymore

HOWEVER

Apparently the leaked error and the RecognitionService busy aren't related. So I'm still stuck with the fact that my speechrecognition doesn't work because it throws a RecognitionService busy error

EDIT I just noticed it writes an additional log

    03-03 13:11:13.252  20018-20018/? A/Error occured﹕ RecognitionService busy
    03-03 13:11:13.260      825-825/? I/RecognitionService﹕ concurrent startListening received - ignoring this call

回答1:

It looks like the RecognitionService is already in use at the point that you call startListening(). I believe this is because you already called startListening() in your constructor and then call it again in onEndOfSpeech().

Make sure you make the necessary cancel() calls before calling startListening() again.



回答2:

You got RecognitionService busy because of this code

@Override
public void onEndOfSpeech() {
    mSpeechRecognizer.startListening(intent);
}

You should call mSpeechRecognizer.startListening(intent) in onResults