Android WebView打印保存PDF总是生成0字节无效文件问题求助
问题原因分析
核心原因是WebView实例被过早释放:
打印(含保存为PDF)是系统PrintManager执行的异步操作,你在onPageFinished回调中调用createWebPrintJob后立刻将成员变量mWebView置为null,此时WebView没有强引用持有,会被垃圾回收机制回收。但PrintManager生成PDF时仍然需要依赖WebView的渲染内容作为数据源,WebView被回收后无法读取内容,最终生成0字节的无效PDF。
你代码注释里写的「Keep a reference to WebView object until you pass the PrintDocumentAdapter to the PrintManager」是错误的,引用需要保持到整个打印任务完全结束,而不是仅到传入PrintDocumentAdapter为止。
解决方案
需要监听打印任务的状态,直到任务执行完成、取消或失败后,再释放WebView实例。
修改步骤
- 新增成员变量持有PrintJob实例,避免打印任务被系统回收
- 为PrintJob设置状态监听器,任务结束后再释放WebView引用
- 移除
onPageFinished中立刻清空mWebView的逻辑
完整修改后代码
public class PrintLauncherFragmentActivity extends AppCompatActivity { private WebView mWebView; // 新增PrintJob成员变量持有引用 private PrintJob mPrintJob; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Create a WebView object specifically for printing WebView webView = new WebView(this); webView.setWebViewClient(new WebViewClient() { public boolean shouldOverrideUrlLoading(WebView view, String url) { return false; } @Override public void onPageFinished(WebView view, String url) { createWebPrintJob(view); // 移除这里立刻置空mWebView的逻辑 } }); String htmlDocument = "<html><body><h1>Test Content</h1><p>Testing, " + "testing, testing...</p></body></html>"; webView.loadDataWithBaseURL(null, htmlDocument, "text/HTML", "UTF-8", null); // Keep a reference to WebView object until print job finished mWebView = webView; } private void createWebPrintJob(WebView webView) { // Get a PrintManager instance PrintManager printManager = (PrintManager) this .getSystemService(Context.PRINT_SERVICE); String jobName = "demo"; // Get a print adapter instance PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(jobName); // Create a print job with name and adapter instance mPrintJob = printManager.print(jobName, printAdapter, new PrintAttributes.Builder().build()); // 监听打印任务状态 mPrintJob.addPrintJobStateChangeListener(new PrintJobStateChangeListener() { @Override public void onPrintJobStateChanged(int state) { // 任务完成、失败、取消时,释放资源 if (mPrintJob.isCompleted() || mPrintJob.isFailed() || mPrintJob.isCancelled()) { mWebView = null; mPrintJob = null; } } }, null); } @Override protected void onDestroy() { super.onDestroy(); // Activity销毁时如果任务还在运行,先取消任务再释放资源 if (mPrintJob != null && !mPrintJob.isCompleted() && !mPrintJob.isFailed() && !mPrintJob.isCancelled()) { mPrintJob.cancel(); } mWebView = null; mPrintJob = null; } }
额外验证点
如果修改后依然存在问题,可以排查以下项:
- 确认HTML内容加载完整,没有异步资源未加载完成就触发了
onPageFinished(如果有JS、图片等异步资源,需要等待所有资源加载完成再调用打印逻辑) - 如果你自定义过WebView的渲染相关配置,确认没有关闭离屏渲染等打印依赖的能力
内容的提问来源于stack exchange,提问作者Cheok Yan Cheng
相关产品推荐
相关产品推荐

