Android generates pdf files

Android generates pdf files

1. Use the official method

Using the official way is the use of the PdfDocument class

1.1 Basic use

/*** 
     * Write tv content to pdf file 
     */ 
    @RequiresApi(api = Build.VERSION_CODES.KITKAT) 
    private void newPdf() { 
        // Create a PDF text object 
        PdfDocument document = new PdfDocument(); 
        // Create The information of the current page, the parameters in the Builder represent the width and height of the page, and the number of pages 
​PdfDocument.PageInfo
        pageInfo = 
                new PdfDocument.PageInfo.Builder(binding.pdfTv.getWidth(), binding.pdfTv.getHeight(), 1) 
                        .create(); 
        // Generate the current page 
        PdfDocument.Page page = document.startPage(pageInfo); 
​//
        Draw on the current page, that is, draw the required view on the canvas of the page 
        View content = pdfTv ; 
        content.draw(page.getCanvas()) 
;
        // End the current page 
        document.finishPage(page); 
        String filePath = getExternalFilesDir("").getAbsolutePath() + "/test.pdf"; 
        try { 
            FileOutputStream outputStream = new FileOutputStream(new File(filePath)); 
            //write Into the file 
            document.writeTo(outputStream); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
        //Close 
        document.close(); 
    }

Precautions

1. Need to apply for permission to write files

2. The minimum API is 19, and there are restrictions on the api version

1.2 Generate a pdf file from the content of the root layout

    /*** 
     * Save the content of a screen (including text, pictures, buttons, etc. in the interface) 
     */ 
    @RequiresApi(api = Build.VERSION_CODES.KITKAT) 
    private void pdfTvAndIv() { 
        // Create a PDF text object 
        PdfDocument document = new PdfDocument(); 
        //Create the information of the current page, the parameters in the Builder indicate the width and height of the page, and the page 
PdfDocument.PageInfo
        pageInfo = 
                new PdfDocument.PageInfo.Builder(binding.getRoot().getWidth() , binding.getRoot().getHeight(), 1) 
                        .create(); 
        // Generate the current page 
        PdfDocument.Page page = document.startPage(pageInfo); 
​//
        Draw on the current page, that is, put the required The view of the view is drawn on the canvas of the page 
        View content = binding.getRoot(); 
        content.draw(page.getCanvas()) 
;
        // 结束当前页
        document.finishPage(page);
        String filePath = getExternalFilesDir("").getAbsolutePath() + "/tviv.pdf";
        try {
            FileOutputStream outputStream = new FileOutputStream(new File(filePath));
            document.writeTo(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
​
        document.close();
    }

It's just as easy. binding.getRoot() is the root layout of the xml file

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
​
    <data>
​
    </data>
​
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".pdf.PdfActivity">
​
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
​
            <TextView
                android:id="@+id/pdf_tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="" />
            <ImageView
                android:id="@+id/pdf_iv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:scaleType="fitXY"
                android:src="@mipmap/logo"
                android:visibility="visible" />
            <Button
                android:id="@+id/pdf1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" 
        </LinearLayout>
                android:text="The official way to generate pdf" />
​
    </ScrollView>
</layout>

1.3 TextView has many lines, more than one screen

/*** 
 * Write multiple lines of text to a pdf file 
 */ 
@RequiresApi(api = Build.VERSION_CODES.KITKAT) 
private void pdfInterviewContent() { 
    TextView tv_content = binding.pdfTv; 
    // Create a PDF text object 
    PdfDocument document = new PdfDocument(); 
    // The height of one page of pdf 
    int onePageHeight = tv_content.getLineHeight() * 30; 
    // How many lines are there in the TextView 
    int lineCount = tv_content.getLineCount(); 
    // Calculate how many pages the TextView needs to be divided into 
    int pdfCount = lineCount % 30 == 0 ? lineCount / 30 : lineCount / 30 + 1; 
    for (int i = 0; i < pdfCount; i++) { 
        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(tv_content.getWidth( ), onePageHeight + 120, 1) 
                .setContentRect(new Rect(0, 60, tv_content.getWidth(), onePageHeight + 60)) 
                .create();
        PdfDocument.Page page = document.startPage(pageInfo);
        Canvas canvas = page.getCanvas();
        canvas.translate(0, -onePageHeight * i);
        tv_content.draw(canvas);
        document.finishPage(page);
    }
    //document = pdfImageviewContent(document);
    File file = new File(getExternalFilesDir("").getAbsolutePath() + "/test.pdf");
    try {
        FileOutputStream outputStream = new FileOutputStream(file);
        document.writeTo(outputStream);
    } catch (IOException e) {
        e.printStackTrace();
    }
    document.close();
}

1.4 Summary

1. The saved file is a bit large 
2. It is difficult to save the content of more than one screen, which involves the movement of canvas 
3. It is difficult to save text and pictures at the same time (if it exceeds one screen, the picture will be blank after saving. No more than One screen, it can be displayed normally after saving) 
4. If there is a special view in the interface, the save may fail! For example, SurfaceView. 
[A link to the solution is attached](https://www.jianshu.com/p/1ebaf5e6fac1)

2. Ways to use itext

For Itext, there are mainly two versions, one is 5.x and the other is 7.x. These two versions are completely incompatible. For the difference, please refer to the official website: iText 7 and iText 5: roadmaps, differences, updates |iTextPDF ,

Documentation for 5.x: iText Javadoc Home

Documentation for 7.x: iText Javadoc Home

2.1 7.x

/**
 * 创建PDF文件
 */
private void createPDF(String path) {
    if (XXPermissions.isGranted(TextActivity.this, Permission.MANAGE_EXTERNAL_STORAGE)) {
        File file = new File(path);
        if (file.exists()) {
            file.delete();
        }
        file.getParentFile().mkdirs();
​
        // 创建Document
        PdfWriter writer = null;
        try {
            writer = new PdfWriter(new FileOutputStream(path));
        } catch (FileNotFoundException e) {
            Log.e("FileNotFoundException", e.toString());
        }
​
        PdfDocument pdf_document = new PdfDocument(writer);
        // Generated PDF document information 
        PdfDocumentInfo info = pdf_document.getDocumentInfo(); 
        // Title 
        info.setTitle("First pdf file"); 
        // Author 
        info.setAuthor("Quinto"); 
        // Subject 
        info.setSubject(" test"); 
        // keywords 
        info.setKeywords("pdf"); 
        // creation date 
        info.setCreator("2022-10-20"); 
​Document
        document = new Document(pdf_document, PageSize.A4, false); 
​//
        Text font (display Chinese), size, color 
        PdfFont font = null; 
        try { 
            font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
        } catch (IOException e) { 
            Log.e("IOException", e.toString()); 
        } 
        float title_size = 36.0f; 
        float text_title_size = 30.0f; 
        float text_size = 24.0f; 
        Color title_color = new DeviceRgb(0, 0 , 0); 
        Color text_title_color = new DeviceRgb(65, 136, 160); 
        Color text_color = new DeviceRgb(43, 43, 43); 
​//
        Line separator 
        // Solid line: SolidLine() Dotted line: DottedLine() Dashboard line: DashedLine() 
        LineSeparator separator = new LineSeparator(new SolidLine()); 
        separator.setStrokeColor(new DeviceRgb(0, 0, 68)); 
​//
        Add a large title
        Text title = new Text("This is the title of the pdf file").setFont(font).setFontSize(title_size).setFontColor(title_color); Paragraph 
        paragraph_title = new Paragraph(title).setTextAlignment(TextAlignment.CENTER); 
        document.add( paragraph_title); 
​for
        (int i = 1; i < 10; i++) { 
            // Add text subtitle 
            Text text_title = new Text("th" + i + "line:").setFont(font).setFontSize(text_title_size ).setFontColor(text_title_color); 
            Paragraph paragraph_text_title = new Paragraph(text_title); 
            document.add(paragraph_text_title); 
​//
            Add text content 
            String content = "I am text content" + i + i + i + i + i + i + i + i + i + i;
            Text text = new Text(content).setFont(font).setFontSize(text_size).setFontColor(text_color); 
            Paragraph paragraph_text = new Paragraph(text); 
            document.add(paragraph_text); 
​//
            Add a newline space 
            document.add (new Paragraph("")); 
            // Add a horizontal line 
            document.add(separator); 
            // Add a breakable space 
            document.add(new Paragraph("")); 
        } 
​/
        ** 
         * Add a list 
         */ 
        List list = new List().setSymbolIndent(12).setListSymbol("\u2022").setFont(font); 
        list.add(new ListItem("List1")) 
                .add(new ListItem("List 2"))
                .add(new ListItem("列表3"));
        document.add(list);
​
        /**
         * 添加图片
         */
        Text text_image = new Text("图片:").setFont(font).setFontSize(text_title_size).setFontColor(text_title_color);
        Paragraph image = new Paragraph(text_image);
        document.add(image);
        Image image1 = null;
        Image image2 = null;
        Image image3 = null;
        try {
            /*image1 = new Image(ImageDataFactory.create("/storage/emulated/0/DCIM/Camera/IMG_20221003_181926.jpg")).setWidth(PageSize.A4.getWidth() * 2 / 3);
            image2 = new Image(ImageDataFactory.create("/storage/emulated/0/Download/互传/folder/证件/XHS_159716343059020494b83-da6a-39d7-ae3b-13fd92cfbb53.jpg")).setWidth(PageSize.A4.getWidth() / 3);
            image3 = new Image(ImageDataFactory.create("/storage/emulated/0/Download/互传/folder/证件/XHS_1597163520524f0b4df77-8db1-35c6-9dfa-3e0aa74f1fef.jpg")).setWidth(PageSize.A4.getWidth() / 3);*/
​
            image1 = new Image(ImageDataFactory.create("/storage/emulated/0/Pictures/JPEG_20230609_154240_8941441911022988116.jpg")).setWidth(PageSize.A4.getWidth() * 2 / 3);
            image2 = new Image(ImageDataFactory.create("/storage/emulated/0/Tencent/QQ_Images/-318f738d395e5630.jpg")).setWidth(PageSize.A4.getWidth() / 3);
            image3 = new Image(ImageDataFactory.create("/storage/emulated/0/Pictures/Screenshots/Screenshot_20230615_145522_com.hermes.wl.jpg")).setWidth(PageSize.A4.getWidth() / 3);
​
        } catch (MalformedURLException e) {
            Log.e("MalformedURLException", e.toString());
        }
        Paragraph paragraph_image = new Paragraph().add(image1)
                .add("  ")
                .add(image2)
                .add("  ")
                .add(image3);
        document.add(paragraph_image);
        document.add(new Paragraph(""));
​
        /**
         * 添加表格
         */
        Text text_table = new Text("Form:").setFont(font).setFontSize(text_title_size).setFontColor(text_title_color); 
        Paragraph paragraph_table = new Paragraph(text_table); 
        document.add(paragraph_table); 
        // 3 columns 
        float[] pointColumnWidths = {100f, 100f, 100f}; 
        Table table = new Table(pointColumnWidths); 
        // Set border style, color, width 
        Color table_color = new DeviceRgb(80, 136, 255); 
        Border border = new DottedBorder(table_color, 3 ); 
        table.setBorder(border); 
        // Set cell text to center 
        table.setTextAlignment(TextAlignment.CENTER); 
        // Add cell content 
        Color table_header = new DeviceRgb(0, 0, 255);
        Color table_content = new DeviceRgb(255, 0, 0);
        Color table_footer = new DeviceRgb(0, 255, 0);
        Text text1 = new Text("姓名").setFont(font).setFontSize(20.0f).setFontColor(table_header);
        Text text2 = new Text("年龄").setFont(font).setFontSize(20.0f).setFontColor(table_header);
        Text text3 = new Text("性别").setFont(font).setFontSize(20.0f).setFontColor(table_header);
        table.addHeaderCell(new Paragraph(text1));
        table.addHeaderCell(new Paragraph(text2));
        table.addHeaderCell(new Paragraph(text3));
        Text text4 = new Text("张三").setFont(font).setFontSize(15.0f).setFontColor(table_content);
        Text text5 = new Text("30").setFont(font).setFontSize(15.0f).setFontColor(table_content);
        Text text6 = new Text("男").setFont(font).setFontSize(15.0f).setFontColor(table_content);
        table.addCell(new Paragraph(text4));
        table.addCell(new Paragraph(text5));
        table.addCell(new Paragraph(text6));
        Text text7 = new Text("丽萨").setFont(font).setFontSize(15.0f).setFontColor(table_footer);
        Text text8 = new Text("20").setFont(font).setFontSize(15.0f).setFontColor(table_footer);
        Text text9 = new Text("女").setFont(font).setFontSize(15.0f).setFontColor(table_footer);
        table.addFooterCell(new Paragraph(text7));
        table.addFooterCell(new Paragraph(text8));
        table.addFooterCell(new Paragraph(text9)); 
        //Add the table to the pdf file 
        document.add(table); 
​/
        ** 
         * Add header, footer, watermark 
         */ 
        Rectangle pageSize; 
        PdfCanvas canvas; 
        int n = pdf_document.getNumberOfPages(); 
        Log.i("zxd", "createPDF: " + n); 
        for (int i = 1; i <= n; i++) { 
            PdfPage page = pdf_document.getPage(i); 
            Log.i ("zxd", "createPDF page: " + page.getPageSize()); 
            pageSize = page.getPageSize(); 
            canvas = new PdfCanvas(page); 
            // header 
            canvas.beginText().setFontAndSize(font, 7)
                    .moveText(pageSize.getWidth() / 2 - 18, pageSize.getHeight() - 10) 
                    .showText("I am the header") 
                    .endText(); 
​//
            Footer 
            canvas.setStrokeColor(text_color) 
                    .setLineWidth( .2f) 
                    .moveTo(pageSize.getWidth() / 2 - 30, 20) 
                    .lineTo(pageSize.getWidth() / 2 + 30, 20).stroke(); 
            canvas.beginText().setFontAndSize(font, 7) 
                    .moveText(pageSize.getWidth() / 2 - 6, 10) 
                    .showText(String.valueOf(i)) 
                    .endText(); 
​//
            watermark
            Paragraph p = new Paragraph("Quinto").setFontSize(60); 
            canvas.saveState(); 
            PdfExtGState gs1 = new PdfExtGState().setFillOpacity(0.2f); 
            canvas.setExtGState(gs1); 
            document.showTextAligned(p, pageSize .getWidth() / 2, pageSize.getHeight() / 2, 
                    pdf_document.getPageNumber(page), 
                    TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45); 
            canvas.restoreState(); 
        } 
​//
        Close 
        document.close(); 
        Toast.makeText(this, "PDF file has been generated", Toast.LENGTH_SHORT).show(); 
    } else { 
        //No permission 
        //requestPermission();
    }
}

Precautions

1.pdfdocument.getPageSize() is not set as an instance of the object iText7, and an error is reported when getting the page size, because the parameter of immediate refresh is set to true

You can tell 文档not to refresh its contents by default by passing the third parameter ( ) falsein the constructorimmediateflush

Document document = new Document(pdf_document, PageSize.A4, false);

pdfdocument.getPageSize() not set to instance of object iText7

2. If the image resource is not found, an io error will be reported

2.2 Basic use of 7.x

2.2.1 Display Chinese

When itext7 uses the default font to display Chinese, because the default font does not support Chinese, the Chinese in the generated pdf will display blank. To solve this problem, you need to import the font yourself.

1. Download a Chinese font (.ttf file, SourceHanSansCN.ttf)

2. Load local font styles

InputStream inputStream = new FileInputStream(new File("SourceHanSansCN.ttf")); 
//The third parameter is embedded, whether it is a built-in font, here is provided by yourself, so pass false 
PdfFont font = PdfFontFactory.createFont(IOUtils.toByteArray( inputStream), PdfEncodings. IDENTITY_H, false);

3. Set the font

//The default is A4 paper size 
Document document = new Document(pdfDocument, new PageSize()); 
document.setFont(font);

2.2.2 Resolution

If there is a need for pdf printing, it involves the issue of resolution.

In itext, except for the inserted pictures, the others are vector graphics, so you don’t have to worry about the resolution. You only need to ensure the resolution of the inserted pictures. The default resolution of the pictures generated in itext is 72dpi. Here, some processing is required. , as follows:

int defaultDpi = 72;
int targetDpi = 300;
Image test = new Image(ImageDataFactory.create("test.jpg"));
test.scale(defaultDpi/targetDpi, defaultDpi/targetDpi);

2.2.3 Layout

The Itext coordinate system is as shown in the figure below. When using an absolute layout, it is necessary to calculate the length of the element from the left side and the bottom side. When using a relative layout, the elements are arranged from top to bottom.

Coordinate origin map

absolute layout
setFixedPosition(float left, float bottom, float width)
relative layout

When using a relative layout, setFixedPosition is not required, and only the length of the distance from top to bottom, left, and right can be set.

setMarginLeft(float value);
setMarginRight(float value);
setMarginBottom(float value);
setMarginTop(float value);
setMargin(float commonMargin);

2.2.4 Automatic pagination + generate page number

When using absolute layout, in most cases the page content is of fixed size and position, and paging also needs to be controlled by writing code yourself. But if the content of the pdf is not fixed, it is not so flexible to use the absolute layout at this time, and you need to calculate the height of the element and set the absolute position. At this time, it is more appropriate and simpler for us to choose to use the relative layout. The code is as follows: 
​class
PageEventHandler implements IEventHandler { 
    private Document document; 
    private PdfFont font; 
​//
    Because of the need for unified and Chinese fonts, a pdffont parameter is added. If there is no such requirement, 
    public PageEventHandler(Document document, PdfFont font may not be added ){ 
        this.document = document; 
        this.font = font; 
    } 
    ​@Override
 
    public void handleEvent(Event event) { 
        PdfDocumentEvent pdfEvent = (PdfDocumentEvent) event; 
        PdfPage page = pdfEvent.getPage();
        PdfDocument pdfDoc = pdfEvent.getDocument(); 
​//
        Get the current page number 
        int pageNumber = pdfDoc.getPageNumber(page); 
        PdfCanvas pdfCanvas = new PdfCanvas( 
                page.newContentStreamBefore(), page.getResources(), pdfDoc); 
​//
        In Write the page number at a distance of 50 from the previous element 
        this.document.setTopMargin(50f); 
​pdfCanvas.beginText
        () 
                .setFontAndSize(this.font, 32) 
                //Write the current page at a place where the page is generally wide, due to font positioning The origin is also in the lower left corner, so here the x-axis subtracts half of the width of the page number, making sure that the page number is written in the middle 
                //The y-axis is 20px from the bottom 
                .moveText(PageSize.A4.getWidth()/2-32/ 2, 20f) 
                .showText(String.valueOf(pageNumber))
                .endText();
        pdfCanvas.release();
​
    }
}
​
//使用
pdfDocument.addEventHandler(PdfDocumentEvent.START_PAGE, new PageEventHandler(document, font));

2.2.5 Common components

table
//Do not specify the width of each column of the table, adapt to the content of the column 
public Table(int numColumns); 
//Specify the width of each column 
public Table(float[] pointColumnWidths); 
//Add cells to the table, the default is Add horizontally, and when the specified number of columns is reached, the line will automatically wrap 
public Table addCell(Cell cell); 
//Set the border of the table or cell, here you need to pay attention, if you don't want to display the border, you need to set the border to none in each cell, only Setting the border of the table will still display the border 
public T setBorder(Border border); 
//No border 
cell.setBorder(Border.NO_BORDER); 
//Solid border 
cell.setBorder(new SolidBorder(1)); 
//Dotted border 
cell.setBorder(new DashedBorder(1)); 
//four are rounded corners 
cell.setBorderRadius(new BorderRadius(10f)); 
//rounded corner - lower right corner 
cell.setBorderBottomRightRadius(new BorderRadius(10f)); 
// Rounded Corner - Bottom Left
cell.setBorderBottomLeftRadius(new BorderRadius(10f)); 
//Rounded corner - upper right corner 
cell.setBorderTopRightRadius(new BorderRadius(10f)); 
//Rounded corner - upper left corner 
cell.setBorderTopLeftRadius(new BorderRadius(10f)); 
//About The rounded corners, the rounded corners in the table, seem to be set and cannot take effect, but it can be achieved by setting the border of the outer table to none and setting the border of the inner cell
Implement a progress bar with table
  • Idea: the outer layer is a table with one row and one column, and the inner cell is set with a table with one row and one column as the actual progress, and the width of the inner table is calculated according to the percentage

//percent here is a decimal 
public void processBar(Document document, float width, float percent){ 
    float processWidth = width * percent; 
    DeviceRgb processColor = new DeviceRgb(11,11,11);//Just write a color 
    DeviceRgb processBgColor = new DeviceRgb(101,11,11);//Just write a color 
    
    Table table = new Table(new float[]{width}).setMargin(0).setPadding(0);//Add unnecessary Gaps are killed in the cradle 
    Table processTable = new Table(new float[]{processWidth}).setMargin(0).setPadding(0); 
    processTable.addCell(new Cell().setBorder(Border.NO_BORDER) 
                         .setMargin(0 ).setPadding(0).setBackgroundColor(processColor)); 
    
    table.addCell(new Cell().setBorder(Border.NO_BORDER).setBackgroundColor(processBgColor)
                  .setMargin(0).setPadding(0).setBorder(Border.NO_BORDER).add(processTable));
​
}
Paragraph

Paragraph should be the most frequently used class, and this class will be used to write text in pdf.

Paragraph para = new Paragraph("I am a paragraph") 
    .setFontSize(14)//Set the font size.setBold 
    ()//Set the text to bold.setFontColor 
    (new DeviceRgb(0,0,0))//Set Font 
    color.setTextAlignment(TextAlignment.CENTER)//The text is centered 
    horizontally.setFixedLeading(14);//Similar to the line height in css

Sometimes there will be some requirements that part of the text in the same paragraph needs to be set to another color or style. At this time, Text can be used to handle it, as follows:

//This processing method can't deal with the problem of bolding. If the text you want to be bold is just in the middle of the paragraph, but if you set it to bold, it will cause the entire text to become bold (italics are the same) para 
. add(new Text("I want to be different").setFontSize("20").setFontColor(new DeviceRgb(255,255,255)));

Image
//For image resolution issues, see the resolution section above 
Image image = new Image(ImageDataFactory.create("/home/test.jpg"));

Reference: Itext7 generates the most complete api summary of pdf

2.2.6 Basic usage

private void pdf1() {
    path = getExternalFilesDir("").getAbsolutePath() + "/itext_basic.pdf";
    PdfWriter writer;//创建一个写入传递的输出流的 PdfWriter。
    try {
        writer = new PdfWriter(new FileOutputStream(path));
        PdfFont font = PdfFontFactory.createFont(StandardFonts.TIMES_ROMAN);
        PdfDocument pdf = new PdfDocument(writer);
        Document document = new Document(pdf);
        Text text = new Text("Hello World PDF created using iText")
                .setFont(font)
                .setFontSize(15)
                .setFontColor(ColorConstants.MAGENTA);
        //Add paragraph to the document
        document.add(new Paragraph(text));
        document.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

2.2.7 Font style

try {
    PdfDocument pdf = new PdfDocument(new PdfWriter(path));
    PdfFont font = PdfFontFactory.createFont(StandardFonts.COURIER);
    Style style = new Style().setFont(font)
            .setFontSize(14)
            .setFontColor(ColorConstants.RED)
            .setBackgroundColor(ColorConstants.YELLOW);
​
    Document document = new Document(pdf);
    document.add(new Paragraph()
            .add("In this PDF, ")
            .add(new Text("Text is styled").addStyle(style))
            .add(" using iText ")
            .add(new Text("Style").addStyle(style))
            .add("."));
    document.close();
​
} catch (IOException e) {
    e.printStackTrace();
}

2.2.8 txt to pdf

private void pdf3(String source, String des) {
    try {
        BufferedReader br = new BufferedReader(new FileReader(source));
        PdfDocument pdf = new PdfDocument(new PdfWriter(des));
        Document document = new Document(pdf);
        String line;
        PdfFont font = PdfFontFactory.createFont(StandardFonts.COURIER);
        while ((line = br.readLine()) != null) {
            document.add(new Paragraph(line).setFont(font));
        }
        br.close();
        document.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Reference: Generate Chinese PDF in Java using iText 7

2.3 open pdf

/**
 * 打开PDF文件
 */
private void openPDF() {
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            try {
                FileUtils.openFile(context, new File(path));
            } catch (Exception e) {
                Log.e("Exception", e.toString());
            }
        }
    }, 1000);
}

open PDF file

/**
 * 打开PDF文件
 *
 * @param context
 * @param url
 * @throws ActivityNotFoundException
 * @throws IOException
 */
public static void openFile(Context context, File url) throws ActivityNotFoundException {
    if (url.exists()) {
        Uri uri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".fileprovider", url);
​
        String urlString = url.toString().toLowerCase();
​
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        /**
         * Security
         */
        List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); 
        for (ResolveInfo resolveInfo : resInfoList) { 
            String packageName = resolveInfo.activityInfo.packageName; 
            context.grantU riPermission(packageName, uri, Intent. FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); 
        } 
​//
        Check the file type you want to open by comparing the url and extension. 
        // When the if condition matches, the plugin sets the correct intent (mime) type 
        // so Android knows what program to use to open the file 
        if (urlString.toLowerCase().contains(".doc") 
                || urlString.toLowerCase(). contains(".docx")) { 
            // Word document
            intent.setDataAndType(uri, "application/msword");
        } else if (urlString.toLowerCase().contains(".pdf")) {
            // PDF file
            intent.setDataAndType(uri, "application/pdf");
        } else if (urlString.toLowerCase().contains(".ppt")
                || urlString.toLowerCase().contains(".pptx")) {
            // Powerpoint file
            intent.setDataAndType(uri, "application/vnd.ms-powerpoint");
        } else if (urlString.toLowerCase().contains(".xls")
                || urlString.toLowerCase().contains(".xlsx")) {
            // Excel file
            intent.setDataAndType(uri, "application/vnd.ms-excel");
        } else if (urlString.toLowerCase().contains(".zip")
                || urlString.toLowerCase().contains(".rar")) {
            // ZIP file
            intent.setDataAndType(uri, "application/trap");
        } else if (urlString.toLowerCase().contains(".rtf")) {
            // RTF file
            intent.setDataAndType(uri, "application/rtf");
        } else if (urlString.toLowerCase().contains(".wav")
                || urlString.toLowerCase().contains(".mp3")) {
            // WAV/MP3 audio file
            intent.setDataAndType(uri, "audio/*");
        } else if (urlString.toLowerCase().contains(".gif")) {
            // GIF file
            intent.setDataAndType(uri, "image/gif");
        } else if (urlString.toLowerCase().contains(".jpg")
                || urlString.toLowerCase().contains(".jpeg")
                || urlString.toLowerCase().contains(".png")) {
            // JPG file
            intent.setDataAndType(uri, "image/jpeg");
        } else if (urlString.toLowerCase().contains(".txt")) {
            // Text file
            intent.setDataAndType(uri, "text/plain");
        } else if (urlString.toLowerCase().contains(".3gp")
                || urlString.toLowerCase().contains(".mpg")
                || urlString.toLowerCase().contains(".mpeg")
                || urlString.toLowerCase().contains(".mpe") 
                || urlString.toLowerCase().contains(".mp4") 
                || urlString.toLowerCase().contains(".avi")) { 
            // Video files 
            intent.setDataAndType(uri, "video/*"); 
        } else { 
            // You can also define the intent type for any other file if you want 
            // Also, use the else clause below to manage other unknown extensions 
            // In this case Android will show all apps installed on the device 
            // so you can choose which one to use 
            intent.setDataAndType(uri, "*/*"); 
        } 
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
        context .startActivity(intent); 
    } else {
        Toast.makeText(context, "The file does not exist", Toast.LENGTH_SHORT).show(); 
    } 
}

manifest.xml

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="com.zg.pdfdemo.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
</provider>

provider_paths

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external_files" path="."/>
</paths>

2.4 Simple use of pdfRender

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 
private void pdf4() { 
    path = getExternalFilesDir("").getAbsolutePath() + "/itext_basic.pdf"; 
    try { 
        // 1. Create a file 
        File pdfFile = new File( path); 
        // 2. Get the ParcelFileDescriptor object 
        ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY); 
        // 3. Create a PdfRenderer object 
        PdfRenderer renderer = new PdfRenderer(parcelFileDescriptor); 
​//
        Render page data to bitmap 
        // 1. Get page number data Page object 
        PdfRenderer.Page page = renderer.openPage(0); 
        int pageCount = renderer.getPageCount();
        Log.i("zxd", "pdf4: Total = " + pageCount); 
​//
        2. Create ARGB_8888 bitmap Bitmap 
        bitmap = Bitmap.createBitmap(page.getWidth(), page.getHeight(), Bitmap.Config. ARGB_8888); 
        //3. Render 
        page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY); 
        //Render to iv 
        binding.iv.setImageBitmap(bitmap); 
        //Close current page data 
        page.close( ); 
​}
    catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
    } 
}

Summarize

Advantages: It is provided by Android itself. It is relatively lightweight and does not need to rely on third-party SDK. The core code is all natively implemented, and the execution efficiency is relatively high.

Disadvantages: It can only be used on Android 5.0 or above. Since the implementation is native, it is impossible to customize the rendering algorithm by yourself, and it is cumbersome to control the thread safety by yourself when using it.

reference:

[API Reference Document](https://www.apiref.com/)

Android PdfRenderer simple to use

Android uses pdfRenderer to realize PDF display function

itext5

Guess you like

Origin blog.csdn.net/fromVillageCoolBoy/article/details/131704261