WebView methods on same thread error
The JavaScript method is executed on a background (i.e. non-UI) thread. You need to call all Android View related methods on the UI thread. You can achieve what you need with:
mWebView.post(new Runnable() {
@Override
public void run() {
mWebView.loadUrl(...).
}
});
Which will post the task to run on the UI thread.
Kotlin: All WebView methods must be called on the same thread
You should use Runnable and Post to WebView Handler.
myWebView.post(Runnable {
myWebView.loadUrl("file:///android_asset/index.html")
})
Android returns methods must be called on same thread error
As you said, when you call methods from JS to the JavaBridge and then to your class from a non-ui Thread, you have to use listeners/callbacks. When you have done your loadUrl
, call you listener to pass the desired String url.
In this Example, I've defined an an inner interface with the onGetWebViewUrl
listener. I've registered the listener by implementing the interface in the same class, so I can call it easily.
For example :
public class WebViewProxy implement WebViewListener {
private WebView mWebView;
...
@JavascriptInterface
public void onJsStuff(){
webView.post(new Runnable() {
public void run() {
mWebView.loadUrl("javascript:" + s + ";");
WebViewProxy.this.onGetWebViewUrl(mWebView.getUrl());
}
});
}
@Override
public void onGetWebViewUrl(String url){
// call method 2 with this url
}
public interface WebViewListener {
void onGetWebViewUrl(String url);
}
}
A WebView method was called on thread 'FinalizerDaemon' BUT MY APP HAS NO WEBVIEW
Apparently you're using an in-app ads SDK that uses a WebView (Admob?) See com.google.android.gms.ads.internal.webview...
.
Plus, from my experience with WebView
and StrictMode
, the fact you're getting this behavior probably it is not a bug of the Ads SDK: I our app we had to disable some checks (or reduce the penalty to log) in order to work around the problem (we do use WebView
, and the WebView
itself creates issues with StrictMode
because of disk access done from UI thread and similar issues).
WebView Methods is not called in android
The warning is telling you everything. You are calling the webview methods directly. That means you are calling them on WebViewCoreThread. You have to call them on the UI Thread that means in the Activity which uses this webview.
Like:
WebView wv = (WebView)findViewById(id);
wv.setJavaScriptEnabled(true);
wv.setJavaScriptCanOpenWindowsAutomatically(true);
wv.setPluginsEnabled(true);
wv.loadUrl("javascript:android.selection.longTouch();");
WebView - Threads
JavascriptInterface
methods are called on background thread and not on UI thread. While dealing with UI, you need to use main UI thread.
Since you are executing it in separate class, you need to pass Activity
object and then in all your JavascriptInterface
methods:
Change the WebAppInterface
class as follows:
public class WebAppInterface {
Activity activityObj;
WebView webview;
/** Instantiate the interface and set the context */
WebAppInterface(Activity activityObj, WebView w) {
mContext = c;
this.activityObj = activityObj;
}
...
}
and runOnUiThread as follows:
activityObj.runOnUiThread(new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT >= 19 /*Might need 21*/) {
webview.evaluateJavascript(script, null);
}else {
webview.loadUrl(script);
}
}
});
Alternatively you can implement some callback interface and perform action in Activity itself as follows:
public interface Callback {
void loadLocalExternal(boolean isExternal);
//define other methods.
}
MainActivity.java
public class MainActivity extends AppCompatActivity implements Callback{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webview = (WebView)findViewById(R.id.webView);
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new WebChromeClient());
webview.loadUrl("file:///android_asset/www/index.html");
webview.addJavascriptInterface(new WebAppInterface(this, this), "Android");
}
@Override
public void loadLocalExternal(boolean isExternal){
runOnUiThread(new Runnable() {
@Override
public void run() {
//Do your action here
}
});
}
}
WebAppInterface.java
public class WebAppInterface {
Context mContext;
private final Callback callback;
/** Instantiate the interface and set the context */
WebAppInterface(Context c, Callback callback) {
mContext = c;
this.callback = callback;
}
@android.webkit.JavascriptInterface
public String loadLocalExternal(boolean isExternal) {
callback.loadLocalExternal(isExternal);
}
...
}
Reloading a WebView with a JavaScript call from a loaded web page
Loading a page in a WebView
componenet (or reloading) needs to be done on the UI thread for some reason, so simply wrapping the reload call in runOnUiThread
resolves this issue.
@JavascriptInterface
public void reloadSite(){
Toast.makeText(mContext, getString(R.string.reloadingWebApp), Toast.LENGTH_LONG).show();
runOnUiThread(new Runnable() {
@Override
public void run() {
mWebView = (WebView) findViewById(R.id.activity_main_webview);
mWebView.loadUrl(getString(R.string.web_app_url));
}
});
}
Related Topics
Location Permission Alert on iPhone with Cordova
Performance Difference Between JavaScript Created Inline Styles and JavaScript Created Stylesheets
Bootstrap Dropdown Checkbox Select
How to Change the Viewport Meta Tag in Mobile Safari on the Fly
Vertical-Align Text Within a Textarea
Attempt to Add a Rule to a CSS Stylesheet Gives "The Operation Is Insecure" in Firefox
JavaScript to Print Contents of Only Specific <Div>
Iframe Dynamic Height Width Change Based on Inner Content
Using JavaScript to Change Table Cells Width
Download Blob File from Website Inside Android Webviewclient
Bootstrap 3.0 Popovers and Tooltips
Jqm Ui-Content 100% Height Issue
Selecting Text in a Div Programmatically Using Position Values Belong to That Text
React Animation for Moving an Element from One Parent to Another
How to Position Popover Over a Highlighted Portion of Text
Onclick JavaScript Function Working Only on Second Click
Does Animating the Value of a CSS3 Transform with JavaScript Rule Out Hardware Acceleration