Android WebView WebArchive freeze after loading - javascript

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.

Related

Android WebView seems to behave different for each device

I'm building an app that is dependend on WebViews to render HTML-files in the assets folder. These files contain Javascript. The app works perfectly on my own device, including all the Javascript. But the Android emulator from Android Studio executes only some of the Javascript, on some of the pages. And the device from one of the testers shows blank pages instead of the HTML-files. And the device from another one of our testers also doesn't execute all the Javascript properly.
So, I'm not really sure what to do here. All pages are loaded with the exact same WebView-method and most of the Javascript is also similar. I can't debug or release an app that behaves differently on each device.
The code to load the WebViews:
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.addJavascriptInterface(new WebAppInterface(this), "Android");
WebSettings webSettings = myWebView.getSettings();
CookieManager.getInstance().setAcceptCookie(true);
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccessFromFileURLs(true);
webSettings.setAllowUniversalAccessFromFileURLs(true);
webSettings.setAllowFileAccess(true);
webSettings.setAllowContentAccess(true);
webSettings.setDomStorageEnabled(true);
webSettings.setLoadWithOverviewMode(true);
myWebView.setWebChromeClient(new WebChromeClient() {
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
}
});
myWebView.loadUrl("file:///android_asset/www/file.html");
myWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
view.loadUrl(request.toString());
return true;
}
});
Once again, the app works perfectly on my own Android device. Even after I reinstalled it. I just don't see why it wouldn't work on other devices. Does someone have a solution or explaination?
I advice you to use the WebView Remote Debugging,so that you can see the source code that running in the WebView of your html fileļ¼Œand then you can click the web page in you Chrome Browser to see how the page react.
That is the way I took when I met some problem in webview.
all you need to do is just run the following code
if (Build.VERSION.SDK_INT >= 19){
WebView.setWebContentsDebuggingEnabled(true);
}
or you can find more detail about remote-debugging

Debugging Android WebViews?

I'm trying to debug an Android app that makes heavy use of WebViews to display web pages from within the app.
The problem is simple - when I load the page, there's an anchor on one page that when clicked gives me a 404. The problem, it does this only when running the page from within the app's WebView. If I load the page in a desktop browser, or from within Chrome or from within the Android Browser on the mobile, I load the page just fine.
More confusingly, there's another anchor on the same page with the same basic architecture that's working just fine.
The URL for the anchor is being set via JQuery:
var url = ...;
$('#submitButton').attr('href', url);
When I load the page on a desktop browser, I can see the URL that the anchor points to, and it's correct. When I run the page within an app's WebView, I cannot see the URL that the anchor points to, so when it fails, I don't know why.
I'm currently running the website with VS2013 and IIS Express, with bindings and firewalls set so I can access it off my machine. I'm building the app in Android Studio 1.1.0, and am running the app within a GenyMotion emulator.
Is there any way I can examine the DOM of a web page loaded into a webview, so I can see exactly what URL we're trying to load? Or any way I can debug the javascript that is constructing that URL?
Is there any way I can examine the DOM of a web page loaded into a webview, >so I can see exactly what URL we're trying to load? Or any way I can debug >the javascript that is constructing that URL?
Yes, but maybe not with your current tools.
If you do however have an android device connected to your computer, you can actually easily debug the webviews with chrome on your computer.
See the following for more details :
https://developer.chrome.com/devtools/docs/remote-debugging
It is possible to configure a WebView so that console.log() messages show up in LogCat. You need to set a WebChromeClient on the WebView, then implement onConsoleMessage() in your client. From http://developer.android.com/guide/webapps/debugging.html:
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebChromeClient(new WebChromeClient() {
public void onConsoleMessage(String message, int lineNumber, String sourceID) {
Log.d("MyApplication", message + " -- From line "
+ lineNumber + " of "
+ sourceID);
}
});
That got me far enough to figure out what my problem was - the javascript that initialized the link depended upon LocalStorage, and LocalStorage and SessionStorage aren't enabled, in WebViews, by default. You need to enable it with a call to setDomStorageEnabled(). (You also need to enable javascript, but I'd already been doing that):
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings settings = myWebView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);

Android webview - XMLHttpRequest cannot load Origin <url> is not allowed by Access-Control-Allow-Origin

I've an application which loads a complete website in the android webview. The native code in in the android project interacts with the webpage & vice-versa using the Android Jockey Library.
Everything works fine accept at one state I encounter the XMLHttpRequest cannot load ... Origin <url> is not allowed by Access-Control-Allow-Origin error. This happens when the website (that gets loaded in the webview) makes an ajax call to the back-end api.
my website is at m.mywebsite.com which makes an ajax call to api.mywebsite.com - notably two separate sub-domains, but this seems to work fine on iOS.
I'm testing this on Android v4.4.2. Have tested it by compiling agains target sdk 15 and 19 but no difference.
I've applied most of the settings to my webview as follows:
webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setBuiltInZoomControls(false);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDatabaseEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setAllowContentAccess(true);
webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
webView.getSettings().setAllowFileAccessFromFileURLs(true);
webView.getSettings().setAllowContentAccess(true);
webView.getSettings().setAppCacheEnabled(true);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
webView.getSettings().setDatabasePath("/data/data/" + webView.getContext().getPackageName() + "/databases/");
}
webView.getSettings().setSupportZoom(false);
webView.setWebChromeClient(new WebChromeClient());
webView.setInitialScale(0);
And following is my jockey integration:
if (Utils.isNetworkAvailable(this)) {
jockey = JockeyImpl.getDefault();
jockey.configure(webView);
webViewClient = new MyWebViewClient(this);
jockey.setWebViewClient(webViewClient);
setJockeyEvents();
webView.loadUrl(EnvironmentManager.getStartUpURL());
}
Anybody facing similar issue or have a solution for this?
Thanks!
Hi I think you need to set a setting for you web view. Actually this issue come with the devices greater than API level 16. Find the following code:
if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
}
Hope it will work for you.
You may be able to solve this by sending an appropriate Access-Control-Allow-Origin header from the page on api.mywebsite.com like so:
Access-Control-Allow-Origin: http://m.mywebsite.com

window.close() not working in android webview?

Android 4.1
Eclipse
Testing on device
I am trying to open a html/javascript webpage, hosted on my localhost for now, in my android application through a webview.
The page is suppose to just close after 2 sec through the below code
<script type="text/javascript">
alert('hello');
setInterval(function(){window.close();},2000);
</script>
I am able to get the hello alert by using WebChromeClient. But the window.close is still not working. Any help would be appreciated.
PS: Here is how i am loading the URL:
WebSettings ws = webView.getSettings();
ws.setJavaScriptEnabled(true);
ws.setJavaScriptCanOpenWindowsAutomatically(true);
webView.loadUrl("http://192.168.1.137/abc.html");
webView.setWebChromeClient(new WebChromeClient());
Try this :
WebChromeClient webClient = new WebChromeClient(){
public void onCloseWindow(Window w){
super.onCloseWindow(w);
Log.d(TAG, "Window close");
}
};
Description :
public void onCloseWindow (WebView window)
Notify the host application to close the given WebView and remove it from the view system if necessary. At this point, WebCore has stopped any loading in this window and has removed any cross-scripting ability in javascript.
It's not possible on android version > KITKAT. But I have find solution. If android build version > KITKAT, I have detected message from js on server side in method onConsoleMessage of WebChromeClient class http://developer.android.com/reference/android/webkit/WebChromeClient.html.
It works for me.

Android WebView Javascript not enabled

I have the following code in my activity:
browser = (WebView)findViewById(R.id.webkit);
browser.getSettings().setJavaScriptEnabled(true);
browser.getSettings().setPluginsEnabled(true);
browser.getSettings().setDomStorageEnabled(true);
/*if (Build.VERSION.SDK_INT >= 16) {
browser.getSettings().setAllowFileAccessFromFileURLs(true);
browser.getSettings().setAllowUniversalAccessFromFileURLs(true);
}*/
// Loads html-string into webview
browser.loadUrl("file:///android_asset/index.html");
THe page loads fine, the css loads fine, the images all load fine. However I also have a local js file. WHich currently only contains an alert message alert("JSEnabled"); and yet the alert never appears. How can I go about diagnosing this?
I'm currently using the emulator to develop the project and have to support back to Gingerbread (2.3.3).
Incidently the same html / js works fine when I use the Browser app on the emulator (Pointing at a remotely served version of the same HTML / js)
I should also point out - all the files are in the assets folder in the project, and I've tried referencing the js as file:///android_assets/main.js and as main.js. I've even tried referencing the remote js file. Nothing works...
To work your javascript alert please add this to your webview
webview.setWebChromeClient(new WebChromeClient() {
#Override
public boolean onJsAlert(WebView view, String url, String message,
JsResult result) {
return super.onJsAlert(view, url, message, result);
}
});

Categories