-->

Android Webview cannot render the pdf sometimes an

2020-08-15 07:30发布

问题:

  • Open the pdf in the webview using google docs
  • Open the same pdf or different pdf again and again.
  • Sometimes it will show the blank/white page in the android untill we refresh the webpage again for 1 or 2 times.

I have made the sample on the pdf. The link for the project is shown below:

https://github.com/gopalawasthi123/PdfWebView

Hope this will help you Better.

public void SetWebView(WebView webview,string externalUrl){
            webview.Tag = "webview";
            webview.Settings.JavaScriptEnabled = true;
            webview.Settings.SupportZoom ();
            webview.Settings.SetAppCacheEnabled(true);
            webview.Settings.DomStorageEnabled = true;
            webview.ZoomOut ();
            webview.ZoomIn ();
            webview.Settings.BuiltInZoomControls = true;
            webview.Settings.LoadWithOverviewMode = true;
            webview.Settings.UseWideViewPort = true;
            //webview.Settings.SetSupportZoom (true);
            webview.Settings.SetPluginState (WebSettings.PluginState.On);
            webview.Settings.GetPluginState ();
            if (externalUrl.StartsWith("http://") || externalUrl.StartsWith("https://"))
                webview.LoadUrl (externalUrl);
            webview.SetWebViewClient (new MonkeyWebViewClient (imgViewBack, imgViewForward, imgRefresh));
            webview.SetWebChromeClient (new WebChromeClient ());
        }

回答1:

You can reload the page until it displays the pdf in this way:

public void onPageFinished(WebView view, String url) {
if (view.getTitle().equals(""))
    view.reload();
}


回答2:

After testing second PDF URL file, WebView seems like that can not load large PDF file.

Reason:

WebView display HTML. The fact that this works at all is by a hack- google will convert simple PDFs into HTML. It doesn't seem like they support anything that big. Even if they did, I would expect loading a large page PDF converted to HTML would be so large I highly doubt you'd be able to load it without going OOM. Use an appropriate PDF library, make a real PDF rendering view, and make sure not to render more of the PDF at a time than you need (or else you'll go OOM anyway). In other words, don't rely on hacky solutions you never should have relied on in the first place.

Solution:

You should try alternatives like PDF.js running locally in your device, instead of a service like Google Docs preview.(Or download PDF first to local file path)

Put it in your assets folder and tweak the example:

wv.loadUrl("file:///android_asset/web/viewer.html");

Also, you can have Out Of Memory situations. An alternative to try is a native viewer like AndroidPdfViewer.



回答3:

We can solve the Problem in the two ways. 1. One is to use the Js.Pdf Plugin on the server end. It surely solve the problem but if we have multiple pdf's in the Fragment then it may cause the out of memory situations and app can crash. 2. Second option is we can recursively called the function to load webview. This will also cause the issue but with less frequency Below is the code:

private void showPdf(final String imageString) {
pdfView.invalidate();
pdfView.getSettings().setJavaScriptEnabled(true);
pdfView.getSettings().setSupportZoom(true);
pdfView.loadUrl("http://docs.google.com/gview?embedded=true&url=" + imageString);
pdfView.setWebViewClient(new WebViewClient() {
    boolean checkhasOnPageStarted = false;

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        checkhasOnPageStarted = true;
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        if (checkhasOnPageStarted ) {
            pdfView.loadUrl(removePdfTopIcon);
        } else {
            showPdf(imageString);
        }
    }
});
}


回答4:

I was having the exact same issue and found that there was always a chance the WebView would not load on the first load attempt, especially if the pdf was on the larger side. The code I put together below works 100% of the time. From my beginner's understanding, it safely utilizes a separate thread to loop through and test the load status of the WebView, re-attempting a load of the view until successful. As this question was posted a year ago, I have generalized my solution to best benefit new viewers.

public class WebViewActivity extends AppCompatActivity {

String PDFView;
WebView webView;
String PDFBrowserView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Get the intended "PDFView"
    PDFView = getIntent().getExtras().get("PDFView").toString();
    //Have to manually encode (?) the url to display it
    try {
        PDFView = URLEncoder.encode(PDFView, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    //Full display url
    PDFBrowserView = "https://docs.google.com/gview?embedded=true&url=" + PDFView;

    //Initialize a new "WebView" instance
    webView = new WebView(WebViewActivity.this);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setAllowFileAccessFromFileURLs(true);
    webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
    webView.getSettings().setBuiltInZoomControls(true);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setPluginState(WebSettings.PluginState.ON);
    webView.getSettings().setDomStorageEnabled(true);
    webView.getSettings().setLoadWithOverviewMode(true);
    webView.getSettings().setUseWideViewPort(true);
    //This handles callbacks (?)
    webView.setWebChromeClient(new WebChromeClient());

    //Call this to load page if page is blank with pdf url until page is not blank
    checkPageFinished();
}

public void checkPageFinished() {
    //If view is blank:
    if (webView.getContentHeight() == 0) {

        //Run off main thread to control delay
        webView.postDelayed(new Runnable() {
            @Override
            public void run() {
                //Load url into the "WebView"
                webView.loadUrl(PDFBrowserView);
            }
            //Set 1s delay to give the view a longer chance to load before 
            // setting the view (or more likely to display blank)
        }, 1000);
        //Set the view with the selected pdf
        setContentView(webView);

        webView.postDelayed(new Runnable() {
            @Override
            public void run() {
                //If view is still blank:
                if (webView.getContentHeight() == 0) {
                    //Loop until it works
                    checkPageFinished();
                }
            }
            //Safely loop this function after 1.5s delay if page is not loaded
        }, 1500);

        }
    }
}