Import and Export PDF Annotations from XFDF Files in Android

XFDF is an XML-based standard from Adobe XFDF (ISO 19444-1:2016) for encoding annotations and forms. An XFDF file will contain a snapshot of the PDF document annotations and forms. It’s compatible with Adobe Acrobat and several other third-party frameworks.

ℹ️ Note: XFDF isn’t well-suited for synchronization. In most cases, using PSPDFKit Instant will result in a smaller file and better synchronization.

PSPDFKit for Android supports both reading and writing XFDF files. The XfdfFormatter class contains parseXfdf() and writeXfdf() methods you can use to perform these operations. It also contains their asynchronous counterparts, parseXfdfAsync() and writeXfdfAsync() (recommended so you can easily offload parsing from the UI thread).

Importing XFDF

To asynchronously read PDF annotations from an XFDF file, you can use the parseXfdfAsync() method, like so:

// Your data provider, serving the XFDF file to parse.
var yourDataProvider = SomeDataProvider()

// The async parse method is recommended (so you can easily offload parsing from the UI thread).
XfdfFormatter.parseXfdfAsync(pdfDocument, yourDataProvider)
    .subscribeOn(Schedulers.io()) // Specify the thread on which to parse XFDF.
    .subscribe { annotations ->
        // Annotations parsed from XFDF aren't added to the document automatically.
        // You need to add them manually.
        for (annotation in annotations) {
            pdfDocument.getAnnotationProvider().addAnnotationToPage(annotation)
        }
    }
// Your data provider, serving the XFDF file to parse.
DataProvider yourDataProvider = new SomeDataProvider();

// The async parse method is recommended (so you can easily offload parsing from the UI thread).
XfdfFormatter.parseXfdfAsync(pdfDocument, yourDataProvider)
    .subscribeOn(Schedulers.io()) // Specify the thread on which to parse XFDF.
    .subscribe(annotations -> {
        // Annotations parsed from XFDF aren't added to the document automatically.
        // You need to add them manually.
        for (Annotation annotation : annotations) {
            pdfDocument.getAnnotationProvider().addAnnotationToPage(annotation);
        }
    });

The list of annotations you get in the callback won’t be added to the document automatically. This allows you to have better control over which of these annotations you want to add. To add annotations to a document, use document.getAnnotationProvider().addAnnotationToPage() on the annotations you want to add.

Exporting to XFDF

You can export annotations and form fields from a document to an XFDF file like so:

// List of annotations from the document to be exported.
val listOfAnnotationsToExport = ...

// List of form fields from the document to be exported.
val listOfFormFieldsToExport = ...

// Output stream pointing to the XFDF file into which to write the data.
val outputStream = ...

// The async `write` method is recommended (so you can easily offload writing from the UI thread).
XfdfFormatter.writeXfdfAsync(pdfDocument, listOfAnnotationsToExport, listOfFormFieldsToExport, outputStream)
        .subscribeOn(Schedulers.io()) // Specify the thread on which to write XFDF.
        .subscribe(..)
// List of annotations from the document to be exported.
List<Annotation> listOfAnnotationsToExport = ... ;

// List of form fields from the document to be exported.
List<FormField> listOfFormFieldsToExport = ... ;

// Output stream pointing to the XFDF file into which to write the data.
OutputStream outputStream = ... ;

// The async `write` method is recommended (so you can easily offload writing from the UI thread).
XfdfFormatter.writeXfdfAsync(pdfDocument, listOfAnnotationsToExport, listOfFormFieldsToExport, outputStream)
        .subscribeOn(Schedulers.io()) // Specify the thread on which to write XFDF.
        .subscribe(..);