MyFamilyTracker
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
Android Auto Backup silently backs up your app's data. When users restore to a new device, they expect their data. Here's how to configure backup correctly, what gets included, what should be excluded, and how to handle restore gracefully.
On this page
User data is one of the top reasons people switch apps when changing devices. "I installed the app on my new phone but lost everything" is a one-star review waiting to happen.
Android Auto Backup handles this for free — if you configure it correctly.
By default, Android 6.0+ backs up:
Backup happens automatically over WiFi when the device is charging and idle. It uses the user's Google account. Up to 25MB per app.
When a user installs your app on a new device, the data is automatically restored before
onCreate()Not all data should be backed up:
Must exclude:
Should exclude:
Create a backup config file:
<!-- res/xml/backup_rules.xml -->
<full-backup-content>
<!-- Include these files -->
<include domain="database" path="app_database" />
<include domain="sharedpref" path="user_settings" />
<!-- Exclude these files -->
<exclude domain="sharedpref" path="auth_prefs" />
<exclude domain="sharedpref" path="fcm_token" />
<exclude domain="file" path="cache" />
<exclude domain="file" path="temp" />
</full-backup-content>Reference it in
AndroidManifest.xml<application
android:allowBackup="true"
android:fullBackupContent="@xml/backup_rules">For Android 12+ (API 31+), use the newer format:
<!-- res/xml/data_extraction_rules.xml -->
<data-extraction-rules>
<cloud-backup>
<include domain="database" path="app_database" />
<exclude domain="sharedpref" path="auth_prefs" />
</cloud-backup>
<device-transfer>
<!-- What transfers via device-to-device transfer (different from cloud) -->
<include domain="database" path="app_database" />
</device-transfer>
</data-extraction-rules><application
android:dataExtractionRules="@xml/data_extraction_rules">The restore process runs before
Application.onCreate()class App : Application() {
override fun onCreate() {
super.onCreate()
// Validate restored data
val restoredVersion = prefs.getInt("data_version", 0)
val currentVersion = BuildConfig.VERSION_CODE
if (restoredVersion > 0 && restoredVersion < currentVersion) {
migrateRestoredData(restoredVersion, currentVersion)
}
// Mark current version
prefs.edit().putInt("data_version", currentVersion).apply()
}
private fun migrateRestoredData(fromVersion: Int, toVersion: Int) {
// Handle schema or data format changes
// Room migration handles database changes automatically
// Custom SharedPreferences migration goes here
}
}Room migrations handle database schema differences automatically when the database is opened after restore — this is why writing and testing migrations is critical.
Test manually via ADB:
# Trigger a backup
adb shell bmgr backup com.yourapp.package
adb shell bmgr run
# Clear app data (simulate new device install)
adb shell pm clear com.yourapp.package
# Restore from backup
adb shell bmgr restore com.yourapp.package
# Reinstall and check stateCheck that:
For data that must be backed up but contains sensitive information:
// Use EncryptedSharedPreferences — it's encrypted at rest and in backup
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val encryptedPrefs = EncryptedSharedPreferences.create(
context,
"encrypted_settings",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)EncryptedSharedPreferencesFor more control than the declarative XML rules provide:
class TaskBackupAgent : BackupAgentHelper() {
override fun onCreate() {
// Back up specific SharedPreferences
SharedPreferencesBackupHelper(
this,
"user_settings",
"app_config"
).also { addHelper("prefs", it) }
// Back up specific files
FileBackupHelper(
this,
"tasks_export.json"
).also { addHelper("files", it) }
}
override fun onRestoreFinished() {
// Called when restore is complete
// Validate and migrate restored data here
validateRestoredDatabase()
}
}Register in Manifest:
<application android:backupAgent=".backup.TaskBackupAgent">Tell users what gets backed up and how to restore it:
@Composable
fun BackupSettingsSection() {
Column {
Text("Data Backup", style = MaterialTheme.typography.titleMedium)
Text(
"Your tasks are automatically backed up to your Google account. " +
"Install the app on a new device and sign in to restore your data.",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
TextButton(onClick = { /* Open backup settings */ }) {
Text("Manage backup settings")
}
}
}EncryptedSharedPreferencesSudarshan Chaudhari
AI Systems Builder / Product Engineer
Bangkok, Thailand
Solo Android developer with 13+ years in QA, building Android apps, AI automation systems, and developer tools at SudarshanTechLabs.
Related Posts
Related Apps
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
Building something? Available for Android dev and QA consulting.
Work with meComments — powered by Giscus
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
ReadPrivate dream journal — structured entry capture, pattern tagging, and optional Claude-powered insight generation. All data stays on-device by default.
ReadWorkout tracker — exercise logging with set/rep/weight history, goal progression, and local Room DB persistence. No account, no cloud sync required.
Read