Skip to content
All posts
June 2, 20264 min read

Android Auto Backup and Data Restore: What Developers Must Know

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.

AndroidDataKotlinUX
Share:

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.


What Auto Backup Does

By default, Android 6.0+ backs up:

  • SharedPreferences files
  • Internal storage files
  • Database files (Room databases)
  • External storage in app-specific directories

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

code
onCreate()
runs.


What Should Be Excluded

Not all data should be backed up:

Must exclude:

  • Auth tokens and session credentials (these expire or are device-specific)
  • FCM tokens (device-specific)
  • Cached data (wastes backup quota, easily re-fetched)
  • Analytics identifiers

Should exclude:

  • Files that are re-downloaded from a server anyway
  • Large media files (use backup quota wisely)
  • Temporary data

Configuring Backup Rules

Create a backup config file:

xml
<!-- 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

code
AndroidManifest.xml
:

xml
<application
    android:allowBackup="true"
    android:fullBackupContent="@xml/backup_rules">

For Android 12+ (API 31+), use the newer format:

xml
<!-- 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>
xml
<application
    android:dataExtractionRules="@xml/data_extraction_rules">

Handling Restore Gracefully

The restore process runs before

code
Application.onCreate()
. Your app must handle the case where restored data is from an older app version:

kotlin
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.


Testing Backup and Restore

Test manually via ADB:

bash
# 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 state

Check that:

  • User preferences are restored
  • The Room database is intact
  • Auth tokens are NOT restored (user needs to log in again)
  • The app handles partial restores gracefully (some data present, some not)

Encrypt Sensitive Backup Data

For data that must be backed up but contains sensitive information:

kotlin
// 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
)

code
EncryptedSharedPreferences
is encrypted before backup and decrypted after restore using the device's Android Keystore — keys don't leave the device.


Implementing a BackupAgent for Custom Control

For more control than the declarative XML rules provide:

kotlin
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:

xml
<application android:backupAgent=".backup.TaskBackupAgent">

The User-Facing Backup UX

Tell users what gets backed up and how to restore it:

kotlin
@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")
        }
    }
}

Takeaways

  • Auto Backup is enabled by default — configure what to include/exclude or you'll back up auth tokens
  • Always exclude session credentials, FCM tokens, and cache files
  • Room migration handles database schema differences on restore automatically
  • Test backup/restore with ADB before every major release
  • Use
    code
    EncryptedSharedPreferences
    for sensitive data that needs to be backed up
Share:
S

Sudarshan 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.

Stay updated

Get new posts on Android, Kotlin, and solo dev straight to your inbox.

Newsletter preferences

Related Apps

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.

Building something? Available for Android dev and QA consulting.

Work with me

Comments — powered by Giscus

Apps tagged with this