I have an issue with Webview. I'm programming my own WebChromeClient class overriding onProgressChanged method because I want to show the page when it finishes loading and then, to hide the splash screen. As I just want it to happen with a specific URL, I compare the actual WebView URL with a specific string, but there is a problem, I get a null pointer when webview.getUrl() method is called and my application finishes.
This is the code:
private class MyWebChromeClient extends WebChromeClient {
#Override
public void onProgressChanged (WebView webview, int newProgress) {
super.onProgressChanged(webview,newProgress);
if(webview.equals(w1) && newProgress == 100 && webview.getUrl().startsWith("https://ssl.facebook.com/login.php")) {
webview.setVisibility(WebView.VISIBLE);
ImageView imageview = (ImageView)findViewById(R.id.ivsplash);
imageview.setVisibility(ImageView.GONE);
ProgressBar progressbar = (ProgressBar)findViewById(R.id.pbsplash);
progressbar.setVisibility(ProgressBar.GONE);
}
}
}
I do this for avoid the webview takes three or four seconds to render the page, but it doesn't work. The code I used before was:
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView webview, String url) {
super.shouldOverrideUrlLoading(webview, url);
webview.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView webview, String url) {
if(url.startsWith("https://ssl.facebook.com/login.php")) {
webview.setVisibility(WebView.VISIBLE);
ImageView imageview = (ImageView)findViewById(R.id.ivsplash);
imageview.setVisibility(ImageView.GONE);
ProgressBar progressbar = (ProgressBar)findViewById(R.id.pbsplash);
progressbar.setVisibility(ProgressBar.GONE);
}
}
}
Not sure if this is possible with WebChromeClient, but I was able to do this using
WebViewClient and overloading onLoadResource, onReceivedError and onPageFinished
This is what I've done
onLoadResource
mwebview.setVisibility(View.GONE);
onReceivedError
mwebview.setVisibility(View.VISIBLE);
onPageFinished
mwebview.setVisibility(View.VISIBLE);
and intially in XML the webview is set as GONE
android:visibility="gone"
I too use it for Facebook and works fine.
Related
WebView is now showing but before that a blank white screen is appearing which might be due to loading of the url.
// webview to load url
webView.loadUrl("https://www.google.com/");
I want to add onCompletionListener when the url is fully loaded and webview is ready to display the conent.
try this one
How can I know that my WebView is loaded 100%?
Or this Url
https://android--code.blogspot.com/2016/03/android-detect-when-webview-finish.html
// Set a WebViewClient for WebView
mWebView.setWebViewClient(new WebViewClient(){
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon){
// Page loading started
}
/*
public void onPageFinished (WebView view, String url)
Notify the host application that a page has finished loading. This
method is called only for main frame. When onPageFinished() is called,
the rendering picture may not be updated yet. To get the notification
for the new Picture, use onNewPicture(WebView, Picture).
Parameters
view WebView: The WebView that is initiating the callback.
url String: The url of the page.
*/
#Override
public void onPageFinished(WebView view, String url){
// Page loading finished
Toast.makeText(mContext,"Page Loaded.",Toast.LENGTH_SHORT).show();
}
});
// Set a WebChromeClient for WebView
// Another way to determine when page loading finish
mWebView.setWebChromeClient(new WebChromeClient(){
/*
public void onProgressChanged (WebView view, int newProgress)
Tell the host application the current progress of loading a page.
Parameters
view WebView: The WebView that initiated the callback.
newProgress int: Current page loading progress, represented by an
integer between 0 and 100.
*/
public void onProgressChanged(WebView view, int newProgress){
mTextView.setText("Page loading : " + newProgress + "%");
if(newProgress == 100){
// Page loading finish
mTextView.setText("Page Loaded.");
}
}
});
// Enable JavaScript
mWebView.getSettings().setJavaScriptEnabled(true);
// Load the url in the WebView
mWebView.loadUrl(mURL);
}
You just need to implement WebViewClient and use onPageFinished() as follows:
mWebView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
// do what you want
}
});
Read more about this here.
Just add this one
webView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
// do whatever you want
}
});
refrance here
I have a custom implementation of WebViewClient that overrides onPageFinished(), where I swap my loading view with the WebView. Sometimes everything works great, but other times onPageFinished() doesn't get called at all. It's completely random.
onPageStarted() always gets called.
public class LoaderWebViewClient extends WebViewClient {
private final TableLayout swapTableLayout;
public LoaderWebViewClient(TableLayout swapTableLayout) {
this.swapTableLayout = swapTableLayout;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
// Sometimes doesn't get called
#Override
public void onPageFinished(WebView view, String url) {
swapTableLayout.removeAllViews();
swapTableLayout.addView(view);
super.onPageFinished(view, url);
}
}
I am instantiating a WebView from a custom class:
WebView webView = new WebView(context);
WebViewClient webViewClient = new LoaderWebViewClient(swapTableLayout);
webView.setWebViewClient(webViewClient);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setUseWideViewPort(true);
webView.setVerticalScrollBarEnabled(false);
webView.setHorizontalScrollBarEnabled(false);
webView.getSettings().setJavaScriptEnabled(true);
webView.setOverScrollMode(WebView.OVER_SCROLL_NEVER);
webView.loadUrl(url);
I have found the problem. In onPageFinished() I am removing all the views from the layout inside which the WebView itself would reside (as seen in the next line).
And that somehow disrupts the loading of the WebView. I have just replaced removing and reinserting views with hiding and showing them (they are always inflated in the layout) and everything seems to work fine.
In webview android I am trying to load a url and in order to check if the load of this url is done successfully (internet connection was available, the server was up etc) I was under the impression that webview.loadUrl would throw exceptions, but wrong! as it explicitly is stated in here "an exception will NOT be thrown".
So how can I check to see if webview.loadUrl did not fail ?
Unfortunately, currently there is no easy way in WebView to ensure that everything on the page has been loaded successfully. We are hoping for a better API to come up in future version. Let me explain what you can do now.
First of all, in order to detect any problems that prevent WebView from making a connection to the server for loading your main page (e.g. bad domain name, I/O error, etc.), you should use WebViewClient.onReceivedError callback as other people correctly suggest:
public class MyWebViewClient extends WebViewClient {
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
// Make a note about the failed load.
}
}
myWebView.setWebViewClient(new MyWebViewClient());
If the server connection was successful, and the main page was retrieved and parsed, you will receive WebView.onPageFinished callback, so you also need to have this in your WebViewClient subclass:
public class MyWebViewClient extends WebViewClient {
...
#Override
public void onPageFinished(WebView view, String url) {
// Make a note that the page has finished loading.
}
...
}
The caveat here is that if you have received an HTTP error from the server (e.g. a 404 or a 500 error), this callback will be called anyway, it's just the content that you will get in your WebView will be a server error page. People suggest different ways of how to deal with it, see the answers here: How can I check from Android WebView if a page is a "404 page not found"? Basically, it really depends on what you expect to be a "good" page and a "error" page. Unfortunately, there is currently no way for the app to get the HTTP response code from WebView.
The callbacks WebViewClient.onPageStarted and WebViewClient.onProgressChanged are only useful if you want to draw a progress bar as you are loading the page.
Also note that the way of overriding WebViewClient.shouldOverrideUrlLoading that people usually suggest is not correct:
public class MyWebViewClient extends WebViewClient {
...
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// !!! DO NOT DO THIS UNCONDITIONALLY !!!
view.loadUrl(url);
return true;
}
...
}
What few developers realize is that the callback is also called for subframes with non-https schemes. If you'll encounter something like <iframe src='tel:1234'>, you will end up executing view.loadUrl('tel:1234') and your app will show an error page, since WebView doesn't know how to load a tel: URL.
It is recommended to simply return false from the method, if you want WebView to do the loading:
public class MyWebViewClient extends WebViewClient {
...
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Returning 'false' unconditionally is fine.
return false;
}
...
}
This doesn’t mean you should not call WebView.loadUrl from shouldOverrideUrlLoading at all. The specific pattern to avoid is doing so unconditionally for all URLs.
public class AppWebViewClient extends WebViewClient {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
setProgressBar(true);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
//Page load finished
super.onPageFinished(view, url);
setProgressBar(false);
}
}
and then you can do
webView.setWebViewClient(new AppWebViewClient());
For the error part you can override the onReceivedError method
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
// TODO Auto-generated method stub
super.onReceivedError(view, errorCode, description, failingUrl);
}
Here is what I came up with, it works like a charm.
Boolean failedLoading = false;
WebView webView = view.findViewById(R.id.webView);
webView.loadUrl("www.example.com");
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (!failedLoading) {
webView.setVisibility(View.VISIBLE);
webView.setAlpha(0f);
ObjectAnimator anim = ObjectAnimator.ofFloat(webView, "alpha",1f);
anim.setDuration(500);
anim.start();
}
}
#Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
failedLoading = true;
}
});
It will also work great if you add some kind of a refresh button and then you can call the code above inside a function to try again.
You can check if a URL is loaded successfully by using onProgressChanged()
mWebView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
progressBar.setProgress(progress);
if (progress == 100) {
//your url is loaded successfully
}
}
});
Is it possible to show a progressbar while loading a url? I need to show the level of progress in the progressbar for which i can use a custom progressbar. But am not able to find out the code for getting he exact progress of how much the url has loaded. This is my current code:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
browser = (WebView)findViewById(R.id.webView1);
progressBar = (ProgressBar)findViewById(R.id.progressBar);
browser.setWebViewClient(new MyBrowser());
browser.setWebChromeClient(new MyCustomChromeClient());
mContext=this.getApplicationContext();
browser.loadUrl(target_url);
MainActivity.this.progressBar.setProgress(0);
}
private class MyBrowser extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
String host = Uri.parse(url).getHost();
if (host.equals(target_url_prefix))
{
if(mWebviewPop!=null)
{
mWebviewPop.setVisibility(View.GONE);
baseLayout.removeView(mWebviewPop);
mWebviewPop=null;
}
return false;
}
if(host.equals("m.facebook.com"))
{
return false;
}
view.loadUrl(url);
return true;
}
#Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
noInternet();
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
visible();
}
#Override
public void onPageFinished(WebView view, String url) {
unvisible();
System.out.println("\n" +view.getUrl());
if(url.startsWith("https://m.facebook.com/v2.1/dialog/oauth")){
if(mWebviewPop!=null)
{
mWebviewPop.setVisibility(View.GONE);
baseLayout.removeView(mWebviewPop);
mWebviewPop=null;
}
view.loadUrl(redirectUrl);
return;
}
super.onPageFinished(view, url);
}
}
private class MyCustomChromeClient extends WebChromeClient
{
#Override
public boolean onCreateWindow(WebView view, boolean isDialog,
boolean isUserGesture, Message resultMsg) {
mWebviewPop = new WebView(mContext);
mWebviewPop.setVerticalScrollBarEnabled(false);
mWebviewPop.setHorizontalScrollBarEnabled(false);
mWebviewPop.setWebViewClient(new MyBrowser());
mWebviewPop.getSettings().setJavaScriptEnabled(true);
mWebviewPop.getSettings().setSavePassword(false);
mWebviewPop.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
baseLayout.addView(mWebviewPop);
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
transport.setWebView(mWebviewPop);
resultMsg.sendToTarget();
return true;
}
#Override
public void onCloseWindow(WebView window) {
}
#Override
public void onProgressChanged(WebView view, int newProgress) {
MainActivity.this.setValue(newProgress);
super.onProgressChanged(view, newProgress);
}
}
public void setValue(int progress) {
this.progressBar.setProgress(progress);
}
}
How to get the exact progress of loading a url. With this code, i can get the progressbar loading, but its shown as an indeterminate progressbar. I want to show a progressbar which is a customised view. It should display the percentage of succesful loading of the url. So maye i can inflate a customised view, but again i dont know how to get exact percentage. Can someone help me with this code.
The onProgressChanged() of WebChromeClient gives you the progress about the status of page loading. See the below info about the function from the android api docs.
public void onProgressChanged (WebView view, int newProgress)
Added in API level 1
Tell the host application the current progress of loading a page.
Parameters
view The WebView that initiated the callback.
newProgress Current page loading progress, represented by an integer between 0 and 100.
I am not familiar with your Webview. But I open URLs in doInBackground AsyncTask ussualy. So I cannot find a way to express this in percentage directly. But what you could do is maybe trick around, with something like:
Set 20% when your app has confirmed that there is a INTERNET connection enables on the Device.
Set 50% when it reaches the AsyncTask to open URL (or however you initialize .connect())
And finally set 100% when URL is opened.
This is a dummy method. But otherwise you should somehow work with Time (seconds). But an App cannot forsee how long will it need to open the URL. The 100% would represent seconds needed to open the URL, but this is not accessable during loading the URL, since App doesn't know at that time how much it needs to open it.
You could do a test run and time the seconds. Set a timer, when you start opening the URL, and stop the timer when it opens it. But that time would just be in that particular case.. if someone uses a slow Android Device, or Bad Internet Connection, it would probably take longer.
Hope my answer is alteast a bit helpful. If there exists a method to do something more precisely, I am sure guys here will write it.
In my App i want to cache a webapage in the background with a hidden webview (at the same time another webview is visible to the user and loads another url).
I start the caching in onResume. Here are the code snippets:
1.) onResume:
#Override
public void onResume() {
new LibraryCacher().startCaching(this);
//some more code...
}
2.) LibraryCacher:
public class LibraryCacher extends BasicClass {
public LibraryCacher () {}
public void startCaching(Context context) {
getLogger().debug("startCaching()");
if (NetworkHandler.isOnline(context) == false) {
getLogger().info("We are offline, no caching");
return;
}
final String URL_TO_CACHE = "http://myUrl.com";
WebView w = new WebView(context);
w.setVisibility(View.GONE);
WebSettings webset = w.getSettings();
webset.setJavaScriptEnabled(true);
webset.setDomStorageEnabled(true);
webset.setDatabaseEnabled(true);
webset.setJavaScriptCanOpenWindowsAutomatically(true);
webset.setSupportMultipleWindows(true);
webset.setAppCacheEnabled(true);
webset.setLoadsImagesAutomatically(true);
webset.setAppCachePath(w.getContext().getCacheDir().getAbsolutePath());
webset.setAllowFileAccess(true);
webset.setCacheMode(WebSettings.LOAD_DEFAULT);
w.setWebViewClient(new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
getLogger().debug(url + " caching...");
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
getLogger().debug(url + "cached");
}
});
w.setWebChromeClient(new WebChromeClient());
getLogger().debug("load Url");
w.loadUrl(URL_TO_CACHE);
}
}
At the FIRST-CACHE-TRY (app starts the first time) logcat looks like this:
startCaching()
load Url
http://myUrl.com caching...
After that i put the app in the background and resume it. So, at the SECOND-CACHE-TRY logcat looks like this:
startCaching()
loadUrl
http://myUrl.com caching...
http://myUrl.com cached
My question:
Why doesn't the webview invoke its method onPageFinished at the first try?
EDIT :
It works, if i invoke
new LibraryCacher().startCaching(this);
in onPageFinished of the other webview, which is visible to the user and loads simultaneously another url.
Does anyone know why?
Webviews in android seem to have some shared state. In my case, onPageFinished was never called, because i used:
#Override
public void onPause() {
webView.pauseTimers();
}
On a completely different webview, in a different activity.