Shahul
Shahul

Reputation: 201

Android: PdfDocument generates empty pdf

        PdfDocument document = new PdfDocument();
        // crate a page description
        PageInfo pageInfo = new PageInfo.Builder(300, 300, 1).create();
        // create a new page from the PageInfo
        Page page = document.startPage(pageInfo);
        // repaint the user's text into the page
        View content = findViewById(R.id.textarea);
        content.draw(page.getCanvas());
        // do final processing of the page
        document.finishPage(page);
        try {
             File f = getPDFPath();
             FileOutputStream fos = new FileOutputStream(f);
             document.writeTo(fos);
             document.close();
             fos.close();

        } catch (IOException e) {
            throw new RuntimeException("Error generating file", e);
        }

Where findViewById(R.id.textarea); refers to a TextView with some text, but the above code generates only empty pdf. What can be the issue?

is there any link that have working sample of generating pdf using Android native API?

Upvotes: 18

Views: 18488

Answers (5)

Kayes Fahim
Kayes Fahim

Reputation: 690

First Of all, you need to add dependency

implementation group: 'com.itextpdf', name: 'itextpdf', version: '5.3.2'

Then Set bitmap on Blank PDf Documents

            PdfDocument pdfDocument =  new PdfDocument();
            PdfDocument.PageInfo pi = new 
            PdfDocument.PageInfo.Builder(mBitmap.getWidth(), 
            mBitmap.getHeight(),1).create();

            PdfDocument.Page page = pdfDocument.startPage(pi);
            Canvas canvas = page.getCanvas();
            Paint paint = new Paint();
            paint.setColor(Color.parseColor("#FFFFFF"));
            canvas.drawPaint(paint);

            mBitmap = Bitmap.createScaledBitmap(mBitmap, 
            mBitmap.getWidth(),mBitmap.getHeight(), true);
            paint.setColor(Color.BLUE);
            canvas.drawBitmap(mBitmap,0,0,null);
            pdfDocument.finishPage(page);
            pdfDocument.close();

Upvotes: 0

Brcinho
Brcinho

Reputation: 321

If somebody is creating layout on the fly, and doesn't have its view attached to activity or fragment which gets rendered and measured at some point in activity or fragment lifecycle, there is another approach:

rootView.measure(800, 480);
rootView.layout(0, 0, 800, 480);

This way your rootView width and height will not stay 0 and there will be something that will be rendered to document. Courtesy of the answer here!

Upvotes: 6

lelloman
lelloman

Reputation: 14173

I had the exact same problem but in order to implement @user2021505 solution (that works) I should have done a major refactor, so I solved the issue this way

// ...
PdfDocument.Page page = document.startPage(pageInfo);

TextView textView = new TextView(ctx);
textView.setText("1,2,3");

// here the solution
int left = 0;
int top = 0;
int width = 200;
int height = 200;
textView.layout(0,0,width,height);

canvas.save()
canvas.translate(left,top);

textView.draw(page.getCanvas());

canvas.restore()

Upvotes: 1

AlvaroSantisteban
AlvaroSantisteban

Reputation: 5336

The example that has helped me the most is the one that it can be found in the Android Cookbook You can find the corresponding code in their github account.

Mix that code with the one for writing and you will have it:

@TargetApi(Build.VERSION_CODES.KITKAT)
public void run() {
    // Create a shiny new (but blank) PDF document in memory
    // We want it to optionally be printable, so add PrintAttributes
    // and use a PrintedPdfDocument. Simpler: new PdfDocument().
    PrintAttributes printAttrs = new PrintAttributes.Builder().
            setColorMode(PrintAttributes.COLOR_MODE_COLOR).
            setMediaSize(PrintAttributes.MediaSize.NA_LETTER).
            setResolution(new PrintAttributes.Resolution("zooey", PRINT_SERVICE, 300, 300)).
            setMinMargins(PrintAttributes.Margins.NO_MARGINS).
            build();
    PdfDocument document = new PrintedPdfDocument(this, printAttrs);
    // crate a page description
    PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(300, 300, 1).create();
    // create a new page from the PageInfo
    PdfDocument.Page page = document.startPage(pageInfo);
    // repaint the user's text into the page
    View content = findViewById(R.id.textArea);
    content.draw(page.getCanvas());
    // do final processing of the page
    document.finishPage(page);
    // Here you could add more pages in a longer doc app, but you'd have
    // to handle page-breaking yourself in e.g., write your own word processor...
    // Now write the PDF document to a file; it actually needs to be a file
    // since the Share mechanism can't accept a byte[]. though it can
    // accept a String/CharSequence. Meh.
    try {
        File f = new File(Environment.getExternalStorageDirectory().getPath() + "/pruebaAppModerator.pdf");
        FileOutputStream fos = new FileOutputStream(f);
        document.writeTo(fos);
        document.close();
        fos.close();            
    } catch (IOException e) {
        throw new RuntimeException("Error generating file", e);
    }
}

Upvotes: 3

user2021505
user2021505

Reputation: 302

i have the have, but after a lot of test, i realise that my View was with 0 heigth and 0 width, since i was using a TextView. So i managed to wait till view (TextView) will load and after start creating document, take a look at the code, hope you will fix it:

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.fragment_main);

     final TextView tv = (TextView) findViewById(R.id.textView1);
        ViewTreeObserver vto = tv.getViewTreeObserver(); 
        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
            @Override 
            public void onGlobalLayout() { 
                Toast.makeText(MainActivity.this, tv.getWidth() + " x " + tv.getHeight(), Toast.LENGTH_LONG).show();    

                try {
                    File file1 = new File("/mnt/sdcard/test/");
                    if(!file1.exists()){
                        file1.mkdirs();
                    }

                    File file = new File("/mnt/sdcard/test", "filename"+System.currentTimeMillis()+".pdf");
                    PrintAttributes printAttrs = new PrintAttributes.Builder().
                            setColorMode(PrintAttributes.COLOR_MODE_COLOR).
                            setMediaSize(PrintAttributes.MediaSize.ISO_A4).
                            setResolution(new Resolution("zooey", PRINT_SERVICE, 450, 700)).
                            setMinMargins(Margins.NO_MARGINS).
                            build();
                    PdfDocument document = new PrintedPdfDocument(MainActivity.this, printAttrs);
                     PageInfo pageInfo = new PageInfo.Builder(450, 700, 1).create();
                     Page page = document.startPage(pageInfo);

                     if (page != null) {

                           View view = findViewById(R.id.textView1);//getContentView();                          
                           view.layout(0, 0, view.getWidth(),
                                   view.getHeight());
                           Log.i("draw view", " content size: "+view.getWidth()+" / "+view.getHeight());
                           view.draw(page.getCanvas());
                           // Move the canvas for the next view.
                           page.getCanvas().translate(0, view.getHeight());
                       }    

                     document.finishPage(page);
                     os = new FileOutputStream(file);
                            document.writeTo(os);
                            document.close();
                            os.close();
                            Log.i("done", file.getAbsolutePath().toString());

                        } catch (IOException e) {
                            throw new RuntimeException("Error generating file", e);
                        }

                tv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            } 
        });

}

the magic inside:

 final TextView tv = (TextView) findViewById(R.id.textView1);
        ViewTreeObserver vto = tv.getViewTreeObserver(); 
        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
            @Override 
            public void onGlobalLayout() { 
         // create document here
} 
        });

Upvotes: 12

Related Questions