3

I'm using Android Studio and trying to get my app to produce a PDF. I've set up an Activity which generates the content that I want my PDF to have. This works fine if I let it display on screen. The onCreate part of the Activity is below:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Connect to database
    connectToDatabase();

    // Set view
    setContentView(R.layout.activity_export_pattern);

    // find various views and set up their contents 
    // (I've left this bit out as it's quite long, but it doesn't contain 
    // anything controversial)

    // Now try to export to PDF.  
    // Return success or failure to calling activity 
    //  (basically just displays a toast indicating success/failure)
    try {
        if(exportToPDF()) {
            Intent returnIntent = new Intent();
            setResult(Activity.RESULT_OK, returnIntent);
            finish();
        }else {
            Intent returnIntent = new Intent();
            setResult(Activity.RESULT_CANCELED, returnIntent);
            finish();
        }
    } catch (IOException e) {
        e.printStackTrace();
        Intent returnIntent = new Intent();
        setResult(Activity.RESULT_CANCELED, returnIntent);
        finish();
    }
}

If I omit the final part (the try-catch), and just let it display on the screen, it works fine. The screen displays what I expect it to display.

However, to get it to create a PDF, I use the try-catch with the call to exportToPDF, which contains the following code (this is basically the code from the Android documentation, with a few changes as indicated by comments below):

   public boolean exportToPDF() {
        // Create PDF document
        PdfDocument document = new PdfDocument();
        // Create page description
        // Line below changed as Android Studio was highlighting an error; 
        //  instead of Rect, I have just put numbers.
        //  I've varied the numbers from 100 up to 1000, to no effect
        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(720, 720, 1).create();
        // Start page
        PdfDocument.Page page = document.startPage(pageInfo);
        // Changed the line below from content = getContentView, as that was causing an error
        // pageContent is the id of the overall LinearLayout in the XML file
        // If I break after this in the debugger, content seems to have found the correct view and be populated with the appropriate page elements
        View content =  this.findViewById(R.id.pageContent);
        // Added the line below after finding it suggested on here in another question
        //  Doesn't seem to make any difference
        content.layout(0, 0, 200, 200);
        if (content != null) {
            content.draw(page.getCanvas());
        }
        // Finish page
        document.finishPage(page);

        // Write document content to external storage
        // I'm using a FileOutputStream instead of BufferedOutputStream as given in the documentation, but, since this does at least produce a file, I don't think this is the source of the problem
        String filename = this.item.getName() + ".pdf";
        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + filename);
        FileOutputStream fileOut = null;
        try {
            fileOut = new FileOutputStream(file);
            document.writeTo(fileOut);
            fileOut.close();
            document.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            if(fileOut != null) fileOut.close();
            document.close();
            return false;
        }
    }

So, running this produces a PDF in the correct directory, named correctly, but it's blank. I've no idea what else to try.

halfer
  • 19,824
  • 17
  • 99
  • 186
Sharon
  • 3,471
  • 13
  • 60
  • 93

1 Answers1

3

Where you writing view to PDF onCreate() in activity, it won't work and because your view returned 0 height and width. You need to wait for activity window to attached and then write view to pdf. You can try calling exportToPDF from onWindowFocusChanged() method of your activity.

public void onWindowFocusChanged(boolean hasFocus) {
    // TODO Auto-generated method stub
    super.onWindowFocusChanged(hasFocus);
try {
        if(exportToPDF()) {
            Intent returnIntent = new Intent();
            setResult(Activity.RESULT_OK, returnIntent);
            finish();
        }else {
            Intent returnIntent = new Intent();
            setResult(Activity.RESULT_CANCELED, returnIntent);
            finish();
        }
    } catch (IOException e) {
        e.printStackTrace();
        Intent returnIntent = new Intent();
        setResult(Activity.RESULT_CANCELED, returnIntent);
        finish();
    }

    }

You can also use ViewTreeObserver

 View content =  this.findViewById(R.id.pageContent);
    ViewTreeObserver vto = content.getViewTreeObserver(); 
            vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
                @Override 
                public void onGlobalLayout() { 
              try {
            if(exportToPDF()) {
                Intent returnIntent = new Intent();
                setResult(Activity.RESULT_OK, returnIntent);
                finish();
            }else {
                Intent returnIntent = new Intent();
                setResult(Activity.RESULT_CANCELED, returnIntent);
                finish();
            }
        } catch (IOException e) {
            e.printStackTrace();
            Intent returnIntent = new Intent();
            setResult(Activity.RESULT_CANCELED, returnIntent);
            finish();
        }
content.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    } 
            }); 
USKMobility
  • 5,721
  • 2
  • 27
  • 34
  • Thanks - I'll give that a go. – Sharon Jun 11 '16 at 13:43
  • That worked! Thank you. I didn't need to use the second part (viewTreeObserver). Just need to fiddle with the page and content sizes now. Thanks again for your help. – Sharon Jun 11 '16 at 14:22