All-In-One Backup & Restore Suite for Android (Google Drive Cloud + Local Storage)
Backpack is a production-ready, drop-in Android backup framework that packages your Room SQLite Database and All Media Attachments (images, audio, videos, documents) into an encrypted, portable archive.
It supports both Google Drive (Cloud) and Device Storage (SAF / Local) with cross-device path remapping and automatic schema/conflict safety.
- ☁️ Google Drive App Folder: Uploads encrypted archives directly to the user's isolated Google Drive app folder.
- 📱 Local Device Storage (SAF): Export and Import backups via Android's Storage Access Framework file picker.
- 🖼️ Full Media Attachments Support: Automatically extracts, archives, and restores images, audio notes, PDFs, videos, and custom attachments.
- 🔄 Cross-Device Path Remapping: Deterministic, manifest-driven path translation so restored attachments load correctly across different Android versions and device storage roots.
- 🛡️ AES-256 GCM Encryption: Secure encryption for both cloud and local archives before writing or uploading.
- ⚡ Atomic DB Swap & Rollback: Safe WAL checkpointing and automatic
.bakrollback protection in case of unexpected errors. ⚠️ Attachment Conflict Resolution: Built-in duplicate detection (OVERWRITE,SKIP, orASK_USER).- 🔄 100% Backward Compatible: Automatically detects and restores legacy v1 raw
.dbfiles from Google Drive without crashing. - 🎨 Plug-and-Play UI: Includes pre-built
BackupViewand modular APIs.
Backpack powers backup & recovery for AutoSend on Google Play.
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}dependencies {
implementation("com.github.vedraj360:Backpack:2.0.4")
}In your Application class:
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
val database = AppDatabase.getInstance(this)
val config = BackupConfig(
database = database,
folderName = "My App Backups",
backupFileName = "myapp_backup",
encryptionEnabled = false,
autoBackupEnabled = false,
backupIntervalHours = 24,
includeAttachmentTypes = setOf(
AttachmentType.IMAGE,
AttachmentType.AUDIO,
AttachmentType.VIDEO,
AttachmentType.DOCUMENT
)
)
Backpack.initialize(this, config)
}
}Backpack comes with ready-to-use Material 3 Custom Views for both Cloud & Local storage:
Handles Google Drive account linking, status, and 1-tap backup/restore.
<com.vdx.backpack.ui.custom.BackupView
android:id="@+id/backupView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />Dedicated card UI matching the cloud backup style for export/import to device or SD card.
<com.vdx.backpack.ui.custom.LocalBackupView
android:id="@+id/localBackupView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />// 1. Check Authentication & Sign-in
val isAuth = Backpack.driveProvider.isAuthenticated()
val signInIntent = Backpack.driveProvider.getSignInIntent(activity)
// In Activity Result:
Backpack.driveProvider.handleSignInResult(activity, dataIntent)
// 2. Perform Cloud Backup (DB + Attachments)
lifecycleScope.launch {
Backpack.cloud.backup(context).collect { result ->
when (result) {
is BackupResult.InProgress -> updateProgress(result.progress)
is BackupResult.Success -> showSuccess("Backup completed!")
is BackupResult.Failure -> showError(result.error)
is BackupResult.ConflictDetected -> {}
}
}
}
// 3. Perform Cloud Restore
lifecycleScope.launch {
Backpack.cloud.restore(context, fileId).collect { result ->
when (result) {
is BackupResult.InProgress -> updateProgress(result.progress)
is BackupResult.Success -> restartApp()
is BackupResult.ConflictDetected -> {
// Prompt user to Overwrite or Keep Existing
Backpack.cloud.resolveConflict(context, overwrite = true)
}
is BackupResult.Failure -> showError(result.error)
}
}
}// 1. Export Backup to Local File (SAF CreateDocument)
val suggestedName = Backpack.local.getDefaultBackupFileName() // e.g. myapp_backup_v2_20260826_031500.zip
createDocLauncher.launch(suggestedName)
// Inside Activity Result:
lifecycleScope.launch {
Backpack.local.export(uri).collect { result ->
when (result) {
is LocalBackupResult.InProgress -> updateProgress(result.progress, result.message)
is LocalBackupResult.Success -> showSuccess("Exported successfully!")
is LocalBackupResult.Failure -> showError(result.error)
else -> {}
}
}
}
// 2. Import Backup from Local File (SAF OpenDocument)
openDocLauncher.launch(arrayOf("application/zip", "application/octet-stream", "*/*"))
// Inside Activity Result:
lifecycleScope.launch {
Backpack.local.import(uri).collect { result ->
when (result) {
is LocalBackupResult.InProgress -> updateProgress(result.progress, result.message)
is LocalBackupResult.Success -> restartApp()
is LocalBackupResult.ConflictDetected -> {
// Resolve conflict:
Backpack.local.resolveConflict(overwrite = true)
}
is LocalBackupResult.Failure -> showError(result.error)
}
}
}MIT License with Attribution
Copyright (c) 2026 Vedraj Sharma
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice, this permission notice, and attribution to the original
author (Vedraj Sharma / Backpack) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.