onPageFinished method is called BEFORE the website finishes loading? - android

It seems that I made some inaccuracies or I missed something regarding public class myWebViewClient class and public void onPageFinished(WebView view, String url). Initially and in the beginning I tried to launch www.yahoo.com and after it finishes loading I fire a toast from inside the public void onPageFinished(WebView view, String url) as indication to me the loading of the www.yahoo.com is finished, and up to here every thing is fine. Inside my RelativeLayout I have a button and edittext and my webview is layedout-above them. The purpose of having an edittext is to enable the user to enter their webite and by clicking on go-button, the entered website should be launched and I expect to see the toast I have inside public void onPageFinished(WebView view, String url) is fired again after the new website finishes loading. But what happens is, once the user enters a new website in the edittext field and immediately after they press go_button the toast fires before even the website is loaded and it fires once again after the same web site is finished loading. Actually, I expect the toast to be fired only after every website finishes loading, but what is happening with me is not like that. Please provide me with suggestions to prevent occurring such problem.
JavaCode:
OnClickListener btnGoListener = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
webView00.loadUrl(etUrl.getText().toString());
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_web_page00);
webView00 = (WebView) findViewById(R.id.webView00);
btnGo = (Button) findViewById(R.id.go_btn);
etUrl = (EditText) findViewById(R.id.url_edittext);
webView00.getSettings().setJavaScriptEnabled(true);
webView00.setWebViewClient(new myWebViewClient());
webView00.setWebChromeClient(new myWebChromeClient());
btnGo.setOnClickListener(btnGoListener);
webView00.loadUrl("http://google.com");
}
public class myWebChromeClient extends WebChromeClient {
}
public class myWebViewClient extends WebViewClient {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Toast.makeText(getBaseContext(), "Loading Finished", Toast.LENGTH_LONG)
.show();
}
};

From the documentation :
When onPageFinished() is called, the rendering picture may not be updated yet.
To get the notification for the new Picture, use onNewPicture(WebView, Picture).
http://developer.android.com/reference/android/webkit/WebViewClient.html#onPageFinished(android.webkit.WebView, java.lang.String)
I suggest that you implement method onProgressChanged from WebChromeClient.
Documentation :
http://developer.android.com/reference/android/webkit/WebChromeClient.html#onProgressChanged(android.webkit.WebView, int)

Have not tried the Chrome client yet, so have commented that one out, perhaps you can change seamlessly between them.
Nevertheless, I would think something like this should work:
OnClickListener btnGoListener = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
webView00.loadUrl(etUrl.getText().toString());
webView00.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
Toast.makeText(getBaseContext(), "Loading Finished 2", Toast.LENGTH_LONG)
.show();
}
});
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_web_page00);
webView00 = (WebView) findViewById(R.id.webView00);
btnGo = (Button) findViewById(R.id.go_btn);
etUrl = (EditText) findViewById(R.id.url_edittext);
webView00.getSettings().setJavaScriptEnabled(true);
btnGo.setOnClickListener(btnGoListener);
webView00.loadUrl("http://google.com");
//webView00.setWebViewClient(new myWebViewClient());
//webView00.setWebChromeClient(new myWebChromeClient());
webView00.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
Toast.makeText(getBaseContext(), "Loading Finished 1", Toast.LENGTH_LONG)
.show();
}
});
}

I noticed onPageFinished is sometimes called multiple times if the webview re-rendered a page that was already loaded. On the reload, the webview would first render about:blank and calls onPageFinished before loading the actual webpage and calling onPageFinished again. The sequence is:
load www.google.com
onPageFinished is called
load 'www.google.com' again
onPageFinished is called. The URL is about:blank
onPageFinished is called. The URL is www.google.com
To get around this issue in step 4, you can check that the url parameter passed to onPageFinished is the one you care about:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
webView00.loadUrl(myWebPage);
}
public class myWebViewClient extends WebViewClient {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, URL);
if(url == myWebPage) {
Toast.makeText(getBaseContext(), "Loading Finished", Toast.LENGTH_LONG)
.show();
}
};

Related

onPageFinished is firing before page is loaded

I just want to know when html page is loaded. OnPageFinished is called before whole page is loaded. I got blank view when I set Image View by bitmap created from WebView
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setAlwaysDrawnWithCacheEnabled(true);
mWebView.setWebViewClient(new WebViewClient(){
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon){
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view,String url){
Bitmap b = Bitmap.createBitmap( 480, 240, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
view.draw(c);
mImageView.setImageBitmap(b);
//b.recycle();
}
});
EDIT :
I tried to implement JavaScriptInterface for now only with making Toast message, but it still doesn't work. I've pasted html code and Java :
EDIT :
I finally got it working. I used JavaScriptInterface with proper . When loadUrl is launch html file is being loaded. When whole page is available on screen, onload function from html file call captureImage function from JavaScriptInterface class. Now I have sure that page is fully loaded and I can grab picture of it. Thanks for all help.
CODE:
JAVA :
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setDrawingCacheEnabled(true);
mWebView.addJavascriptInterface(new JavaScriptInterface(this), "Android");
mWebView.setWebViewClient(new WebViewClient(){});
mButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mWebView.loadUrl("file:///android_asset/html_sample.html");
//mWebView.loadUrl("https://www.onet.pl");
}
});
public class JavaScriptInterface {
private Context mContext;;
public JavaScriptInterface(Context context) {
mContext = context;
}
#JavascriptInterface
public void captureImage(){
Bitmap b = mWebView.getDrawingCache(true);
mImageView.setImageBitmap(b);
}
#JavascriptInterface
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
}
}
HTML :
<html>
<head>
<title>My first styled page</title>
<link rel="stylesheet" href="sample_css.css">
</head>
<body onload="function(){ Android.captureImage() }">
...
</body>
</html>
This is because onPageFinished means "the page has finished loading", not "the page is on screen". Unfortunately the WebView doesn't have a 'the page you wanted is now on screen' API. Folks usually resort to a combination of PictureListener (which was deprecated since it's unreliable) and random timeouts (which are either super long or don't work on some devices).
You could try by rendering to a small bitmap and checking if it's all white on every PictureListener callback (and remember to stop doing this when you're done waiting, otherwise you'll burn tons of CPU if the page has animations/gifs/etc..). Rendering to a small bitmap will still be very CPU-intensive if the page has big images, so this is definitely not a great solution.
It happened to me also, that in WebViewClient, the callback onPageFinished kicks in before the actual window.load event.
Still investigating on why this happens sometimes, which is hard because the android app is produced by a heavily customized in-house hybrid app generator.
Nevertheless, I've got past this issue by implementing a safeguard that checks if there is an error in the script that I want to call in onPageFinished, in which case I add an event handler which calls again my script during window.load.
You can also use document.addEventListener("DOMContentLoaded", ...) instead of window.load.
Below is a code snippet that exemplifies this, also with debug.log calls. You can pass the call to your javascript interface as argument
private void executeOnLoad(final WebView view, final String jsStringToExecute) {
StringBuilder sb = new StringBuilder("javascript:");
sb.append("try {console.log('native.onPageFinished. document.readyState: ' + document.readyState);").append(jsStringToExecute).append("} catch(err){console.log('error calling jsBridge script on page load, deferring call to window.load event');")
.append("window.addEventListener('load', function() {console.log('window.onload callled from native. document.readyState: ' + document.readyState);").append(jsStringToExecute).append("});").append("}");
String jsWithWindowLoadedFallback = sb.toString();
view.loadUrl(jsWithWindowLoadedFallback);
}
Found simple technique to load page even after onPageFinished is called--
Recursively call loadUrl method until page is not loaded successfully..
#Override
public void onPageFinished(WebView view, String url) {
// progressDialog.hide();
Log.e("onPageFinished","onPageFinished");
if (view.getContentHeight() == 0){
pbar.setVisibility(View.VISIBLE);
webView.loadUrl("https://drive.google.com/viewerng/viewer?embedded=true&url="+pdf);
}
else {
pbar.setVisibility(View.GONE);
}
}
try this :-
OnClickListener btnGoListener = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
webView00.loadUrl(etUrl.getText().toString());
webView00.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
Toast.makeText(getBaseContext(), "Loading Finished 2", Toast.LENGTH_LONG)
.show();
}
});
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_web_page00);
webView00 = (WebView) findViewById(R.id.webView00);
btnGo = (Button) findViewById(R.id.go_btn);
etUrl = (EditText) findViewById(R.id.url_edittext);
webView00.getSettings().setJavaScriptEnabled(true);
btnGo.setOnClickListener(btnGoListener);
webView00.loadUrl("http://google.com");
//webView00.setWebViewClient(new myWebViewClient());
//webView00.setWebChromeClient(new myWebChromeClient());
webView00.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
Toast.makeText(getBaseContext(), "Loading Finished 1", Toast.LENGTH_LONG)
.show();
}
});
}
Use WebViewClient and onPageFinished method as below:
mWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) {
if (!loadingFinished) {
redirect = true;
}
loadingFinished = false;
webView.loadUrl(urlNewString);
return true;
}
#Override
public void onPageStarted(WebView view, String url) {
loadingFinished = false;
//SHOW LOADING IF IT ISNT ALREADY VISIBLE
}
#Override
public void onPageFinished(WebView view, String url) {
if(!redirect){
loadingFinished = true;
}
if(loadingFinished && !redirect){
Bitmap b = Bitmap.createBitmap( 480, 240, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
view.draw(c);
mImageView.setImageBitmap(b);
} else{
redirect = false;
}
}
});
For more information refer https://stackoverflow.com/a/5172952/685240
Hope it helps.
EDIT : As per your comment, I think your page gets loaded successfully but it takes time to render/draw the page on screen, which is the cause of your issue. Try with implementing onPictureListener for webview. For more reference, refer https://stackoverflow.com/a/18123023/685240

Android WebView is blank after network disconnect

I have a following scenario for webview
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view_tutorial);
mWebView = (WebView) findViewById(R.id.webView1);
mWebView.setWebViewClient(mWebViewClient);
mWebView.setInitialScale(0);
mWebView.setVerticalScrollBarEnabled(false);
mWebView.requestFocusFromTouch();
WebSettings settings = mWebView.getSettings();
settings.setJavaScriptEnabled(true);
Button btnGo = (Button) findViewById(R.id.button1);
btnGo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String url = "http://www.google.com";// here goes my server url with https://...... for authentication
showProgressDialog("Loading");
mWebView.loadUrl(url);
}
});
}
private void showProgressDialog(String title) {
if(mProgress == null || !mProgress.isShowing()){
mProgress = ProgressDialog.show(this, title, "Please wait...", true,
true, new OnCancelListener() {
public void onCancel(DialogInterface pd) {
finishActivity();
}
});
mProgress.setCanceledOnTouchOutside(false);
mProgress.setCancelable(true);
}
}
private void finishActivity() {
if(mWebView!=null){
finish();
}
}
private final WebViewClient mWebViewClient = new WebViewClient() {
public void onPageStarted(WebView view, String url,
android.graphics.Bitmap favicon) {
super.onPageStarted(view, url, favicon);
Log.d("test", "page started");
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.d("test", "page should override called");
return super.shouldOverrideUrlLoading(view, url);
}
#Override
public void onPageFinished(WebView view, String url) {
if (mIsLoadingSigninPage) {
mIsLoadingSigninPage = false;
dismissProgressDialog();
}
Log.d("test", "page finished");
super.onPageFinished(view, url);
}
#Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
mIsLoadingSigninPage = false;
dismissProgressDialog();
Log.d("test", "page error received");
super.onReceivedError(view, errorCode, description, failingUrl);
finishActivity();
}
};
private void dismissProgressDialog() {
if (mProgress != null && mProgress.isShowing()) {
mProgress.dismiss();
mProgress =null;
}
}
// this is log cat for point 3 below
03-07 07:31:20.977: D/test(1431): page started
03-07 07:31:22.788: D/test(1431): page should override called
03-07 07:31:22.887: D/test(1431): page started
03-07 07:31:24.496: D/test(1431): page finished
Ok,
When network is not available I ran this code, webviewclient's onReceivedError get called,
If network available and page loading started, and network disconnect, then also onReceivedError get called.
But there is a some instance of time,(count 1,2,3 after pressing button and disconnect network with f8 on emulator) mWebView.loadUrl(url) gets called, webViewclient's methods gets called like below
and WebView displays blank white screen, onReceivedError not called.
here is logcat
and
What is wrong with this code.
Why onReceivedError not called. If it does not get called, how to handle this situation
How to know webView has not loaded anyting and finish activity
it will certainly call page started and page finished because onReceivedError will be called on:-
-click of any link (if internet not present) then should override url will throw an error which it will handle
-on activity started or when webview is called
for all the exceptions which are not handled by onRecievedError you have to check http status

Trying to display url in Web View

I am experimenting with the loopj package. I am trying to make a HTTP request to a website and display the website in the webview.
I am successfully getting a result back, however the web view does not display the page as desired, instead chrome opens up and displays the page.
Am I missing something or is there a way I can override this unwanted behaviour?
Below is my oncreate method where I am making the request:
public class MainActivity extends Activity {
Button connectBtn;
TextView status;
WebView display;
String url = "http://www.google.com";
AsyncHttpClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
status = (TextView)findViewById(R.id.statusbox);
connectBtn = (Button)findViewById(R.id.connectBtn);
display = (WebView)findViewById(R.id.webView1);
connectBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
client = new AsyncHttpClient();
client.get(url, new AsyncHttpResponseHandler(){
#Override
public void onSuccess(String response) {
Toast.makeText(getApplicationContext(), "Success!", Toast.LENGTH_SHORT).show();
display.loadUrl(url);
}
});
}
});
}
setWebViewClient to your WebView and override shouldOverrideUrlLoading() now write view.loadUrl(url); in that method.
Just add this code,
display.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}});
You need to set a WebViewClient and override the shouldOverrideUrlLoading method. Something like this:
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(final WebView view, final String url) {
view.loadUrl(url);
}
});
That makes sure that clicks on links in the WebView are handled by the WebView itself.
Edit: Actually, I misread the question. You aren't dealing with a click in the WebView itself, so this isn't relevant. Sorry!
just use this code under you webviewclient
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
final EditText editText = (EditText) findViewById(R.id.urlfield);
editText.setText(url);
}
}

progress dialog could not stop

I am new to android.I am using progress dialog in my app but it could not stop.In my app i am using webview.In first activity I have connect button.In second activity connect to facebook code is available.In second activity code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.facebook);
wvFacebook.setWebViewClient(new MyWebViewClient());
wvFacebook.loadUrl(strFacebook);
}
private class MyWebViewClient extends WebViewClient
{
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
view.getSettings().setJavaScriptEnabled(true);
view.loadUrl(url);
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
prDialog = ProgressDialog.show(getParent(), "In progress", "Loading, please wait...");
}
#Override
public void onPageFinished(WebView view, String url) {
Log.e("status","calling....");
super.onPageFinished(view, url);
prDialog.dismiss();
Log.e("status","calling next......");
}
}
when connect button clicked the second activity will be executed and getting facebook page.But progress dialog could not stop.
Try like this
First create dialog in your onCreate()
ProgressDialog progressDialog =new ProgressDialog(getApplicationContext());
progressDialog.setMessage("Please Wait");
Then show the dialog in onPageStarted() method.
progressDialog .show();
Then dismiss it in your onPageFinished() method
progressDialog.cancel();
You should not create Dialog in onPageStart, when loading a web page, onPageStart() could be called multi times.
In you onPageStart, you create a new Dialog without closing the old one, so the old dialog will always show.
To solve this you have many choices:
As lmran said, create the dialog only once in onCreate(). Show it in onPageStarted and dismiss in onPageFinished.
Before create a new Dialog, dismiss the old one.
just this code used and try it out,
#Override
public void onPageFinished(WebView view, String url) {
Log.e("status","calling....");
super.onPageFinished(view, url);
if (prDialog != null || prDialog.isShowing())
prDialog.dismiss();
Log.e("status","calling next......");
}
#Override
public void onPageFinished(WebView view, String url) {
try{
if (prDialog.isShowing()|| prDialog!= null) {
prDialog.dismiss();
prDialog= null; /*** Add ***/
}
}catch(Exception exception){
exception.printStackTrace();
}
}
}
You may also visit the following link to get a complete detail...
http://androiddubd.blogspot.com/2014/07/how-to-show-progress-dialog-or-loader.html

Website wrapped in App - Loading

I'm working on an Android App that simply wraps a mobile version of a website inside of a native App container.
At present I call (example):
wv.loadUrl("http://www.websitehere.com/");
I have exported the entire project and tested it on my phone and when loading a new page inside of the App it takes a few moments, however not being on a browser there is no loading indicator, so it is a still screen on the current page for a few moments (depending on internet speed) while the new page loads.
What would be the best way to implement a loading indicator so that the user knows that a new page is infact loading?
EDIT: Loading added, but only for the initial pageload of app.
public class Main extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ProgressDialog pd = ProgressDialog.show(this, "Page is", "Loading...",true);
WebView wv = (WebView)findViewById(R.id.my_webview);
wv.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
if(pd.isShowing()&&pd!=null);
{
pd.dismiss();
}
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
pd = ProgressDialog.show(this, "Page is", "Loading...", true);
view.loadUrl(url);
return true;
}
});
wv.loadUrl("http://www.websitehere.com");
}
}
If your website is html based and not server side (asp/php etc) you could package the website in the app so no internet is required. Downside to this is updating 2 websites.
Alternatively you could add a loading script (javascript) to the website itself.
You could start a ProgressDialog before you load the website and dismiss it after the loading is done.
Code should look something like this:
ProgressDialog progressDialog = ProgressDialog.show(this, "", "Loading...");
wv.loadUrl("http://www.yourwebsite.com");
progressDialog.dismiss();
EDIT: new code for every new url clicked
You should add this to your WebViewClient and also make you (ProgressDialog) pd a member variable.
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
pd = ProgressDialog.show(this, "Page is:", "Loading...",true);
view.loadUrl(url);
return true;
}
EDIT:
You should make the ProgressDialog pd a member variable.
public class Main extends Activity {
private ProgressDialog pd;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pd = ProgressDialog.show(this, "Page is", "Loading...",true);
WebView wv = (WebView)findViewById(R.id.my_webview);
wv.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
if(pd.isShowing()&&pd!=null);
{
pd.dismiss();
}
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
pd = ProgressDialog.show(Main.this, "Page is", "Loading...", true);
}
});
wv.loadUrl("http://www.websitehere.com");
}
}
EDIT: using onPageStarted.

Categories

Resources