• 12
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

I use a WebView to display some internet content on one of our app's Activities.
The problem is that when the user switches out of this activity, WebView's threads keep running!
The problematic threads are:

Thread [<17> WebViewCoreThread] (Running)
Thread [<25> CookieSyncManager] (Running)
Thread [<19> http0] (Running)
Thread [<29> http1] (Running)
Thread [<31> http2] (Running)
Thread [<33> http3] (Running)

Pausing each one of these threads, and checking what it is busy doing:

Thread [<17> WebViewCoreThread] (Suspended)
    Object.wait(long, int) line: not available [native method]
    MessageQueue(Object).wait() line: 288
    MessageQueue.next() line: 148
    Looper.loop() line: 110
    WebViewCore$WebCoreThread.run() line: 471
    Thread.run() line: 1060

Thread [<25> CookieSyncManager] (Suspended)
    Object.wait(long, int) line: not available [native method]
    MessageQueue(Object).wait(long) line: 326
    MessageQueue.next() line: 144
    Looper.loop() line: 110
    CookieSyncManager(WebSyncManager).run() line: 90
    Thread.run() line: 1060

Thread [<19> http0] (Suspended)
    Object.wait(long, int) line: not available [native method]
    RequestQueue(Object).wait() line: 288
    ConnectionThread.run() line: 93

I wonder how can I tell the Looper in each of those threads to quit.

I tried calling webView.destroy() in the activity's onPause() method, but it had no influence.
When I disable the call for opening a web page in the webView ( webView.loadUrl(...) ), those threads naturally are not started, and therefore don't stay on after leaving the activity.

Any ideas as to how I can make WebView's threads stop after leaving their activity?

      • 2
    • "Any ideas as to how I can make WebView's threads stop after leaving their activity?" Why do you care? What specific harm is it causing?
    • I have been trying to avoid having extra threads running, holding resources in memory and (possibly) adding more cpu scheduling slots. Are you saying it will have no influence on performance nor resources?

You should be able to stop / resume these threads by calling the onPause / onResume on the webview.

Those are however hidden, so you will need to do it through reflection. The following code worked for me:

Class.forName("android.webkit.WebView").getMethod("onPause", (Class[]) null).invoke(webView, (Object[]) null);

Where webView is the instance of WebView.

Also see: http://code.google.com/p/android/issues/detail?id=10282

  • 40
Reply Report
      • 1
    • Thanks for you answer. As the bug report in the url you provided says, it might work, but it "feels a little dirty". I guess for now it is the best answer to this question.
    • Well, taking the original question into account, I would override the main activity's methods onPause and onResume and call it from there.

My solution, in extended webview class(tested in android 2.2, andriod 2.3, android 3.1):

 private boolean is_gone = false;
 public void onWindowVisibilityChanged(int visibility) {
     super.onWindowVisibilityChanged(visibility);
     if (visibility == View.GONE) {
         try {
             WebView.class.getMethod("onPause").invoke(this); //stop flash
         } catch (Exception e) {}
         this.pauseTimers();
         this.is_gone = true;
     } else if (visibility == View.VISIBLE) {
         try {
             WebView.class.getMethod("onResume").invoke(this); //resume flash
         } catch (Exception e) {}
         this.resumeTimers();
         this.is_gone = false;
     }
 }
 public void onDetachedFromWindow() { //this will be trigger when back key pressed, not when home key pressed
     if (this.is_gone) {
         try {
             this.destroy();
         } catch (Exception e) {}
     }
 }
  • 16
Reply Report

A clean easy solution that does the job:

@Override
public void onPause() {
    super.onPause();
    webView.onPause();
    webView.pauseTimers(); //careful with this! Pauses all layout, parsing, and JavaScript timers for all WebViews.
}

@Override
public void onResume() {
    super.onResume();
    webView.onResume();
    webView.resumeTimers();
}

@Override
public void onDestroy() {
    super.onDestroy();
    parentViewGroup.removeAllViews(); //the viewgroup the webview is attached to
    webView.loadUrl("about:blank"); 
    webView.stopLoading();
    webView.setWebChromeClient(null);
    webView.setWebViewClient(null);
    webView.destroy();
    webView = null;
}
  • 13
Reply Report
    • This worked excellent for my 4.4.2 application, though i havnt yet figured out what "parentViewGroup.removeAllViews(); " is for, but "javaScriptTester.removeAllViews();" seemed to be accepted by the ide. so?? and like Ayyappa said it requires api level 11.

Take a look at this andev.org thread (WebViewCoreThread problem).

See the response... Re: WebViewCoreThread problem - Postby potatoho

2) To pause flash you have to call hidden methods WebView.onPause() / WebView.onResume().

3) To pause WebViewCoreThread you use WebView.pauseTimers() / WebView.resumeTimers().

I skipped the onPause/onResume, but I implemented webView.pauseTimers() and webView.resumeTimers() and it at least stops the CPU bleed.

I also added CookieSyncManager.getInstance().stopSync() / startSync to my onPause/onResume as well.

  • 4
Reply Report
      • 2
    • Thanks, i found solution in the blog:In your Activity onPause you should call WebView.onPause() and WebView.pauseTimers(). In your Activity onResume you should call WebView.onResume() and WebView.resumeTimers(). But since there is a one-off error in the refcount, you need to call WebView.resumeTimers() when you first create the WebView. WebView.class.getMethod("onPause").invoke(webview);

Thanks for these info, I had this problem pausing sounds in my swf on webView when I press the lock button on the phone, onPause and onResume still plays my swf when i press the unlock button but the activity is still not visible, I suggest you place these on onWindowFocusChanged if you want to pause and resume playing of swf sounds in webView

@Override
public void onWindowFocusChanged(boolean hasFocus) {
gameView = (WebView) findViewById(R.id.gameView);
    // TODO Auto-generated method stub
    if (hasFocus) {
        try {
            Class.forName("android.webkit.WebView")
                    .getMethod("onResume", (Class[]) null)
                    .invoke(gameView, (Object[]) null);
        } catch (Exception e) {

        }
        gameView.resumeTimers();
        gameView.loadUrl("javascript:setflashfocus()");
    } else {
        try {
            Class.forName("android.webkit.WebView")
                    .getMethod("onPause", (Class[]) null)
                    .invoke(gameView, (Object[]) null);
        } catch (Exception e) {

        }
        gameView.pauseTimers();
    }
    super.onWindowFocusChanged(hasFocus);
}
  • 2
Reply Report

Actually, using webView.destroy(), onPause(), clear**() cannot stop Webcore and its related threads yet.

Practically, an ideal way is to set the activity where WebView resides to be in an independent process, so that when the activity is finished, all the threads including Webcore will be destroyed.

That is the way I have employed. Maybe it is also useful to you.

  • 1
Reply Report

I had to call onDestroy of the WebView to clear the memory specifically for the webview. I was loading flash in and it was killing my app when we go back to this activity with a webview. Flash will eat you alive if you don't destroy your WebView EVERY TIME you're done with it.

  • 0
Reply Report

The above solutions failed for me on Samsung Galaxy S with Android 2.3.3. But I made success trying the below workaround:

    webview.loadUrl("file:///android_asset/nonexistent.html");

I am forcing the webview to load a non existent html file. This seems to be forcing the webview to clean things up.

  • 0
Reply Report

Define a method:

    private void hiddenWebViewMethod(String state){
        if( webView != null ){
            try {
                Method method = WebView.class.getMethod(state);
                method.invoke(webView);
            } catch (Exception e) {
                Log.e("TAG", "Exception: " + e.toString());
                webView.loadData("", "text/html", "utf-8");
            }
        }
    }

then call hiddenWebViewMethod("onPause"); to stop loading, and hiddenWebViewMethod("onResume"); to resume.

  • 0
Reply Report