Reputation: 327
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>
Upvotes: 12
Views: 8983
Reputation: 6444
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();
}
});
}
Upvotes: 0
Reputation: 71
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);
}
}
Upvotes: 1
Reputation: 2019
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);
}
Upvotes: 1
Reputation: 3231
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.
Upvotes: 7
Reputation: 1948
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
Upvotes: 0