I'm having a really weird problem.
I keep getting this crash in my logcat, but the weird this is that my app has nothing to do with the Text To Speech
thing. not just this activity, my entire app doesn't use it at all.
08-04 03:47:19.321: E/ActivityThread(24755): Activity com.lablabla.similarsearch.WebViewActivity has leaked ServiceConnection android.speech.tts.TextToSpeech$Connection@443065c0 that was originally bound here
08-04 03:47:19.321: E/ActivityThread(24755): android.app.ServiceConnectionLeaked: Activity com.lablabla.similarsearch.WebViewActivity has leaked ServiceConnection android.speech.tts.TextToSpeech$Connection@443065c0 that was originally bound here
08-04 03:47:19.321: E/ActivityThread(24755): at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:974)
08-04 03:47:19.321: E/ActivityThread(24755): at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:868)
08-04 03:47:19.321: E/ActivityThread(24755): at android.app.ContextImpl.bindServiceAsUser(ContextImpl.java:1452)
08-04 03:47:19.321: E/ActivityThread(24755): at android.app.ContextImpl.bindService(ContextImpl.java:1440)
08-04 03:47:19.321: E/ActivityThread(24755): at android.content.ContextWrapper.bindService(ContextWrapper.java:496)
08-04 03:47:19.321: E/ActivityThread(24755): at android.speech.tts.TextToSpeech.connectToEngine(TextToSpeech.java:685)
08-04 03:47:19.321: E/ActivityThread(24755): at android.speech.tts.TextToSpeech.initTts(TextToSpeech.java:655)
08-04 03:47:19.321: E/ActivityThread(24755): at android.speech.tts.TextToSpeech.<init>(TextToSpeech.java:608)
08-04 03:47:19.321: E/ActivityThread(24755): at android.webkit.AccessibilityInjector$TextToSpeechWrapper.<init>(AccessibilityInjector.java:682)
08-04 03:47:19.321: E/ActivityThread(24755): at android.webkit.AccessibilityInjector.addTtsApis(AccessibilityInjector.java:483)
08-04 03:47:19.321: E/ActivityThread(24755): at android.webkit.AccessibilityInjector.addAccessibilityApisIfNecessary(AccessibilityInjector.java:168)
08-04 03:47:19.321: E/ActivityThread(24755): at android.webkit.AccessibilityInjector.updateJavaScriptEnabled(AccessibilityInjector.java:418)
08-04 03:47:19.321: E/ActivityThread(24755): at android.webkit.WebViewClassic.updateJavaScriptEnabled(WebViewClassic.java:1682)
08-04 03:47:19.321: E/ActivityThread(24755): at android.webkit.WebSettingsClassic.setJavaScriptEnabled(WebSettingsClassic.java:1125)
08-04 03:47:19.321: E/ActivityThread(24755): at com.lablabla.similarsearch.WebViewActivity.onCreate(WebViewActivity.java:24)
08-04 03:47:19.321: E/ActivityThread(24755): at android.app.Activity.performCreate(Activity.java:5133)
08-04 03:47:19.321: E/ActivityThread(24755): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
08-04 03:47:19.321: E/ActivityThread(24755): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
08-04 03:47:19.321: E/ActivityThread(24755): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
08-04 03:47:19.321: E/ActivityThread(24755): at android.app.ActivityThread.access$600(ActivityThread.java:141)
08-04 03:47:19.321: E/ActivityThread(24755): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
08-04 03:47:19.321: E/ActivityThread(24755): at android.os.Handler.dispatchMessage(Handler.java:99)
08-04 03:47:19.321: E/ActivityThread(24755): at android.os.Looper.loop(Looper.java:137)
08-04 03:47:19.321: E/ActivityThread(24755): at android.app.ActivityThread.main(ActivityThread.java:5103)
08-04 03:47:19.321: E/ActivityThread(24755): at java.lang.reflect.Method.invokeNative(Native Method)
08-04 03:47:19.321: E/ActivityThread(24755): at java.lang.reflect.Method.invoke(Method.java:525)
08-04 03:47:19.321: E/ActivityThread(24755): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
08-04 03:47:19.321: E/ActivityThread(24755): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
08-04 03:47:19.321: E/ActivityThread(24755): at dalvik.system.NativeStart.main(Native Method)
And here's the code for that activity: (All it does is get a url from the Intent
and load it to a WebView
)
public class WebViewActivity extends Activity {
public static final String EXTRA_URL = "extra_url";
private WebView webView;
private String baseUrl;
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview);
webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient());
webView.getSettings().setUserAgentString(
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/20 Safari/537.31");
baseUrl = getIntent().getStringExtra(EXTRA_URL);
webView.loadUrl(baseUrl);
}
}
I keep getting this crash in my logcat, but the weird this is that my app has nothing to do with the Text To Speech thing. not just this activity, my entire app doesn't use it at all.
Your app indeed has nothing to do with it.
Except that when you call:
webView.getSettings().setJavaScriptEnabled(true);
the method WebViewClassic.updateJavaScriptEnabled(boolean) is executed:
void updateJavaScriptEnabled(boolean enabled) {
if (isAccessibilityInjectionEnabled()) {
==>>>> // Call placed to AccessibilityInjector.updateJavaScriptEnabled(boolean)
getAccessibilityInjector().updateJavaScriptEnabled(enabled);
}
}
Here, isAccessibilityInjectionEnabled()
returns true
in your device's case. It retrieves a list of Accessibility Services that are currently enabled, and provide/support AccessibilityServiceInfo.FEEDBACK_SPOKEN
. If this list is non-empty, true
is returned.
Moving up the stacktrace:
android.webkit.AccessibilityInjector.addTtsApis()
eventually creates a TextToSpeech
object.
The problem: TextToSpeech.connectToEngine()
uses Context to call bindService(). The context is your Activity's context (passed on from WebView). I believe the Logcat shows this (or something similar) when WebViewActivity
is started:
Sucessfully bound to com.google.android.tts
Hypothesis: When your Activity is destroyed and recreated on screen rotation, the TTS service is still bound while the context isn't valid anymore. This is what the exception refers to.
I tried the following to test my hypothesis:
Instead of defining WebView in xml, I created it dynamically in onCreate():
webView = new WebView(getApplicationContext());
Notice that I used the Application's context in place of Activity's (this). The context stays valid on orientation change, and hence the exception isn't thrown.
To confirm that one (or more) Accessibility Service is enabled, add this code to your activity's onCreate():
AccessibilityManager am = (AccessibilityManager)
getSystemService(ACCESSIBILITY_SERVICE);
List<AccessibilityServiceInfo> listOfServices =
am.getEnabledAccessibilityServiceList(
AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
for (AccessibilityServiceInfo asi : listOfServices) {
Log.i("", "Accessibility Service >>>>>>>>: " + asi.getSettingsActivityName());
Log.i("", "Accessibility Service >>>>>>>>: " +
asi.loadDescription(getPackageManager()));
}
Note: I had to turn on TalkBack
(under Settings > Accessibility) to replicate the issue. Also, I am not sure why this exception isn't thrown after force stopping the application.
Based on user Robert Nekic's comment: behavior on back press: Exception is thrown when activity's context is used. Application's context still works.
Useful information: Link.
You can add this code snippet to avoid this service connection leaked exception:
class YourActivity extends Activity {
WebView yourWebView;
@Override
public void onDestroy() {
if (yourWebView != null) {
yourWebView.getSettings().setJavaScriptEnabled(false);
}
}
yourWebView.getSettings().setJavaScriptEnabled(false); will trigger the invoke of AccessibilityInjector.updateJavaScriptEnabled() in which:
private void removeTtsApis() {
if (mTextToSpeech != null) {
mTextToSpeech.stop();
mTextToSpeech.shutdown();
mTextToSpeech = null;
}
mWebView.removeJavascriptInterface(ALIAS_TTS_JS_INTERFACE);
}
mTextToSpeech.shutdown() is just the key point.
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