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
Shared Preferences allow you to save and retrieve data in the form of key,value pair. In order to use shared preferences, you have to call a method getSharedPreferences() that returns a SharedPreference instance pointing to the file that contains the values of preferences.
There's no hard limit. The main reason it is not recommended to use SharedPreferences in place of the database is mainly the performance -> shared preferences data is keept in ordinary flat XML file which lacks all the features SQLite offers.
Android stores Shared Preferences settings as XML file in shared_prefs folder under DATA/data/{application package} directory. The DATA folder can be obtained by calling Environment. getDataDirectory() .
SharedPreferences are not intended to store a lot of data, there is no limit per se (since it is an xml file), but for larger sets of data, I would suggest using Room (or SQLite for the older projects). There is also another reason why storing in a database makes more sense.
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With