Android Webview иногда не может отображать PDF-файл и вместо этого показывает пустую / белую страницу

#java #c# #android #xamarin.android #android-webview

#java #c# #Android #xamarin.android #android-webview

Вопрос:

  • Откройте PDF-файл в Webview с помощью документов Google
  • Открывайте один и тот же PDF-файл или другой PDF-файл снова и снова.
  • Иногда он будет отображать пустую / белую страницу в Android, пока мы снова не обновим веб-страницу 1 или 2 раза.

Я сделал образец в PDF. Ссылка на проект показана ниже:

https://github.com/gopalawasthi123/PdfWebView

Надеюсь, это поможет вам лучше.

 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. Привет, спасибо, что поделились примером, вы решили эту проблему? Я нашел решение для меня. При необходимости я обновлю ответ 🙂

2. Спасибо, пожалуйста, обновите его. или вы также можете поделиться кодом, если хотите

3. Хорошо, я поделюсь решением 🙂

4. вы получили решение?

5. @HariShankarS Я отметил правильный ответ, вы можете попробовать ответ Микеланджело Пуччи в приведенных ниже ответах, которые будут работать для вас

Ответ №1:

Вы можете перезагрузить страницу, пока она не отобразит PDF таким образом:

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

Комментарии:

1. здесь вместо получения заголовка вы сравниваете свое условие, используя условие if (view.getContentHeight() == 0), которое предоставит вам точные данные о том, загружена ваша страница или нет.

Ответ №2:

После тестирования второго файла URL-адреса PDF WebView, похоже, не может загрузить большой файл PDF.

Причина:

WebView отображает HTML. Тот факт, что это вообще работает, является взломом — Google преобразует простые PDF-файлы в HTML. Не похоже, что они поддерживают что-то настолько большое. Даже если бы они это сделали, я бы ожидал, что загрузка большой страницы PDF, преобразованной в HTML, будет настолько большой, что я очень сомневаюсь, что вы сможете загрузить ее, не переходя на ООМ. Используйте соответствующую библиотеку PDF, создайте реальный вид рендеринга PDF и убедитесь, что за один раз не отображается больше PDF-файла, чем вам нужно (иначе вы все равно перейдете на ООМ). Другими словами, не полагайтесь на хакерские решения, на которые вам никогда не следовало полагаться в первую очередь.

Решение:

Вам следует попробовать такие альтернативы, какPDF.js запускается локально на вашем устройстве вместо службы, подобной Google Docs preview.(Или сначала загрузите PDF по локальному пути к файлу)

Поместите его в папку с активами и настройте пример:

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

Кроме того, у вас могут возникнуть ситуации с нехваткой памяти. Альтернативой является встроенный просмотрщик, такой как AndroidPdfViewer.

Комментарии:

1. я попробовал оба ваших решения. но эти решения не сработали для меня, если вы откроете этот PDF-файл 9-10 раз, страница вместо этого станет пустой / белой. Также не могли бы вы изменить URL на adobe.com/content/dam/acom/en/devnet/acrobat/pdfs / …

2. @GopalAwasthi Привет, после тестирования нового URL-адреса я обнаружил, что проблема также существует. Предыдущее решение может не полностью решить эту проблему. Это связано с другой причиной. Я обновил ответ.

Ответ №3:

Мы можем решить проблему двумя способами. 1. Одним из них является использование плагина Js.Pdf на стороне сервера. Это, безусловно, решает проблему, но если у нас есть несколько PDF-файлов во фрагменте, это может привести к нехватке памяти, и приложение может выйти из строя. 2. Второй вариант — мы можем рекурсивно вызвать функцию для загрузки webview. Это также вызовет проблему, но с меньшей частотой Ниже приведен код:

 private void showPdf(final String imageString) {
pdfView.invalidate();
pdfView.getSettings().setJavaScriptEnabled(true);
pdfView.getSettings().setSupportZoom(true);
pdfView.loadUrl("http://docs.google.com/gview?embedded=trueamp;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:

У меня была точно такая же проблема, и я обнаружил, что всегда был шанс, что WebView не загрузится при первой попытке загрузки, особенно если PDF был на большей стороне. Приведенный ниже код работает в 100% случаев. Насколько я понимаю для начинающих, он безопасно использует отдельный поток для просмотра и проверки состояния загрузки WebView, повторяя попытку загрузки представления до успешного завершения. Поскольку этот вопрос был опубликован год назад, я обобщил свое решение, чтобы наилучшим образом использовать новых зрителей.

 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=trueamp;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);

        }
    }
}
  

Ответ №5:

Есть несколько способов, с помощью которых мы можем определить, правильно ли загружена страница / URL или нет, из onPageFinished() метода Webview и на основе этого reload() URL.

Вариант 1: проверить с contentHeight помощью webview.

 override fun onPageFinished(view: WebView?, url: String?) {
    if(view?.contentHeight == 0){
        view?.reload()
        return
    }
    super.onPageFinished(view, url)
}
    
  

Вариант 2: проверить с title помощью webview.

 override fun onPageFinished(view: WebView?, url: String?) {
    if(view?.title.isNullOrEmpty()){
        view?.reload()
        return
    }
    super.onPageFinished(view, url)
}
  

Ответ №6:

Протестировано на нескольких устройствах и работает в API 29

в Kotlin

  val webSettings: WebSettings = webview.settings
    webSettings.javaScriptEnabled = true
    webSettings.useWideViewPort = true
    webSettings.loadWithOverviewMode = true
    webSettings.domStorageEnabled = true

    webview.webViewClient = AppWebViewClients()
// val TERM_CONDITION_URL = "http://docs.google.com/gview?embedded=trueamp;url="
//            "YOUR_DOC_URL_HERE"

   bindind?.webview?.loadUrl(TERM_CONDITION_URL) 
  

и здесь AppWebViewClients класс

     class AppWebViewClients : WebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView, url: String?): Boolean {
        view.loadUrl(url)
        return true
    }

    override fun onPageFinished(view: WebView?, url: String?) {
        if (view?.contentHeight == 0)
            view?.reload();
        else {
            super.onPageFinished(view, url)
        }
    }
}
  

Ответ №7:

Я думаю, вы должны сделать, как показано ниже:

 public void onPageFinished(WebView view, String url) {

    if (!view.getUrl().equals(url)) {
       view.loadUrl(url);
       return;
    }
}