It appears you must call the super method in onActivityResult
super.onActivityResult(requestCode, resultCode, data);
I am getting this error from TTS when I press the back button on my Activity. Aparently it is because I am not calling shutdown() but I am, see onDestroy() below. I have made an abstract TtsActivity Class which Activities Extend. I am calling super.onDestroy() in all subclasses.
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)
The Activity that my classes are extending
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);
}
}
Here is the code related the the activity in 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();
....
}
}
And here is ActivitySelectItGame, it doe not reference TTS at all, just extends ActivityGame
public class ActivitySelectItGame extends ActivityGame {
...
}
But I get the exact same problem from a totally unrelated Activity the extends ActivityTTS.
@Override
protected void onDestroy() {
//Close the Text to Speech Library
if(mTts != null) {
mTts.stop();
mTts.shutdown();
Log.d(TAG, "TTS Destroyed");
}
super.onDestroy();
}
I think the problem is you are clsoing the mTts after the activity is destroyed. Try to use the code i have posted. Let me know if this works out
Each time you create an instance of mtts you need to shutdown
it.
Or in other words, if you have more than one of new TextToSpeech(xxx)
you need to have the same number of shutdown()
.
This works for me.
I'm not sure that onDestroy() is always called by the system. I've seen instances of it being skipped in my emulator. I can't reproduce the circumstances every time though. I've used TTS and have no problems with leaks. I call the mTts.shutdown() in onPause() and reinitialise it in onResume(). This works fine for me.
onCreate()
, where you start the activity for result in order to check whether TTS is available, can be called by the framework many times. So I think you may be creating multiple TTS instances in onActivityResult()
. For more information, see the diagram for the Activity class. Note that onCreate()
can be called again after a call to onStop()
I got this Leaked Connection when using a WebView in my Fragment. In the onCreateView method I did setJavaScriptEnabled(true), which caused this error, when pressing back on the Activity. To get rid of it, I moved the set to onResume(), and also set it to false in onPause(), then problem disappeared.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With