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);
Related
If you have a webview open in Android, you can inspect it in Chrome devtools. However, I can't open the devtools first, then open the webview to log network requests that occur on page load. Is there a way to log network requests that occur as soon as the webview loads?
Also, refreshing the page behaves differently from the initial load because the page modifies the URL.
You can intercept various components of WebView communication by implementing your own WebViewClient. A short snippet is below:
webView.webViewClient = object : WebViewClient() {
override fun shouldInterceptRequest(view: WebView,
request: WebResourceRequest): WebResourceResponse? {
// Use the `request` object as needed.
}
}
More information regarding the WebViewClient, including other possible overrides, can be found here.
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.
I am trying to save the HTML from a webpage into a file so if my app is opened and no internet is available then the webview loads from a file instead. Here is my debugging code - the first time the view is created it downloads the file. The second time onwards it opens the files
WebView cwebView = (WebView) rootView.findViewById(R.id.aboutWebview);
if(loadedLatest) {
cwebView.loadData(FileUtils.read(Values.aboutWebviewOfflineFile,getContext()),"text/html", "UTF-8");
cwebView.getSettings().setJavaScriptEnabled(true);
//cwebView.getSettings().setBuiltInZoomControls(true);
}else {
cwebView.loadUrl(Values.aboutPageURL);
new GetWebviewContents(getContext()).execute(Values.aboutPageURL, Values.aboutWebviewOfflineFile) //Saves the HTML to a file;
loadedLatest = true;
}
The HTML download and file seem to be working correctly however the webview looks completely different when from online and when from the file - it is much narrower and images overlap. I have tried using .loadurl(File...) and it has the same effect. Enabling Javascript makes no difference.
Does anyone have any idea what could be causing this?
Thanks
I don't know for sure, but it could be the issue of Cross-Origin blocking by the WebView. To verify that this is the issue, open the same webpage that you saved on your app, on your laptop or desktop, and save it on your disk. Then try to open that saved page and see the Javascript console on your's browser Developer Tools and see if it shows any Cross-Origin access restriction errors.
I'm trying to automatically redirect from a local html file in an android web-view to a browser window when a cookie is read. The JavaScript below opens the URL in the web-view but I need it to open in a separate browser instead.
onload=function(){
document.getElementById('linksNewWindow').checked = readCookie('linksNewWindow')==1? true : false;
if(document.getElementById('linksNewWindow').checked = readCookie('linksNewWindow')== true){
location.href = "url";
}
}
The code for the android app just calls the local html file into the webview
if (android.os.Build.VERSION.RELEASE.startsWith("4.4.2")) {
String localUrl = "file:///android_asset/splash/splashKitkat.html";
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl(localUrl);
}
I'm not sure if this is a small issue with my javascript or something bigger if someone could help me out that would be great.
Thanks in advance
You can use Javasctipt-Java bridge and call Android code from your custom HTML javascript inside WebView. That Android code may launch intent for the external browser. See more Call Java function from JavaScript over Android WebView
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);
}
});