简体   繁体   English

保存到外部存储时,Android PdfDocument已损坏

[英]Android PdfDocument damaged when saved to external storage

I'm trying to create a simple PDF document using Androids native PdfDocument class (from api 19). 我正在尝试使用Androids原生PdfDocument类(来自api 19)创建一个简单的PDF文档。 What i want is to have an XML layout file, for example called pdf_doc.xml , and then inflate it when creating the PDF. 我想要的是拥有一个XML布局文件,例如名为pdf_doc.xml ,然后在创建PDF时对其进行充气。 Inside the pdf_doc.xml i would then have a bunch of views that could be fetched in the code, and then drawn onto the PdfDocuments pages, seperately. pdf_doc.xml中,我会有一堆可以在代码中获取的视图,然后单独绘制到PdfDocuments页面上。 The problem is, that this creates a damaged PDF file. 问题是,这会创建一个损坏的PDF文件。

On the other hand, if i just create a simple TextView, in my main_activity.xml (the xml of the activity i'm using when creating the PDF) and use that TextView instead, it works fine. 另一方面,如果我只是创建一个简单的TextView,在我的main_activity.xml (创建PDF时我正在使用的活动的xml)中使用TextView,它可以正常工作。

Why does it make a difference whether the TextView comes from an inflated layout or the activity's layout? 为什么TextView来自膨胀的布局还是活动的布局会有所不同? Am i trying to do this the wrong way? 我试图以错误的方式做到这一点吗?

FYI: It also fails when creating the TextView programmatically. 仅供参考:以编程方式创建TextView时也会失败。

Below is my source code. 以下是我的源代码。 These two functions are called right after eachother. 这两个函数在彼此之后立即调用。 The first one creates the PDF, the other one saves it. 第一个创建PDF,另一个保存。 The problem is in the view, called content , that im getting from the inflated layout. 问题在于视图,称为内容 ,即从膨胀的布局中获取。 If i instead put that TextView in the Activity's XML and then get it from the activity, like this act.findViewById(R.id.pdf_text); 如果我把TextView放在Activity的XML中然后从活动中获取它,就像这个act.findViewById(R.id.pdf_text); it then workst as intended. 然后按预期工作。

Code: 码:

    public static PdfDocument createPdf(Activity act){
        PrintAttributes printAttrs = new PrintAttributes.Builder().
                setColorMode(PrintAttributes.COLOR_MODE_COLOR).
                setMediaSize(PrintAttributes.MediaSize.ISO_A4).
                setMinMargins(PrintAttributes.Margins.NO_MARGINS).
                build();

        ViewGroup mainLayout = (ViewGroup) View.inflate(act, R.layout.pdf_doc, null);

        int pageHeight = printAttrs.getMediaSize().getHeightMils() / 1000 * 72;
        int pageWidth = printAttrs.getMediaSize().getWidthMils() / 1000 * 72;

        PdfDocument document = new PrintedPdfDocument(act, printAttrs);
        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(pageWidth, pageHeight, 1).create();
        PdfDocument.Page page = document.startPage(pageInfo);

        View content = mainLayout.findViewById(R.id.pdf_text);
        content.draw(page.getCanvas());
        document.finishPage(page);

        return document;
    }

    public static void saveFile(PdfDocument doc){
        String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();
        File myDir = new File(root + "/pdf_test");
        myDir.mkdirs();

        File file = new File(myDir, "test.pdf");

        if (file.exists()) {
            file.delete();
        }

        try {
            FileOutputStream out = new FileOutputStream(file);
            doc.writeTo(out);
            doc.close();
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        String path = file.getAbsolutePath();
        Log.d("pdftest", "path: " + path);
    }

Two suggestions: 两个建议:

  1. Since your mainLayout will have zero height and zero width (you haven't inflated it into a parent), try manually laying it out, by calling measure() and layout() on it, in that order. 由于你的mainLayout将具有零高度和零宽度(你没有将它膨胀为父级),尝试通过按顺序调用它上面的measure()layout()来手动将其放置。 You will need to specify a size in pixels that you want the layout to be sized to. 您需要指定希望布局大小的像素大小。

  2. Call out.getFd().sync() after out.flush() and before out.close() . out.flush()out.close()之前调用out.getFd().sync() out.close() I doubt that this is causing your specific problem here, but it's a good idea and is unlikely to hurt. 我怀疑这是在这里造成你的具体问题,但这是一个好主意,不太可能受到伤害。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM