Incremental PDF saving on Android
In some cases, the file size of a document will increase with each save. This could be particularly noticeable if the document contains image annotations with large images and is saved often, either explicitly or via any of the available save triggers.
Incremental saving, which is enabled by default, is the strategy PSPDFKit uses to make sure saving is as fast as possible: It always appends changes to the end of the document, but it never deletes anything. However, even though this is the fastest way of saving a document, it does come with the cost of incrementing the file size with each save. You can read more about incremental vs. full saving in PDFs here.
In most cases, the file size increase is negligible. However, there might be some cases in which you want to prioritize file size over saving performance. Below you’ll find some strategies to prevent the file size from growing unnecessarily when saving changes to a document.
Rewriting a Document When Saving
You can trigger a non-incremental document save, which will rewrite the entire document instead of appending changes at the end.
This can be done by manually saving the document and setting the incrementalSave
property of DocumentSaveOptions
to false
as follows:
val incrementalSave = false val options = document.defaultDocumentSaveOptions options.isIncremental = incrementalSave document.saveIfModified(options)
final boolean incrementalSave = false; final DocumentSaveOptions options = document.getDefaultDocumentSaveOptions(); options.setIncremental(incrementalSave); document.saveIfModified(options);
Keep in mind that rewriting the document does not guarantee that the file size will be the same after saving.
Optimizing Size Even Further
In addition to disabling incremental saving, you can also set the rewriteAndOptimizeFileSize
property of DocumentSaveOptions
to true
. This will cause PSPDFKit to first determine which objects in the PDF are no longer required and then remove them from the final output:
val incrementalSave = false val options = document.defaultDocumentSaveOptions options.isIncremental = incrementalSave options.setRewriteAndOptimizeFileSize(true) document.saveIfModified(options)
final boolean incrementalSave = false; final DocumentSaveOptions options = document.getDefaultDocumentSaveOptions(); options.setIncremental(incrementalSave); options.setRewriteAndOptimizeFileSize(true); document.saveIfModified(options);
While this leads to smaller file sizes, performing this operation is not free and will increase the time it takes to save documents.
When rewriteAndOptimizeFileSize
is enabled, incremental saving will automatically be disabled.
Do not rely on file size optimization to get to a target file size. This option does not provide any kind of guarantee that the resulting file will be smaller by a fixed number of bytes.
Disabling Incremental Save When Using Auto-Save
The method described above works only when you are saving manually. But it is also possible to disable incremental saving when using auto-save with PdfActivity
or PdfFragment
.
The simplest method is to disable incremental saving via DocumentListener#onDocumentSave()
:
override fun onDocumentSave(document: PdfDocument, saveOptions: DocumentSaveOptions): Boolean { saveOptions.isIncremental = false return super.onDocumentSave(document, saveOptions) }
@Override public boolean onDocumentSave(@NonNull PdfDocument document, @NonNull DocumentSaveOptions saveOptions) { saveOptions.setIncremental(false); return super.onDocumentSave(document, saveOptions); }
Incremental saving can also be prevented by using a custom WritableDataProvider
with disabled appending:
// Return `false` from `supportsAppending()` to prevent incremental saving. val dataProvider = object: ContentResolverDataProvider(uri) { override fun supportsAppending(): Boolean { return false } } // Start the activity. val intent = PdfActivityIntentBuilder.fromDataProvider(context, dataProvider) .configuration(configuration) .build() context.startActivity(intent)
// Return `false` from `supportsAppending()` to prevent incremental saving. DataProvider dataProvider = new ContentResolverDataProvider(uri) { @Override public boolean supportsAppending() { return false; } }; // Start the activity. Intent intent = PdfActivityIntentBuilder.fromDataProvider(context, dataProvider) .configuration(configuration) .build(); context.startActivity(intent);