Managing data storage and privacy in Android
When auditing your app’s data practices, it’s important to understand how Nutrient Android SDK handles data storage, caching, and privacy. This guide explains where and how data is stored locally, and how you can maintain control over data retention and security.
No external data transmission
Nutrient Android SDK operates entirely on-device with no external data transmission. All PDFs, annotations, and metadata remain on the device. The SDK doesn’t send any document data, annotations, or user information to external servers unless you explicitly implement such functionality in your application.
For information about network access used by the SDK itself, refer to our SDK security guide.
Data storage overview
The SDK manages different types of data with varying persistence and cleanup strategies, as detailed below.
Temporary files and caches
The SDK uses Android’s cache directory for temporary data that improves performance but isn’t essential to preserve. This data is stored in cache/nutrient within your app’s cache directory.
Cache types and management
Bitmap memory cache
- Purpose — Stores prerendered page bitmaps for fast display
- Size limit — 15 MB by default
- Eviction — Least recently used (LRU) items removed when limit exceeded
- Memory pressure — Automatically released when Android signals low memory
Rendered page cache
- Purpose — Caches fully rendered PDF pages
- Size limit — 32 MB by default
- Eviction — LRU-based when limit exceeded
- Configuration — Customize using
PdfActivityConfiguration.Builder#memoryCacheSize()
Automatic cleanup
The Android operating system may clear cache files when:
- The device is running low on storage
- The user manually clears app cache via Settings
- The app is uninstalled
For more information about cache configuration and memory optimization, refer to our memory usage guide.
Clearing caches programmatically
You can manually clear caches when needed:
// Clear Nutrient's bitmap memory cache.Nutrient.clearCaches()
// Clear all app cache files (including Nutrient's disk cache).context.cacheDir.deleteRecursively()Persistent data
Persistent data includes PDFs, annotations, and document state that should be retained across app sessions.
Annotation storage
Annotations are stored differently depending on whether a PDF is writeable.
Writeable PDFs
- Annotations are saved directly into the PDF file using
AnnotationProvider - Data persists as part of the PDF document
- No separate annotation files are created
Read-only PDFs
For read-only documents where you still want users to edit and save annotations, use the Save As functionality to save the modified document to a new writeable location. Refer to the how to save documents as PDFs on Android guide for implementation details.
To learn more about annotation saving mechanism, refer to the save PDF annotations on Android guide.
Document state
Nutrient Android SDK maintains an internal SQLite database that stores document preferences:
- Last viewed page position
- Selected annotation tool
- User interface (UI) state preferences
Important characteristics
- Does not store annotations — Only UI state and preferences
- Automatic cleanup — Old data is automatically pruned to keep storage manageable
- Transient data — Safe to delete without losing document content or annotations
Auto-save behavior
Auto-save triggers when the fragment’s onStop() is called, which happens when:
- App is backgrounded
- Activity is no longer visible
- Configuration changes (for example, screen rotation) since it destroys and recreates the activity, triggering
onStop()
You can monitor or customize this behavior as demonstrated below:
// Disable auto-save if needed.val config = PdfConfiguration.Builder() .autosaveEnabled(false) .build()
// Monitor save events with `DocumentListener`.pdfFragment.addDocumentListener(object : DocumentListener { override fun onDocumentSaved(document: PdfDocument) { // Handle successful save. Log.d("App", "Document saved successfully") }
override fun onDocumentSaveFailed(document: PdfDocument, error: Throwable) { // Handle save failure. Log.e("App", "Document save failed", error) }})For advanced save configuration, including checkpointing, refer to our auto save guide.
Manual save operations
You can programmatically save documents and annotations at any time:
// Synchronous save (blocks until complete).document.saveIfModified()
// Asynchronous save with callback.pdfFragment.saveAsync().subscribe(object : SimpleCompletableObserver() { override fun onComplete() { // Document saved successfully }
override fun onError(e: Throwable) { // Handle save error. }})Security and privacy considerations
An app’s private storage is protected by Android’s sandboxing mechanisms, ensuring other apps cannot access your app’s files. Below are some best practices to enhance data security and privacy.
App sandbox protection
All files created by Nutrient Android SDK reside in your app’s private storage, which is protected by Android’s application sandboxing:
- Other apps cannot access your app’s private files
- Files are automatically deleted when the app is uninstalled
- Root access or compromised devices bypass these protections
Read-only PDF annotations
For read-only PDFs, annotation files are stored separately and persist until explicitly deleted. If you need to implement data retention policies for compliance, use the following:
// Custom retention: Delete old annotation files after a certain period.fun cleanupOldAnnotations(maxAgeInDays: Int) { val annotationDir = File(context.filesDir, "annotations") val cutoffTime = System.currentTimeMillis() - (maxAgeInDays * 24 * 60 * 60 * 1000L)
annotationDir.listFiles()?.forEach { file -> if (file.lastModified() < cutoffTime) { file.delete() } }}Screenshot prevention
By default, Nutrient doesn’t prevent screenshots. To prevent screenshot capture for sensitive documents, you can set the FLAG_SECURE flag on your activity’s window:
// In your activity.override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Prevent screenshots and screen recording. window.setFlags( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE )}Compliance and data retention
We recommend the following practices to help ensure compliance with data protection regulations such as General Data Protection Regulation (GDPR).
GDPR and privacy compliance
To ensure compliance with data protection regulations:
- Document what data is stored — PDFs, annotations, document state, and cache files
- Implement data deletion — Clear caches and delete annotation files when users delete documents
- Respect user privacy — No data leaves the device unless you implement sync features
- Provide transparency — Inform users about local storage in your privacy policy
Custom storage paths
If you need to control where documents and annotations are stored, you can implement a custom data provider by extending the WriteableDataProvider interface. This enables you to define your own storage logic and paths:
// Use a custom data provider for full control.class CustomDataProvider(private val customPath: String) : WriteableDataProvider { // Implement custom storage logic. // This gives you full control over where and how data is stored.}
// Open document with custom provider.val document = PdfDocumentLoader.openDocument( context, CustomDataProvider("/custom/path/document.pdf"))For more information about custom data providers, refer to our custom data provider guide.