0

I tried most ways to reload a webview in every 10 seconds, such as using threads, timers, ScheduledExecutiveService... but every time I try, my app crashes. Here is my code...

public class MainActivity extends AppCompatActivity {

String user;
String password;
WebView webView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Intent i = getIntent();
    user = i.getStringExtra("username");
    password = i.getStringExtra("password");


    webView = (WebView) findViewById(R.id.webView);
    final WebSettings webSettings = webView.getSettings();
    webSettings.setBuiltInZoomControls(true);
    webSettings.setJavaScriptEnabled(true);

    webView.loadUrl("http://www.google.com");


    webView.setWebViewClient(new WebViewClient() {


        @Override
        public void onPageFinished(final WebView view, String url) {

            view.loadUrl("javascript: (function() {document.getElementById('ft_un').value= '" + user + "';}) ();");
            view.loadUrl("javascript: (function() {document.getElementById('ft_pd').value= '" + password + "';}) ();");
            view.loadUrl("javascript:(function(){ document.querySelectorAll(\"input[type='submit']\")[0].click();})();");


            super.onPageFinished(view, url);
        }
    });

//After this is i am getting error this is my timer and below that is the code to reload a webview

    new Timer().schedule(new TimerTask(){
        @Override
        public void run() {
            // TODO Auto-generated method stub
            refresh();
        }}, 10000, 10000);

}
public void refresh() {

    // TODO Auto-generated method stub
    webView.loadUrl("javascript:window.location.reload(true)");


  }
}

And the error i got is here:

FATAL EXCEPTION: Timer-0
Process: com.anshuman.cgcautologin, PID: 5318
java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread 'Timer-0'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {256ea4a6} called on null, FYI main Looper is Looper (main, tid 1) {256ea4a6})
at android.webkit.WebView.checkThread(WebView.java:2204)
at android.webkit.WebView.loadUrl(WebView.java:851)
at com.anshuman.cgcautologin.MainActivity.refresh(MainActivity.java:72)
at com.anshuman.cgcautologin.MainActivity$2.run(MainActivity.java:64)
at java.util.Timer$TimerImpl.run(Timer.java:284)
Caused by: java.lang.Throwable: A WebView method was called on thread 'Timer-0'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {256ea4a6} called on null, FYI main Looper is Looper (main, tid 1) {256ea4a6})
at android.webkit.WebView.checkThread(WebView.java:2194)
at android.webkit.WebView.loadUrl(WebView.java:851) 
at com.anshuman.cgcautologin.MainActivity.refresh(MainActivity.java:72) 
at com.anshuman.cgcautologin.MainActivity$2.run(MainActivity.java:64) 
at java.util.Timer$TimerImpl.run(Timer.java:284)

 

Noam Hacker
  • 4,671
  • 7
  • 34
  • 55
Anshuman Kaushik
  • 91
  • 1
  • 1
  • 9

3 Answers3

1

Your error message is telling you: All WebView methods must be called on the same thread..

You can solve this with an event loop pattern: have your main thread run an event loop, and post an event so your main thread picks it up and runs it in that thread.

Krease
  • 15,805
  • 8
  • 54
  • 86
  • i dont know anything about event loop pattern can you tell me with the code to how to solve it – Anshuman Kaushik Mar 15 '16 at 16:24
  • I'm not as familiar with the best way to implement this on android specifically, but [this android tutorial](http://developer.android.com/training/multiple-threads/communicate-ui.html#Handler) and [this related SO question](http://stackoverflow.com/questions/3652560/what-is-the-android-uithread-ui-thread) seem like great starting points to learn more about the UI event loop. – Krease Mar 15 '16 at 16:34
1

The error says:

All WebView methods must be called on the same thread.

So, change the refresh code to be done in the main thread. Or the one that has the webview initialization. Like this:

//In the activity
Handler handler = new Handler(this);

// Your refresh function
 public void refresh() {

      handler.post(new Runnable() {
              @Override
             public void run() {
            webView.loadUrl("javascript:window.location.reload(true)");

      }
 });}
Rafael Lucena
  • 635
  • 1
  • 6
  • 9
  • when i use Handler handler = new Handler(this); i got this error Handler is abstract;cannot be instantiated – Anshuman Kaushik Mar 15 '16 at 16:41
  • android.os.Handler is not abstract http://developer.android.com/reference/android/os/Handler.html And (this) refers to context that you can get with activity.getAplicationContext() or (this) if you are in the activity – Rafael Lucena Mar 15 '16 at 16:43
0

Android lets you update the UI components only on the main thread, you can use handlers for this:

final int MSG_UPDATE = 0;
Handler handler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        switch(msg.what) {
            case MSG_UPDATE:
                //update ur ui component here
                refresh();
        }
        return false;
    }
});
public void refreshWithDelay(long delayMillis) {
    handler.sendEmptyMessageDelayed(MSG_UPDATE, delayMillis);
}
public void refresh() {
    //Your implementation
}

The codes above does this on the main thread, You just need to call refreshWithDelay where you need to refresh your View.

Farshad
  • 3,074
  • 2
  • 30
  • 44