Android SharedPreferences Backup Not Working

6.4k views Asked by At

I've been doing my homework on how to backup SharedPreferences in my Android application, especially using reflection to maintain backwards compatibility. At least I've been trying. Unfortunately, none of my code actually ends up creating a backup! This includes forcing adb bmgr commands on the emulator as explained here. So I'm wondering if the community could perhaps help me out and in the process come up with some better documentation?

Here's my code. To keep this as generic as possible for others, I will simply call my application Andy with a package name of com.example.andy.

Android Manifest (excerpt)

<application
    ...
    android:backupAgent="com.example.andy.backupHelper"
    android:restoreAnyVersion="true">
    ...
    <meta-data
        android:name="com.google.android.backup.api_key"
        android:value="GIVEN KEY GOES HERE" />
    ...

backupHelper.java

Note: /data/data/com.example.andy/shared_prefs/com.example.andy_preferences.xml

package com.example.andy;

import android.app.backup.BackupAgentHelper;
import android.app.backup.SharedPreferencesBackupHelper;

public class BlinkyBackup extends BackupAgentHelper {

    static final String PREFS_FILE = "andy_preferences";
    static final String BACKUP_KEY = "AndyPreferencesBackup";

    public void onCreate() {

        SharedPreferencesBackupHelper backupHelper = new SharedPreferencesBackupHelper(this, PREFS_FILE);
        addHelper(BACKUP_KEY, backupHelper);
    }
}

BackupAgentWrapper

package com.example.andy;

import android.app.backup.BackupManager;
import android.content.Context;

public class BackupAgentWrapper {

    private BackupManager wrappedInstance;

    static {

        try {

            Class.forName("android.app.backup.BackupManager");
        }
        catch (Exception e) {

            throw new RuntimeException(e);
        }
    }

    public static void checkAvailable() {}

    public void dataChanged() {

        wrappedInstance.dataChanged();
    }

    public BackupAgentWrapper(Context ctx) {

        wrappedInstance = new BackupManager(ctx);
    }
}

And finally, the commands to initiate a backup during run-time. In my application, this code is run from a class available to my application (not the main activity) which is passed this as a context upon creation and then stored in the private variable mContext.

private void backupData() {

    boolean backupAgentAvailable = false;

    try {

        BackupAgentWrapper.checkAvailable();
        backupAgentAvailable = true;
    }
    catch (Throwable t) {

        // really nothing to do
    }

    if(backupAgentAvailable) {

        BackupAgentWrapper backupWrapper = new BackupAgentWrapper(mContext);
        backupWrapper.dataChanged();
    }
}

To summarize, neither the above function nor the commands below actually backup any data:

$ adb shell bmgr enable true
$ adb shell bmgr backup com.example.andy
$ adb shell bmgr run
1

There are 1 answers

0
Amy On

In your main calling activity (first one that starts in your app), you need to instantiate BackupManager:

BackupManager mBackupManager = new BackupManager(getApplicationContext());

This will tell the backupmanager to look for the backup file and load it.

You need to make sure the preferences file is format "packagename_preferences" eg. andy_preferences. And use the same name when you first saved your preferences. (Very important!)

After the your settings activity saves via apply() or commit(), you need to tell BackupManager that something has changed so include immediately after:

mBackupManger.dataChanged();