Reloading a WebView with a JavaScript call from a loaded web page - javascript

I have a WebView in an app that loads a specific web page.
On that web page is a button that uses JavaScript to call a method within the Android activity to reload the URL in the WebView (effectively resetting the web app to its default state).
I've got all of the JavaScript interface to Android bit working thanks to a few threads here and I can pop up a Toast to show that the app is about to reload, but I'm getting an error with the WebView.loadUrl() call as follows.
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) {1d015c84} called on Looper (JavaBridge, tid 122148) {33703881}, FYI main Looper is Looper (main, tid 1) {1d015c84})
I'm guessing that this is because the method that is doing the reload is not within the onCreate method for this activity which does all of the other WebView stuff but I'm not sure if this really is the problem and how to resolve it if it is - as the method that reloads the URL needs to be within the JavascripInterface class to be reachable from within the 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

WebView does not recognize history state in some cases

In my Android app I implemented a common approach to "go back on back-button pressed":
private WebView webView; // my WebView
#Override
public void onBackPressed() {
if(webView.canGoBack()) webView.goBack();
else super.onBackPressed();
}
But today I noticed a weird thing. If, on the very first webpage loaded on webView, it calls history.pushState(...) automatically, then webView.canGoBack() will return false, causing the approach above to fail (even if I execute webView.goBack() directly, nothing happens in the webView), although executing history.back() still works within the webpage itself. I've also tried calling history.pushState automatically using setTimeout, with the same result. However, if history.pushState is called manually, i.e. triggered by some user events, then webView.canGoBack() is true and the code works.
It seems to me that this is a bug of WebViews. Any ideas?

Android WebView WebArchive freeze after loading

I'm currently developping an android app for a tablet and I want to cover the use case : "if there is no internet connection, I want the app to run as normal".
I used a webview to load a survey in the app so once installed inside our stores, I won't have to install a new version each time we need a new makeover or add questions.
To cover the case where there is no connection, I save a webArchive that I load if there is no wifi when I need to load the webpage.
private void setMainView() {
mainview = (WebView) findViewById(R.id.wvMain);
WebSettings webSettings = mainview.getSettings();
webSettings.setLightTouchEnabled(true);
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
JavaScriptInterface myJavaScriptInterface = new JavaScriptInterface(this);
mainview.addJavascriptInterface(myJavaScriptInterface, "AndroidFunction");
if (DetectConnection.checkInternetConnection(this)){
mainview.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
File webpage = new File(context.getExternalFilesDir(Environment.DIRECTORY_DCIM).getAbsolutePath()+ File.separator +"home.mht");
mainview.saveWebArchive(webpage.toString());
editor.putString(BuildConfig.HOME_PAGE_WEB_ARCHIVE_FILE,webpage.toString() );
editor.commit();
}
});
mainview.loadUrl(BuildConfig.SERVER_URL + BuildConfig.HOME_PAGE);
}
else{
String filename = getSharedPreferences(BuildConfig.PREFERENCES_NAME, 0).getString(BuildConfig.HOME_PAGE_WEB_ARCHIVE_FILE,null);
mainview.setWebChromeClient(new WebChromeClient());
mainview.loadUrl("file:///"+filename);
}
}
The only problem is that the webarchive froze as soon as it is loaded. I tried many thing to make it works but the solution is escaping me.
When I set my application to plane mode and I reload the app, I see the home page fine but the click events don't work. My Android Javascript interface is also not working as I tested to send Toast to debug when the app is finished loading so I'm guessing the javascript is not working in my webarchive or maybe the webarchive is not including the CSS and Javascript that are from other website such as W3.css and JQuery?
Maybe if I used a local version of these asset they will be included in the webarchive.
Any suggestions would be welcome.
Thanks
I ended up using the cache of my webview instead of loading a web archive.
I first added a cache.appcache a the root of my webpage linking my main page to it.
<html manifest="cache.appcache">
At the root (wwww/http_doc) I added this file :
CACHE MANIFEST
/home
/thank-you
/css/w3.css
/js/jquery-3.3.1.min.js
/images/happy1.png
/images/happy2.png
/favicon.ico
#NETWORK
NETWORK:
/home
/thank-you
#FALLBACK
FALLBACK:
/home /offline.html
/thank-you /offline_thankyou.html
The fallback section allowed to have a html file to fall to if the network is available. I then activated the cache of my webview :
WebSettings webSettings = mainview.getSettings();
webSettings.setAppCacheEnabled(true);
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
webSettings.setAppCachePath(
getApplicationContext().getCacheDir().getAbsolutePath());
And now each time, I modified the file "cache.appcache" and reload the application, it take a copy of the current "offline.html" files and reload a working site according to the cache. A good thing I had a very static website to load from so it's 100% functionnal without an internet connection.

how to disable android ImageButton from javascript

i have a hybrid app. I used web-view to make a android hybrid app. I also have a native menubar above the webview. My question is, How can i disable the native menu from my web application? Is it possible? If yes please share your thoughts on this
Check the answer of this question, as they provide snippet code to call Java method from javascript in Android, this will help you if you create a Java method that will disable your ImageButton from a Javascript
Call Java function from JavaScript over Android WebView
You will need to find the user-agent click here to see how to check useragent then u can write a simple javascript function on page load to disable your header
Try to set webviewclient to your webview and override onPageFinished like this. In my project I tried to hide google and facebook buttons on fitbit page.
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (!TextUtils.isEmpty(url) && url.contains("fitbit")) {
view.loadUrl("javascript: setTimeout(function () { $('.external-choices,.or').hide();} , 1000) ");//JS to hide the fitbit login from G+ and FB
}
}
}

Android WebView callstack exceeded error on OAuth callback URL

I have a WebView in which users can log in to my online service by using other online services.
Logging in works fine on Desktop and the Android Chrome browser, but when I use the WebView in my App, I get a callback stack size exceeded error.
Uncaught RangeError: Maximum call stack size exceeded, source: THE_CALL_BACK_URL
The Webview adds a www prefix to the url, which could probably lead to the URL not being recognized by the OAuth service. Buw how do I remove the www prefixing?
Or could this be cause by something else?
Code:
WebSettings webSettings = webView.getSettings();
webSettings.setJavascriptEnabled(true);
webView.setWebViewClient(new WebVieCient() {
#Override
public boolean onRecievedError(); // Stump for brevity
#Override
public boolean shouldOverrideUrlLoading() // Stump for brevity
// This function handles internal links in WebView and opens external links in standard browser.
// (The function responds to the callback link as an internal link and opens it in the WebView)
EDIT
I have removed the www Prefix and i still get the Maximum call stack error

Cannot display web page on WebView control

I tried to follow the instruction describe here: http://docs.oracle.com/javafx/2.0/webview/jfxpub-webview.htm to display a web page on javafx 2.1, but web page does not display although I've already signed my application using javafx-ant tool (this link mentions about signing javafx application How can I display a javascript webpage inside a WebView in JavaFx 2.0 in Browser).
I can view the web page when running javafx on browser, but can't view it when running application as java stand alone application.
Here's the code:
browser control:
public class Browser extends Region {
final WebView browser = new WebView();
final WebEngine webEngine = browser.getEngine();
public Browser() {
//apply the styles
getStyleClass().add("browser");
// load the web page
webEngine.load("http://www.google.com");
//add the web view to the scene
getChildren().add(browser);
}
//...
}
Display it:
Stage stage = new Stage();
stage.setTitle("Web View");
Scene scene = new Scene(new Browser(),590,400, Color.web("#666970"));
stage.setScene(scene);
scene.getStylesheets().add("/com/sai/javafx/calendar/styles/BrowserToolbar.css");
stage.show();
Any idea would be highly appreciated.
Here is a sample app:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class WebViewSample extends Application {
public static void main(String[] args) { launch(args); }
#Override public void start(final Stage primaryStage) {
final WebView webView = new WebView();
webView.getEngine().load("http://docs.oracle.com/javafx/");
primaryStage.setScene(new Scene(webView));
primaryStage.show();
}
}
Here is what it looks like in a browser, the inner scrollpane is the JavaFX WebView rendered browser and the outer text is the html page embedding the JavaFX WebView.
To run it I used NetBeans nightly build, JavaFX 2.2b4, JDK7u6ea, Win7, IE9.
Steps in NetBeans were:
New Project | JavaFX | JavaFX Application
Create a Java file with the sample app code.
After project created, right click Project | Properties
Build | Deployment | Check "Request Unrestricted Access"
Run | Check radio Run "in Browser"
OK to accept property changes
Press F6 to run the application in the browser.
Accept any security dialog warnings.
Wait a few seconds for the WebView to load.
As far as I know, the only way to solve my problem is loading the .html file locally (can't load web page from other domain, and this html file must not refer to any external link)
public Browser() {
//apply the styles
getStyleClass().add("browser");
// load the web page
final URL urlHello = Browser.class.getResource("sample.html");
webEngine.load(urlHello.toExternalForm());
}
Display it:
Stage stage = new Stage();
stage.setTitle("Web View");
Scene scene = new Scene(new Browser(),590,400, Color.web("#666970"));
stage.setScene(scene);
scene.getStylesheets().add("/com/sai/javafx/calendar/styles/BrowserToolbar.css");
stage.show();

Categories