In my simple android app I programmatically load a webpage in the WebView. It initially starts with a default webpage, and the next one is loaded based upon the user inputs for the first one. The JavaScript pass information back into the Android side of things via a message. Everything works fine, except when the second webpage doesn't load no matter what I do and which URL I give. When I load the second test, a warning appears "All WebView methods must be called on the same thread." But to my knowledge I'm not using multithreading, nor do I need to use multithreading.
Here's the relevant code:
public class MainActivity extends Activity {
public WebView myWebView;
public int state;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
myWebView = (WebView) findViewById(R.id.webview);
WebSettings myWebViewSettings = myWebView.getSettings();
myWebViewSettings.setJavaScriptEnabled(true);
myWebViewSettings.setDomStorageEnabled(true);
myWebViewSettings.setAllowFileAccessFromFileURLs(true);
myWebViewSettings.setAllowUniversalAccessFromFileURLs(true);
myWebView.addJavascriptInterface(new JavascriptHandler(), "cpjs");
state = 0;
loadNextTest();
}
public void webviewLoadURL(String url) {
Log.d("app", "now loading " + url);
myWebView.clearHistory();
myWebView.clearFormData();
myWebView.clearCache(true);
myWebView.loadUrl(url);
}
final class JavascriptHandler {
@JavascriptInterface
public void sendToAndroid(String text) {
if (text.equals("confirmed at target")) {
loadNextTest();
}
}
}
public void loadNextTest() {
Log.d("app", "now loading test " + (state + 1));
if (state == 0) {
webviewLoadURL("file:///android_asset/test1.html");
state = state + 1;
} else if (state == 1) {
webviewLoadURL("file:///android_asset/test2.html");
// webviewLoadURL("");
state = state + 1;
} else {
webviewLoadURL("file:///android_asset/test3.html");
}
}
}
Here's the relevant log lines:
02-22 09:12:32.250: V/WebViewChromium(15117): Binding Chromium to the background looper Looper (main, tid 1) {41c7ec00}
02-22 09:12:32.250: I/chromium(15117): [INFO:library_loader_hooks(112)] Chromium logging enabled: level = 0, default verbosity = 0
02-22 09:12:32.255: I/BrowserProcessMain(15117): Initializing chromium process, renderers=0
02-22 09:12:32.265: W/chromium(15117): [WARNING:proxy_service(888)] PAC support disabled because there is no system implementation
02-22 09:12:32.315: D/dalvikvm(15117): GC_FOR_ALLOC freed 86K, 5% free 3217K/3364K, paused 8ms, total 8ms
02-22 09:12:32.315: I/dalvikvm-heap(15117): Grow heap (frag case) to 4.273MB for 1127536-byte allocation
02-22 09:12:32.325: D/dalvikvm(15117): GC_FOR_ALLOC freed <1K, 4% free 4318K/4468K, paused 11ms, total 11ms
02-22 09:12:32.345: D/dalvikvm(15117): GC_CONCURRENT freed <1K, 4% free 4317K/4468K, paused 1ms+6ms, total 17ms
02-22 09:12:32.365: D/app(15117): now loading test 1
02-22 09:12:32.365: D/app(15117): now loading file:///android_asset/test1.html
02-22 09:12:32.450: D/mali_winsys(15117): new_window_surface returns 0x3000
02-22 09:12:32.460: I/Icing(794): Indexing 5AA949AFB589F1D17D8668589402D01E615E228D from com.google.android.googlequicksearchbox
02-22 09:12:32.500: D/OpenGLRenderer(15117): Enabling debug mode 0
02-22 09:12:32.505: W/AwContents(15117): nativeOnDraw failed; clearing to background color.
02-22 09:12:32.540: I/ActivityManager(447): Displayed com.example.myApp/.MainActivity: +344ms
02-22 09:12:32.550: W/AwContents(15117): nativeOnDraw failed; clearing to background color.
02-22 09:12:32.635: I/Icing(794): Indexing done 5AA949AFB589F1D17D8668589402D01E615E228D
02-22 09:12:32.945: I/chromium(15117): [INFO:async_pixel_transfer_manager_android(56)] Async pixel transfers not supported
02-22 09:12:32.960: I/chromium(15117): [INFO:async_pixel_transfer_manager_android(56)] Async pixel transfers not supported
02-22 09:12:33.180: E/AndroidProtocolHandler(15117): Unable to open asset URL: file:///android_asset/backend/images/ajax-loader.gif
02-22 09:12:46.010: D/app(15117): now loading test 2
02-22 09:12:46.010: D/app(15117): now loading
02-22 09:12:46.020: W/WebView(15117): java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {41c7ec00} called on Looper (JavaBridge, tid 271) {41c6f5c8}, FYI main Looper is Looper (main, tid 1) {41c7ec00})
02-22 09:12:46.020: W/WebView(15117): at android.webkit.WebView.checkThread(WebView.java:2063)
02-22 09:12:46.020: W/WebView(15117): at android.webkit.WebView.clearHistory(WebView.java:1399)
02-22 09:12:46.020: W/WebView(15117): at com.example.myApp.MainActivity.webviewLoadURL(MainActivity.java:68)
02-22 09:12:46.020: W/WebView(15117): at com.example.myApp.MainActivity.loadNextTest(MainActivity.java:91)
02-22 09:12:46.020: W/WebView(15117): at com.example.myApp.MainActivity$JavascriptHandler.sendToAndroid(MainActivity.java:78)
02-22 09:12:46.020: W/WebView(15117): at com.android.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
02-22 09:12:46.020: W/WebView(15117): at com.android.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
02-22 09:12:46.020: W/WebView(15117): at android.os.Handler.dispatchMessage(Handler.java:102)
02-22 09:12:46.020: W/WebView(15117): at android.os.Looper.loop(Looper.java:136)
02-22 09:12:46.020: W/WebView(15117): at android.os.HandlerThread.run(HandlerThread.java:61)
02-22 09:12:46.030: W/System.err(15117): java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {41c7ec00} called on Looper (JavaBridge, tid 271) {41c6f5c8}, FYI main Looper is Looper (main, tid 1) {41c7ec00})
02-22 09:12:46.035: W/System.err(15117): at android.webkit.WebView.checkThread(WebView.java:2073)
02-22 09:12:46.035: W/System.err(15117): at android.webkit.WebView.clearHistory(WebView.java:1399)
02-22 09:12:46.035: W/System.err(15117): at com.example.myApp.MainActivity.webviewLoadURL(MainActivity.java:68)
02-22 09:12:46.035: W/System.err(15117): at com.example.myApp.MainActivity.loadNextTest(MainActivity.java:91)
02-22 09:12:46.035: W/System.err(15117): at com.example.myApp.MainActivity$JavascriptHandler.sendToAndroid(MainActivity.java:78)
02-22 09:12:46.035: W/System.err(15117): at com.android.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
02-22 09:12:46.040: W/System.err(15117): at com.android.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
02-22 09:12:46.040: W/System.err(15117): at android.os.Handler.dispatchMessage(Handler.java:102)
02-22 09:12:46.040: W/System.err(15117): at android.os.Looper.loop(Looper.java:136)
02-22 09:12:46.040: W/System.err(15117): at android.os.HandlerThread.run(HandlerThread.java:61)
02-22 09:12:46.040: W/System.err(15117): Caused by: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {41c7ec00} called on Looper (JavaBridge, tid 271) {41c6f5c8}, FYI main Looper is Looper (main, tid 1) {41c7ec00})
02-22 09:12:46.045: W/System.err(15117): at android.webkit.WebView.checkThread(WebView.java:2063)
02-22 09:12:46.045: W/System.err(15117): ... 9 more
Any help is appreciated. Thanks.
In my simple android app I programmatically load a webpage in the WebView. It initially starts with a default webpage, and the next one is loaded based upon the user inputs for the first one. The JavaScript pass information back into the Android side of things via a message. Everything works fine, except when the second webpage doesn't load no matter what I do and which URL I give. When I load the second test, a warning appears "All WebView methods must be called on the same thread." But to my knowledge I'm not using multithreading, nor do I need to use multithreading.
Here's the relevant code:
public class MainActivity extends Activity {
public WebView myWebView;
public int state;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
myWebView = (WebView) findViewById(R.id.webview);
WebSettings myWebViewSettings = myWebView.getSettings();
myWebViewSettings.setJavaScriptEnabled(true);
myWebViewSettings.setDomStorageEnabled(true);
myWebViewSettings.setAllowFileAccessFromFileURLs(true);
myWebViewSettings.setAllowUniversalAccessFromFileURLs(true);
myWebView.addJavascriptInterface(new JavascriptHandler(), "cpjs");
state = 0;
loadNextTest();
}
public void webviewLoadURL(String url) {
Log.d("app", "now loading " + url);
myWebView.clearHistory();
myWebView.clearFormData();
myWebView.clearCache(true);
myWebView.loadUrl(url);
}
final class JavascriptHandler {
@JavascriptInterface
public void sendToAndroid(String text) {
if (text.equals("confirmed at target")) {
loadNextTest();
}
}
}
public void loadNextTest() {
Log.d("app", "now loading test " + (state + 1));
if (state == 0) {
webviewLoadURL("file:///android_asset/test1.html");
state = state + 1;
} else if (state == 1) {
webviewLoadURL("file:///android_asset/test2.html");
// webviewLoadURL("http://www.google.com");
state = state + 1;
} else {
webviewLoadURL("file:///android_asset/test3.html");
}
}
}
Here's the relevant log lines:
02-22 09:12:32.250: V/WebViewChromium(15117): Binding Chromium to the background looper Looper (main, tid 1) {41c7ec00}
02-22 09:12:32.250: I/chromium(15117): [INFO:library_loader_hooks.cc(112)] Chromium logging enabled: level = 0, default verbosity = 0
02-22 09:12:32.255: I/BrowserProcessMain(15117): Initializing chromium process, renderers=0
02-22 09:12:32.265: W/chromium(15117): [WARNING:proxy_service.cc(888)] PAC support disabled because there is no system implementation
02-22 09:12:32.315: D/dalvikvm(15117): GC_FOR_ALLOC freed 86K, 5% free 3217K/3364K, paused 8ms, total 8ms
02-22 09:12:32.315: I/dalvikvm-heap(15117): Grow heap (frag case) to 4.273MB for 1127536-byte allocation
02-22 09:12:32.325: D/dalvikvm(15117): GC_FOR_ALLOC freed <1K, 4% free 4318K/4468K, paused 11ms, total 11ms
02-22 09:12:32.345: D/dalvikvm(15117): GC_CONCURRENT freed <1K, 4% free 4317K/4468K, paused 1ms+6ms, total 17ms
02-22 09:12:32.365: D/app(15117): now loading test 1
02-22 09:12:32.365: D/app(15117): now loading file:///android_asset/test1.html
02-22 09:12:32.450: D/mali_winsys(15117): new_window_surface returns 0x3000
02-22 09:12:32.460: I/Icing(794): Indexing 5AA949AFB589F1D17D8668589402D01E615E228D from com.google.android.googlequicksearchbox
02-22 09:12:32.500: D/OpenGLRenderer(15117): Enabling debug mode 0
02-22 09:12:32.505: W/AwContents(15117): nativeOnDraw failed; clearing to background color.
02-22 09:12:32.540: I/ActivityManager(447): Displayed com.example.myApp/.MainActivity: +344ms
02-22 09:12:32.550: W/AwContents(15117): nativeOnDraw failed; clearing to background color.
02-22 09:12:32.635: I/Icing(794): Indexing done 5AA949AFB589F1D17D8668589402D01E615E228D
02-22 09:12:32.945: I/chromium(15117): [INFO:async_pixel_transfer_manager_android.cc(56)] Async pixel transfers not supported
02-22 09:12:32.960: I/chromium(15117): [INFO:async_pixel_transfer_manager_android.cc(56)] Async pixel transfers not supported
02-22 09:12:33.180: E/AndroidProtocolHandler(15117): Unable to open asset URL: file:///android_asset/backend/images/ajax-loader.gif
02-22 09:12:46.010: D/app(15117): now loading test 2
02-22 09:12:46.010: D/app(15117): now loading http://www.google.com
02-22 09:12:46.020: W/WebView(15117): java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {41c7ec00} called on Looper (JavaBridge, tid 271) {41c6f5c8}, FYI main Looper is Looper (main, tid 1) {41c7ec00})
02-22 09:12:46.020: W/WebView(15117): at android.webkit.WebView.checkThread(WebView.java:2063)
02-22 09:12:46.020: W/WebView(15117): at android.webkit.WebView.clearHistory(WebView.java:1399)
02-22 09:12:46.020: W/WebView(15117): at com.example.myApp.MainActivity.webviewLoadURL(MainActivity.java:68)
02-22 09:12:46.020: W/WebView(15117): at com.example.myApp.MainActivity.loadNextTest(MainActivity.java:91)
02-22 09:12:46.020: W/WebView(15117): at com.example.myApp.MainActivity$JavascriptHandler.sendToAndroid(MainActivity.java:78)
02-22 09:12:46.020: W/WebView(15117): at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
02-22 09:12:46.020: W/WebView(15117): at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
02-22 09:12:46.020: W/WebView(15117): at android.os.Handler.dispatchMessage(Handler.java:102)
02-22 09:12:46.020: W/WebView(15117): at android.os.Looper.loop(Looper.java:136)
02-22 09:12:46.020: W/WebView(15117): at android.os.HandlerThread.run(HandlerThread.java:61)
02-22 09:12:46.030: W/System.err(15117): java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {41c7ec00} called on Looper (JavaBridge, tid 271) {41c6f5c8}, FYI main Looper is Looper (main, tid 1) {41c7ec00})
02-22 09:12:46.035: W/System.err(15117): at android.webkit.WebView.checkThread(WebView.java:2073)
02-22 09:12:46.035: W/System.err(15117): at android.webkit.WebView.clearHistory(WebView.java:1399)
02-22 09:12:46.035: W/System.err(15117): at com.example.myApp.MainActivity.webviewLoadURL(MainActivity.java:68)
02-22 09:12:46.035: W/System.err(15117): at com.example.myApp.MainActivity.loadNextTest(MainActivity.java:91)
02-22 09:12:46.035: W/System.err(15117): at com.example.myApp.MainActivity$JavascriptHandler.sendToAndroid(MainActivity.java:78)
02-22 09:12:46.035: W/System.err(15117): at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
02-22 09:12:46.040: W/System.err(15117): at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
02-22 09:12:46.040: W/System.err(15117): at android.os.Handler.dispatchMessage(Handler.java:102)
02-22 09:12:46.040: W/System.err(15117): at android.os.Looper.loop(Looper.java:136)
02-22 09:12:46.040: W/System.err(15117): at android.os.HandlerThread.run(HandlerThread.java:61)
02-22 09:12:46.040: W/System.err(15117): Caused by: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {41c7ec00} called on Looper (JavaBridge, tid 271) {41c6f5c8}, FYI main Looper is Looper (main, tid 1) {41c7ec00})
02-22 09:12:46.045: W/System.err(15117): at android.webkit.WebView.checkThread(WebView.java:2063)
02-22 09:12:46.045: W/System.err(15117): ... 9 more
Any help is appreciated. Thanks.
Share Improve this question edited Feb 22, 2014 at 14:30 yansun0 asked Feb 22, 2014 at 14:22 yansun0yansun0 831 gold badge1 silver badge4 bronze badges2 Answers
Reset to default 19As mentioned by ProfessorT, there are many threads running behind the scenes with the WebView, and callbacks from JavaScript via JavaScript interface objects are made on a background thread.
You can achieve what you like with some code like this inside loadNextTest
:
myWebView.post(new Runnable() {
@Override
public void run() {
webviewLoadURL("file:///android_asset/test1.html");
}
});
Please also note that your state
variable will also be written on the JavaScript background thread so you many need to synchronize your read/writes if they are coming from other threads too.
The object that is bound to your JavaScript runs in another thread and not in the thread in which it was constructed.
You can force all your webview url loading to be done on the main thread, check this out:
Run Callback On Main Thread