Question
I wonder what is the best way to make android webview perform best for the single page application loading.
Situation
I already have a web application with AngularJS.
Currently, I'm building an android application and use webview for the main view of that one.
This android application sends the http request every time when users click the menu on native side.
Sadly, webview loading is very slow since it always get entire resource from my web application, although one of great benefits of the single-page-application is url routing function without refreshing page entirely as I understand correctly. Below is my code for webview loading. Nothing changed I set setCacheMode(WebSettings.LOAD_DEFAULT) though.
webviewFragment.java
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String url = getArguments().getString("URL");
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setAllowFileAccess(true);
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
webView.loadUrl(url);
webView.setWebViewClient(new WebViewClient() {
// handle url-scheme
}
webView.setWebChromeClient(new WebChromeClient() {
// handle reaction for UI Component
}
}
Related
I am trying to write an app I want it to open a web page and auto login I am not sure how to go about sending the info to the browser from the app code.
So basically you are going to need to load in the webpage within a WebView (You can find instructions for that here and then probably push javascript into the WebView that will fill in the fields and load the page.
In your activity's onCreate:
WebView webview = new WebView(this);
setContentView(webview);
webView.setWebViewClient(new WebViewClient(){
#Override
public boolean onPageFinished(WebView view, String url) {
// Check here if url is equal to your site URL.
}
});
webview.loadUrl("http://yourwebsite.com/");
This line enables javascript in your WebView:
webView.getSettings().setJavaScriptEnabled(true);
Then you can use the WebViewClient to detect when the page you want has fully loaded. When that happens, you can use:
webView.loadUrl("javascript:document.getElementsByName('username').value = 'username'");
webView.loadUrl("javascript:document.getElementsByName('password').value = 'password'");
webView.loadUrl("javascript:document.forms['login'].submit()");
And it should automatically log you in. It's worth noting that this generally isn't easy to do on a lot of sites since they will randomize the login control ids and it also doesn't generally sit well with users if an application is logging into a website automatically for them.
I'm developing an app using PhoneGap. So, it's a web app. In this app, I have a requirement to embed a YouTube video and autoplay it whenever the user navigates to that particular page.
I've read that HTML5 video autoplay doesn't work on mobile devices because of bandwidth concers. My question is that is there any way at all to bypass this restriction? I don't mind complex workarounds or hacks that could allow me to do this. Anything at all.
Thanks.
As you pointed out yourself, all autoplay instructions in your code itself will be ignored on load. So we'll implement a function that gets the video in the body and starts playing it.
The following javascript code could do this:
(function() {
document.getElementsByTagName('video')[0].play();
})()
To execute this code after the page has loaded, we need to set a WebViewClient and implement onPageFinished()
webview.setWebViewClient(new CordovaWebViewClient(this, webview) {
// autoplay when finished loading via javascript injection
public void onPageFinished(WebView view, String url) { webview.loadUrl("javascript:(function() { document.getElementsByTagName('video')[0].play(); })()"); }
});
final WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setPluginState(WebSettings.PluginState.ON);
A full example:
webview = new CordovaWebView(this);
setContentView(webview);
final WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setPluginState(WebSettings.PluginState.ON);
webview.setWebViewClient(new CordovaWebViewClient() {
// autoplay when finished loading via javascript injection
public void onPageFinished(WebView view, String url) { webview.loadUrl("javascript:(function() { document.getElementsByTagName('video')[0].play(); })()"); }
});
webview.loadUrl("http://html5demos.com/video");
There is a cordova/phonegap plugin that promises to do this. It rely on the Webview method setMediaPlaybackRequiresUserGesture, added in API level 17 (Android 4.2).
It simply call this method on the webview:
WebView view = getWebViewFromPlugin();
view.getSettings().setMediaPlaybackRequiresUserGesture(false);
It's also available in phongap build.
I am trying to make an Android app display a website in a WebView, but only the website home page actually show content properly via the WebView, the other pages completely disregard the website styles and display content with a white background and blue default hyperlinks. I tested the same type of app on iOS and it works fine there. What can I do about it?
This is the method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView myWebView = (WebView) findViewById(R.id.webView);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.setWebViewClient(new WebViewClient());
myWebView.loadUrl("http://www.awesomestories.com");
}
Settings should be set. Tricks Like this:
WebSettings settings = webview.getSettings();
settings.setBuiltInZoomControls(true);
settings.setPluginState(PluginState.ON);
settings.setJavaScriptEnabled(true);
settings.setSupportZoom(true);
If you have kept Single Column Setting in WebView remove it, it will work just perfect.
myWebView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
If you have not kept Single Column setting and still its not working, then check that you have enabled JavaScript or not, if not then enable it.
myWebView.getSettings().setJavaScriptEnabled(true);
Android WebView requires you to explicitly enable javascript.
Styles in the page may be loaded via javascript, and generally websites don't tend to work good without it, so enabling it is important and might solve your problem in addition to that.
myWebView.getSettings().setJavaScriptEnabled(true);
I am experimenting with Android code: I would like to store one value using HTML 5 local storage. For this exercise I' using a page as simple as this one:
http://www.w3schools.com/html5/tryit.asp?filename=tryhtml5_webstorage_local_clickcount
My manifest does allow me to hit the internet, and it is min-sdk of 7.
Here is my java code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webview = (WebView) findViewById(R.id.webview);
WebView webView = (WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new JavaScriptInterface(this), "Android");
WebSettings webSettings = webview.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDatabasePath("");
webSettings.setDomStorageEnabled(true);
webview.setWebChromeClient(new WebChromeClient());
webview.loadUrl("http://www.xyz.com/test.html");
///xyz.com/test.html is a sample :)
webview.setWebViewClient(new HelloWebViewClient());
}
My problem is that when I close the app, the locally stored value is no longer there. I can browse to the same page using the default browser, and the value is persistent even after closing the emulator, which is exactly the behavior that I am looking for.
This is probably a something extremely simple....any ideas?
It appears the empty string DatabasePath is the problem. I tried similar code and with an empty string path, the value does not persist after the app exits. If I define a specific database path, the value persists as expected.
Try:
webSettings.setDatabasePath("/data/data/"+this.getPackageName()+"/databases/");
If your app use multiple webview you will still have troubles : localStorage is not correctly shared accross all webviews.
If you want to share the same data in multiple webviews the only way is to repair it with a java database and a javascript interface.
This page on github shows how to do this.
hope this help!
Couldn't get it working on all devices (especially with ICS) - even with database path, enabling DOMStorage etc. - using cookies instead helped me out.
I have an application on appspot that works fine through regular browser, however when used through Android WebView, it cannot set and read cookies. I am not trying to get cookies "outside" this web application BTW, once the URL is visited by WebView, all processing, ids, etc. can stay there, all I need is session management inside that application. First screen also loads fine, so I know WebView + server interactivity is not broken.
I looked at WebSettings class, there was no call like setEnableCookies.
I load url like this:
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webview = new WebView(this);
setContentView(webview);
webview.loadUrl([MY URL]);
}
..
}
Any ideas?
If you are using Android Lollipop i.e. SDK 21, then:
CookieManager.getInstance().setAcceptCookie(true);
won't work. You need to use:
CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);
I ran into same issue and the above line worked as a charm.
From the Android documentation:
The CookieSyncManager is used to synchronize the browser cookie
store between RAM and permanent storage. To get the best performance,
browser cookies are saved in RAM. A separate thread saves the cookies
between, driven by a timer.
To use the CookieSyncManager, the host application has to call the
following when the application starts:
CookieSyncManager.createInstance(context)
To set up for sync, the host application has to call
CookieSyncManager.getInstance().startSync()
in Activity.onResume(), and call
CookieSyncManager.getInstance().stopSync()
in Activity.onPause().
To get instant sync instead of waiting for the timer to trigger, the
host can call
CookieSyncManager.getInstance().sync()
The sync interval is 5 minutes, so you will want to force syncs
manually anyway, for instance in onPageFinished(WebView, String). Note
that even sync() happens asynchronously, so don't do it just as your
activity is shutting down.
Finally something like this should work:
// use cookies to remember a logged in status
CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().startSync();
WebView webview = new WebView(this);
webview.getSettings().setJavaScriptEnabled(true);
setContentView(webview);
webview.loadUrl([MY URL]);
I figured out what's going on.
When I load a page through a server side action (a url visit), and view the html returned from that action inside a Webview, that first action/page runs inside that Webview. However, when you click on any link that are action commands in your web app, these actions start a new browser. That is why cookie info gets lost because the first cookie information you set for Webview is gone, we have a seperate program here.
You have to intercept clicks on Webview so that browsing never leaves the app, everything stays inside the same Webview.
WebView webview = new WebView(this);
webview.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
view.loadUrl(url); //this is controversial - see comments and other answers
return true;
}
});
setContentView(webview);
webview.loadUrl([MY URL]);
This fixes the problem.
My problem is cookies are not working "within" the same session. –
Burak: I had the same problem. Enabling cookies fixed the issue.
CookieManager.getInstance().setAcceptCookie(true);
CookieManager.getInstance().setAcceptCookie(true); Normally it should work if your webview is already initialized
or try this:
CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
cookieManager.setAcceptCookie(true);