Android WebView加载含图PDF偶现空白,API>23设备频发
Hey there! Let's work through this frustrating blank screen issue you're seeing when loading image-heavy PDFs via Google Docs Viewer in your WebView—especially on devices running API 23+. I know the two settings that fixed it are off-limits for Google Play, so let's explore safe, compliant alternatives.
Why Those Forbidden Settings Worked (And Why You Can't Use Them)
First, quick context: setAllowFileAccessFromFileURLs(true) and setAllowUniversalAccessFromFileURLs(true) relax cross-origin access restrictions, which likely resolved loading issues with the embedded PDF's assets (images/charts). But Google Play blocks these because they introduce significant security risks—so we need safer workarounds.
Recommended Fixes to Try
Let's tweak your existing code with secure, Play-compliant settings and enhancements:
1. Enhance WebSettings for Better Asset Loading
Add these settings to your WebView configuration to improve resource handling without compromising security:
// Enable DOM storage (critical for complex web apps like Google Docs Viewer) webView.getSettings().setDomStorageEnabled(true); // Set a reasonable cache size and enable app cache webView.getSettings().setAppCacheEnabled(true); webView.getSettings().setAppCacheMaxSize(10 * 1024 * 1024); // 10MB // Enable media playback settings if needed (for any embedded media in PDFs) webView.getSettings().setMediaPlaybackRequiresUserGesture(false); // Ensure JavaScript can open windows if required webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
2. Improve WebViewClient with Error Handling & Retry Logic
Modify your MyWebViewClient to detect loading failures and retry the load—this helps with intermittent network or resource loading issues:
private class MyWebViewClient extends WebViewClient { private int retryCount = 0; private static final int MAX_RETRIES = 2; @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); // Reset retry count when a new page starts retryCount = 0; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // Remove toolbar as before webView.loadUrl("javascript:(function() { document.querySelector('[role=\"toolbar\"]').remove();})()"); } @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { super.onReceivedError(view, request, error); // Retry loading if we haven't exceeded max retries if (retryCount < MAX_RETRIES) { retryCount++; view.reload(); } } @Override public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) { super.onReceivedHttpError(view, request, errorResponse); // Handle HTTP errors (e.g., 404, 500) with retry logic if (retryCount < MAX_RETRIES) { retryCount++; view.reload(); } } }
3. Adjust PDF Loading URL
Try using the HTTPS version of Google Docs Viewer instead of HTTP—mixed content can sometimes cause loading issues even with MIXED_CONTENT_ALWAYS_ALLOW:
webView.loadUrl("https://docs.google.com/gview?embedded=true&url=MYURL");
Make sure your MYURL is also HTTPS if possible—this avoids mixed content warnings entirely.
4. Test with Hardware Acceleration
Sometimes hardware acceleration can cause rendering issues with complex content. Try disabling it for the WebView (or the whole Fragment) temporarily to see if it helps:
<!-- In your Fragment's layout XML --> <WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent" android:hardwareAccelerated="false" />
Or programmatically:
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
Final Notes
- Always test on multiple API 23+ devices (especially older ones) since rendering behavior can vary.
- If the issue persists, consider using a dedicated PDF rendering library (like PdfRenderer or third-party libraries) instead of Google Docs Viewer—this gives you more control over loading and rendering, though it requires more code.
内容的提问来源于stack exchange,提问作者Yamuna

