You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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实例。

修改步骤

  1. 新增成员变量持有PrintJob实例,避免打印任务被系统回收
  2. 为PrintJob设置状态监听器,任务结束后再释放WebView引用
  3. 移除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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 06:24:07