【问题标题】:TTS Error: leaked ServiceConnection android.speech.tts.TextToSpeechTTS 错误:泄露的 ServiceConnection android.speech.tts.TextToSpeech
【发布时间】:2017-03-09 06:32:17
【问题描述】:

解决方案

看来你必须在onActivityResult中调用super方法

super.onActivityResult(requestCode, resultCode, data);

当我按下 Activity 上的后退按钮时,我从 TTS 收到此错误。显然这是因为我没有调用 shutdown() 但我是,请参阅下面的 onDestroy()。我制作了一个活动扩展的抽象 TtsActivity 类。我在所有子类中调用 super.onDestroy()。

12-05 18:04:05.268: ERROR/ActivityThread(30240): Activity com.mysite.myapp.ActivitySelectItGame has leaked ServiceConnection android.speech.tts.TextToSpeech$1@43e9b4a0 that was originally bound here
12-05 18:04:05.268: ERROR/ActivityThread(30240): android.app.ServiceConnectionLeaked: Activity com.mysite.myapp.ActivitySelectItGame has leaked ServiceConnection android.speech.tts.TextToSpeech$1@43e9b4a0 that was originally bound here
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.app.ActivityThread$PackageInfo$ServiceDispatcher.<init>(ActivityThread.java:1121)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.app.ActivityThread$PackageInfo.getServiceDispatcher(ActivityThread.java:1016)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.app.ContextImpl.bindService(ContextImpl.java:863)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.content.ContextWrapper.bindService(ContextWrapper.java:347)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.speech.tts.TextToSpeech.initTts(TextToSpeech.java:467)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.speech.tts.TextToSpeech.<init>(TextToSpeech.java:433)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at com.mysite.android.library.activity.ActivityTTS.onActivityResult(ActivityTTS.java:98)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at com.mysite.myapp.ActivityGame.onActivityResult(ActivityGame.java:445)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.app.Activity.dispatchActivityResult(Activity.java:3890)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.app.ActivityThread.deliverResults(ActivityThread.java:3511)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.app.ActivityThread.handleSendResult(ActivityThread.java:3557)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.app.ActivityThread.access$2800(ActivityThread.java:125)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2063)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.os.Handler.dispatchMessage(Handler.java:99)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.os.Looper.loop(Looper.java:123)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at android.app.ActivityThread.main(ActivityThread.java:4627)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at java.lang.reflect.Method.invokeNative(Native Method)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at java.lang.reflect.Method.invoke(Method.java:521)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
12-05 18:04:05.268: ERROR/ActivityThread(30240):     at dalvik.system.NativeStart.main(Native Method)

我的课程正在扩展的活动

public abstract class ActivityTTS extends Activity implements OnInitListener {
    //TEXT TO SPEECH SERVICE
    public static final int CHECK_TTS_AVAILABILITY = 101;
    private static final String TAG = "ActivityTTS";
    private TextToSpeech mTts; //Text to speech library

    //MESSAGES
    private String NO_TTS_ANDROID_MARKET_REDIRECT = 
            "'SpeechSynthesis Data Installer' is not installed on your system, you are being redirected to" +
            " the installer package. You may also be able to install it my going to the 'Home Screen' then " +
            "(Menu -> Settings -> Voice Input & output -> Text-to-speech settings)";
    private String NO_TTS_AVAILABLE = 
            "'SpeechSynthesis Data Installer' is not available on your system, " +
            "you may have to install it manually yourself. You may also be able to install it my going to the 'Home Screen' " +
            "then (Menu -> Settings -> Voice Input & output -> Text-to-speech settings)";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate() called in ActivityTTS");

        try { //A weird error was occurring on some phones with the TTS, hence the try catch
            //TTS Service
            Intent checkIntent = new Intent();
            checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
            startActivityForResult(checkIntent, CHECK_TTS_AVAILABILITY);
        } catch (Exception e) {
            Toast.makeText(this, NO_TTS_AVAILABLE, Toast.LENGTH_LONG).show();
            finish();
        }

    }






    @Override
    protected void onStart() {
        super.onStart();


    }






    @Override
    protected void onStop() {
        super.onStop();
    }



    /**
     * Add a custom audio file for a particular 
     * audio element.
     * 
     * @param text
     * @param filename
     */
    protected void addSpeech(String text, String filename ) {
        mTts.addSpeech(text, filename);
    }



    /**
     * For TTS
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        try {
            //Log.d(TAG, "TTS Response: "+requestCode);
            if (requestCode == CHECK_TTS_AVAILABILITY) {
                if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {

                    // success, create the TTS instance
                    this.mTts = new TextToSpeech(this, this);

                } else {
                    // missing data, install it
                    Toast.makeText(this, NO_TTS_ANDROID_MARKET_REDIRECT, Toast.LENGTH_LONG).show();

                    PackageManager pm = getPackageManager();
                    Intent installIntent = new Intent();
                    installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                    ResolveInfo resolveInfo = pm.resolveActivity( installIntent, PackageManager.MATCH_DEFAULT_ONLY );

                    if( resolveInfo == null ) {
                       // Not able to find the activity which should be started for this intent
                        Toast.makeText(this, NO_TTS_AVAILABLE, Toast.LENGTH_LONG).show();
                    } else {
                       startActivity( installIntent );
                    }

                    finish();
                }
            }
        }catch (Exception e) {
            Log.e(TAG, "Unable to access service");
            finish();
        }

    }




    /**
     * Loads when the TTS is ready
     */
    @Override
    public void onInit(int status) {
        mTts.setLanguage(Locale.getDefault());
    }


    /**
     * Speak text
     */
    protected void speak(String text) {
        try{
            mTts.stop(); //Stop speaking
            mTts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
        }
        catch(Exception e) {
            Log.e(TAG, "TTS Failed - cannot say: "+text );
        }
    }


    /**
     * Speak a pre-recorded word
     */
    protected void speak(String text, File filename) {
        try{
            mTts.stop(); //Stop speaking
            mTts.addSpeech(text, filename.toString());
            mTts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
        }
        catch(Exception e) {
            Log.e(TAG, "TTS Failed - cannot say: "+text );
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();

        //Close the Text to Speech Library
        if(mTts != null) {

            mTts.stop();
            mTts.shutdown();
            Log.d(TAG, "TTS Destroyed");
        }
    }

    public void setLanguage(Locale audioLocale) {
        mTts.setLanguage(audioLocale);
    }
}

这是与ActivityGame中的活动相关的代码

public abstract class ActivityGame extends ActivityTTS {

...

    protected void speak() {
        if (Logging.INFO) Log.i(TAG, "Speaking");

        if(this.mVoicePreference) {
            String word = mBoundService.getCurrentWord().getSpelling();


            if(WordRecordingHelper.recordingExists(word)) {

                try{
                    File f = new File(Constants.SDCARD_RECORDINGS+WordRecordingHelper.formatRecordedWord(word));
                    super.addSpeech(word, f.getAbsolutePath());
                } catch (Exception e) {
                    if(Logging.WARN) Log.w(TAG, "An error occurred while trying to use addSpeech()", e);
                }
            }


            //play the audio
            super.speak(word);  
        }
    }



    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        ...

        }



    @Override
    protected void onDestroy() {
        super.onDestroy();

        ....
        }


}

这里是ActivitySelectItGame,它根本不引用TTS,只是扩展了ActivityGame

public class ActivitySelectItGame extends ActivityGame {
    ...
}

但是我从一个完全不相关的 Activity 中遇到了完全相同的问题,扩展了 ActivityTTS。

【问题讨论】:

  • mTts 中的值在哪里设置?
  • @gnobal 我更新了问题以添加更多信息
  • 我认为您提到的解决方案不正确。就我而言,我必须确保在创建新实例之前完全执行 onDestroy()。

标签: android


【解决方案1】:
@Override
protected void onDestroy() {


    //Close the Text to Speech Library
    if(mTts != null) {

        mTts.stop();
        mTts.shutdown();
        Log.d(TAG, "TTS Destroyed");
    }
    super.onDestroy();
}

我认为问题是您在活动被破坏后关闭 mTts。尝试使用我发布的代码。让我知道这是否可行

【讨论】:

  • 是否可以在ActivitySelectItGame中显示与mTts相关的代码
  • 我更新了问题,但我从一个完全不相关的 Activity 中得到了完全相同的错误,该 Activity 扩展了 ActivityTTS
【解决方案2】:

每次创建 mtts 实例时都需要shutdown

或者换句话说,如果你有多个new TextToSpeech(xxx),你需要有相同数量的shutdown()

这对我有用。

【讨论】:

    【解决方案3】:

    我不确定系统是否总是调用 onDestroy()。我已经看到它在我的模拟器中被跳过的实例。我不能每次都重现这种情况。 我使用过 TTS 并且没有泄漏问题。 我在 onPause() 中调用 mTts.shutdown() 并在 onResume() 中重新初始化它。这对我来说很好。

    【讨论】:

    • 它实际上调用了 onDestroy,因为我在错误发生之前在 Android 日志中看到了我的 Log.d 语句。
    【解决方案4】:

    onCreate(),您在其中启动活动以获得结果以检查 TTS 是否可用,可以被框架多次调用。所以我认为你可能在onActivityResult() 中创建了多个 TTS 实例。有关详细信息,请参阅the diagram for the Activity class。注意onCreate()可以在调用onStop()后再次调用

    【讨论】:

    • 我只调用一次 onCreate() 时遇到了同样的错误 - 但在从对话框返回后也调用了它。那是 pb tnx
    【解决方案5】:

    在我的 Fragment 中使用 WebView 时,我得到了这个泄漏的连接。在 onCreateView 方法中,当我按下 Activity 时,我做了 setJavaScriptEnabled(true),这导致了这个错误。为了摆脱它,我将设置移动到onResume(),并在onPause()中将其设置为false,然后问题就消失了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-29
      • 1970-01-01
      • 2010-12-31
      • 2015-01-27
      • 2015-11-14
      • 2013-11-17
      相关资源
      最近更新 更多