In my backupagent class I have this:
import android.app.backup.BackupAgentHelper;
import android.app.backup.SharedPreferencesBackupHelper;
public class TheBackupAgent extends BackupAgentHelper {
// The names of the SharedPreferences groups that the application maintains. These
// are the same strings that are passed to getSharedPreferences(String, int).
static final String RECIPE_NAMES = "MyRecipeNames";
static final String TEST = "testSave";
// An arbitrary string used within the BackupAgentHelper implementation to
// identify the SharedPreferencesBackupHelper's data.
static final String MY_PREFS_BACKUP_KEY = "myprefs";
// Simply allocate a helper and install it
public void onCreate() {
SharedPreferencesBackupHelper helper =
new SharedPreferencesBackupHelper(this, TEST);
addHelper(MY_PREFS_BACKUP_KEY, helper);
}
}
I then have code to store a string into the testSave Shared Preferences and request a backup of the preferences:
public void requestBackup() {
BackupManager bm = new BackupManager(this);
bm.dataChanged();
}
public void saveRecipe (View v) {
SharedPreferences prefs = getApplicationContext().getSharedPreferences("testSave", 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("testString", "This is my saved data.");
editor.apply();
requestBackup();
}
I then try to uninstall and reinstall the app and the saved data is gone. I have added the required code to the Manifest but it is not working. Does my app need to be on the play store? I really have no idea why it won't work.
You can test your Backup agent using the bmgr tool which is part of your Android SDK (it's a command in adb). See here how it can be used.
Related
I'm trying to backup my shared preferences file, made a BackupAgentHelper -
public class MyPrefsBackupAgent extends BackupAgentHelper {
// The name of the SharedPreferences file
static final String PREFS = "favorites";
// A key to uniquely identify the set of backup data
static final String PREFS_BACKUP_KEY = "prefs";
// Allocate a helper and add it to the backup agent
#Override
public void onCreate() {
SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, PREFS);
addHelper(PREFS_BACKUP_KEY, helper);
}
on MainActivity -
bm = new BackupManager(getApplicationContext());
public static void requestBackup() {
bm.dataChanged();
}
and when saving the shared preferences calling the requestBackup method -
editor.commit();
MainActivity.requestBackup();
manifest as below-
<application
android:allowBackup="true"
android:backupAgent="MyPrefsBackupAgent">
<meta-data android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAI1Ap52upiK6qBdhShe4Diyzti2CLyayVouApfKQ" />
it is not working, what am I doing wrong?
This question already has answers here:
Determine if Android app is being used for the first time
(15 answers)
Closed 6 years ago.
I am new to android development and and I want to setup some of application's attributes based on Application first run after installation. Is there any way to find that the application is running for the first time and then to setup its first run attributes?
The following is an example of using SharedPreferences to achieve a 'first run' check.
public class MyActivity extends Activity {
SharedPreferences prefs = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Perhaps set content view here
prefs = getSharedPreferences("com.mycompany.myAppName", MODE_PRIVATE);
}
#Override
protected void onResume() {
super.onResume();
if (prefs.getBoolean("firstrun", true)) {
// Do first run stuff here then set 'firstrun' as false
// using the following line to edit/commit prefs
prefs.edit().putBoolean("firstrun", false).commit();
}
}
}
When the code runs prefs.getBoolean(...) if there isn't a boolean saved in SharedPreferences with the key "firstrun" then that indicates the app has never been run (because nothing has ever saved a boolean with that key or the user has cleared the app data in order to force a 'first run' scenario). If this isn't the first run then the line prefs.edit().putBoolean("firstrun", false).commit(); will have been executed and therefore prefs.getBoolean("firstrun", true) will actually return false as it overrides the default true provided as the second parameter.
The accepted answer doesn't differentiate between a first run and subsequent upgrades. Just setting a boolean in shared preferences will only tell you if it is the first run after the app is first installed. Later if you want to upgrade your app and make some changes on the first run of that upgrade, you won't be able to use that boolean any more because shared preferences are saved across upgrades.
This method uses shared preferences to save the version code rather than a boolean.
import com.yourpackage.BuildConfig;
...
private void checkFirstRun() {
final String PREFS_NAME = "MyPrefsFile";
final String PREF_VERSION_CODE_KEY = "version_code";
final int DOESNT_EXIST = -1;
// Get current version code
int currentVersionCode = BuildConfig.VERSION_CODE;
// Get saved version code
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
int savedVersionCode = prefs.getInt(PREF_VERSION_CODE_KEY, DOESNT_EXIST);
// Check for first run or upgrade
if (currentVersionCode == savedVersionCode) {
// This is just a normal run
return;
} else if (savedVersionCode == DOESNT_EXIST) {
// TODO This is a new install (or the user cleared the shared preferences)
} else if (currentVersionCode > savedVersionCode) {
// TODO This is an upgrade
}
// Update the shared preferences with the current version code
prefs.edit().putInt(PREF_VERSION_CODE_KEY, currentVersionCode).apply();
}
You would probably call this method from onCreate in your main activity so that it is checked every time your app starts.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkFirstRun();
}
private void checkFirstRun() {
// ...
}
}
If you needed to, you could adjust the code to do specific things depending on what version the user previously had installed.
Idea came from this answer. These also helpful:
How can you get the Manifest Version number from the App's (Layout) XML variables?
User versionName value of AndroidManifest.xml in code
If you are having trouble getting the version code, see the following Q&A:
How to get the build/version number of your Android application?
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.UUID;
import android.content.Context;
public class Util {
// ===========================================================
//
// ===========================================================
private static final String INSTALLATION = "INSTALLATION";
public synchronized static boolean isFirstLaunch(Context context) {
String sID = null;
boolean launchFlag = false;
if (sID == null) {
File installation = new File(context.getFilesDir(), INSTALLATION);
try {
if (!installation.exists()) {
launchFlag = true;
writeInstallationFile(installation);
}
sID = readInstallationFile(installation);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return launchFlag;
}
private static String readInstallationFile(File installation) throws IOException {
RandomAccessFile f = new RandomAccessFile(installation, "r");// read only mode
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
f.close();
return new String(bytes);
}
private static void writeInstallationFile(File installation) throws IOException {
FileOutputStream out = new FileOutputStream(installation);
String id = UUID.randomUUID().toString();
out.write(id.getBytes());
out.close();
}
}
> Usage (in class extending android.app.Activity)
Util.isFirstLaunch(this);
There is no way to know that through the Android API. You have to store some flag by yourself and make it persist either in a SharedPreferenceEditor or using a database.
If you want to base some licence related stuff on this flag, I suggest you use an obfuscated preference editor provided by the LVL library. It's simple and clean.
Regards,
Stephane
I'm not sure it's good way to check it. What about case when user uses button "clear data" from settings? SharedPreferences will be cleared and you catch "first run" again. And it's a problem. I guess it's better idea to use InstallReferrerReceiver.
Just check for some preference with default value indicating that it's a first run. So if you get default value, do your initialization and set this preference to different value to indicate that the app is initialized already.
The following is an example of using SharedPreferences to achieve a 'forWhat' check.
preferences = PreferenceManager.getDefaultSharedPreferences(context);
preferencesEditor = preferences.edit();
public static boolean isFirstRun(String forWhat) {
if (preferences.getBoolean(forWhat, true)) {
preferencesEditor.putBoolean(forWhat, false).commit();
return true;
} else {
return false;
}
}
There's no reliable way to detect first run, as the shared preferences way is not always safe, the user can delete the shared preferences data from the settings!
a better way is to use the answers here Is there a unique Android device ID? to get the device's unique ID and store it somewhere in your server, so whenever the user launches the app you request the server and check if it's there in your database or it is new.
This might help you
public class FirstActivity extends Activity {
SharedPreferences sharedPreferences = null;
Editor editor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
sharedPreferences = getSharedPreferences("com.myAppName", MODE_PRIVATE);
}
#Override
protected void onResume() {
super.onResume();
if (sharedPreferences.getBoolean("firstRun", true)) {
//You can perform anything over here. This will call only first time
editor = sharedPreferences.edit();
editor.putBoolean("firstRun", false)
editor.commit();
}
}
}
SharedPreferences mPrefs;
final String welcomeScreenShownPref = "welcomeScreenShown";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
// second argument is the default to use if the preference can't be found
Boolean welcomeScreenShown = mPrefs.getBoolean(welcomeScreenShownPref, false);
if (!welcomeScreenShown) {
// here you can launch another activity if you like
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(welcomeScreenShownPref, true);
editor.commit(); // Very important to save the preference
}
}
In one of my views the user makes a selection. I want to store that selection in a variable I can use across all views so it can be used for further database queries such as "bookId".
How can I make "bookId" a global variable that is set on one view and can be accessed across the other views when needed?
----- Edit: What I'm attempting to do based on comments and answers -----
On my main activity where the SharedPreference is stored I have this before the onCreate:
public static final String PREFS_NAME = "myPrefs";
SharedPreferences settings;
Integer bookId;
In my onCreate I've done this:
settings = getSharedPreferences(PREFS_NAME, 0);
bookId = settings.getInt("bookId", 0);
After the button press I'm storing a custom attribute and attempting to set bookId in the SharedPreference:
SharedPreferences.Editor editor = settings.edit();
editor.putInt("bookId",bookKey);
editor.commit();
In another view I'm attempting to get the bookId from the SharedPreference and, for testing purposes, I'm trying to set the stored value to a textView just to make sure it stored and carried over correctly.
Before the onCreate on the second view:
public static final String PREFS_NAME = "myPrefs";
SharedPreferences settings;
Inside the onCreate:
settings = getSharedPreferences(PREFS_NAME, 0);
Integer bookId = settings.getInt("bookId", (Integer) null);
tempBookTextView = (TextView) findViewById(R.id.tempBookTextView);
tempBookTextView.setText(bookId);
I have a two questions, how does this look so far? Any ideas why the app crashes when I use
Integer bookId = settings.getInt("bookId", (Integer) null);
Instead of using global variable to access variable value through out the app try using SharedPreferences.
sample activity:
public class Book extends Activity {
public static final String PREFS_NAME = "MyPrefsFile";
String mBookId = null;
#Override
protected void onCreate(Bundle state){
super.onCreate(state);
. . .
// Restore preferences
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
mBookId = settings.getString("book_id", null);
// use book_id;
}
#Override
protected void onStop(){
super.onStop();
// We need an Editor object to make preference changes.
// All objects are from android.context.Context
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString("book_id", mBookId);
// Commit the edits!
editor.commit();
}
}
Preferences are typically created private and can be accessed via all over the application components. Sharing data with other application with world readable or writable preference file is rarely used, as the external component would need to know the exact filename and location of the file.
To kill the spirit of encapsulation,
public class Globals {
public static int x;
public static int y;
}
and later
if (Globals.x == 0) { ... }
But please don't do exactly that, any class can contain static variables, find a class responsible for the value you want to store.
OTOH, android processes may be restarted when you don't expect it, in which case all the variables will be reset. So it's better to use shared preferences and if they don't work as expected (which I have seen in at least one release of Android), store the instance of shared preferences in a static variable.
You can use Shared Preferences
Saved at once !
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(ProjectAct.this).edit();
editor.putInteger(StaticVariable.BOOKID, "1");
p.get("contract_no"));
editor.commit();
Then call from anywhere like that
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
int book_id = prefs.getInteger(StaticVariable.BOOKID,null);
See more at How to use SharedPreferences in Android to store, fetch and edit values
If i set a sharedpreference in one activity, why does the other one has different preferences? context changed? (but i se use application context!)
Here is my code
MyApp appState = ((MyApp)this.activity.getApplicationContext());
appState.setDittaSelezionata( (int) itemId);
....
MyApp appState = ((MyApp)this.getApplicationContext());
int ditta_id_selezionata = appState.getIdSomething();
And
public class MyApp extends Application implements Parcelable {
private SharedPreferences getSharedPrefs()
{
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
//SharedPreferences settings = this.getSharedPreferences(MyApp.PREFS_NAME, this.MODE_PRIVATE);
return settings;
}
public int getIdSomething() {
SharedPreferences settings = this.getSharedPrefs();
return settings.getInt("ditta_id_selezionata", 0);
}
public void setDittaSelezionata(final int ditta_selezionata) {
SharedPreferences settings = this.getSharedPrefs();
SharedPreferences.Editor editor = settings.edit();
editor.putInt("ditta_id_selezionata", ditta_selezionata);
// Commit the edits!
editor.commit();
}
...
How can i make global preferences that are shared among all activities android 3.2? is there something android provides or i have to code a save to file/open to file and add it for each activity onStop() / onCreate() ?
try this.
private static final String APP_PREF = "application_preference";
private static final String DITTA = "ditta_id_selezionata";
public class MyApp extends Application implements Parcelable {
private SharedPreferences getSharedPrefs(){
SharedPreferences settings = getApplicationConext().getSharedPreferences(APP_PREF, Context.MODE_PRIVATE);
return settings;
}
public int getIdSomething() {
SharedPreferences settings = this.getSharedPrefs();
return settings.getInt(DITTA, 0);
}
public void setDittaSelezionata(final int ditta_selezionata) {
SharedPreferences settings = this.getSharedPrefs();
SharedPreferences.Editor editor = settings.edit();
editor.putInt(DITTA, ditta_selezionata);
// Commit the edits!
editor.commit();
}
I think you had done something similar but commented it. This should keep your preferences constant throughout the app over the activities. As you see here, you make sure that the same preference file is being read and written to.
Shared Preferences ARE persisted across activities. If you're seeing different data then I expect the values are not being saved. I don't think the issue is the reading of the data, but the writing, so check your preference writing code.
I have a problem with SharedPrefences and initializations.
My application has a login where you insert an user, and for that user, you have a specific preferences... so, I need to save preferences according to the user to load it later.
I though that SharedPrefences would be the solution, and it really is I think, but I have a problem to initialize they: I have an Activity class called Options. It has static functions that returns the value of the options... but I have a problem, I call that functions before I have create that activity (intent), so I think that the functions are returning the last value that the last user has selected on the options...
How can I load the options before that calls?
I though to use first of all an Intent sending extra data with the user and in onCreate() of the Options, initialize they, but if I make an intent, then the Options will appear (xml will load).
Any help pls?
Try something like this.... adding methods for each variable you want to save.
public class PreferenceManager {
private static PreferenceManager self;
private SharedPreferences preferences = null;
private SharedPreferences.Editor editor = null;
private boolean isInitialised = false;
private static final String MY_PREFERENCE = "mypreferencekey";
private String myPreference = null;
public void initialise(Context context) {
if (!isInitialised) {
preferences = context.getSharedPreferences("MyPreferencePlace", Context.MODE_PRIVATE);
editor = preferences.edit();
loadPreferences();
isInitialised = true;
}
}
public static PreferenceManager getInstance() {
if (self == null) {
self = new PreferenceManager();
}
return self;
}
private PreferenceManager() {
}
public void setPreference(String newPreferenceValue) {
this.myPreference = newPreferenceValue;
savePreferences();
}
public String getPreference(){
return myPreference;
}
private void savePreferences() {
editor.putString(MY_PREFERENCE, myPreference);
editor.commit();
}
private void loadPreferences() {
myPreference = preferences.getString(MY_PREFERENCE, null);
}
}
All the SharedPreferences need is a context and it can be initialized. As your application always opens an Activity to start with, you always have a context to work with.
I would advise you to wrap the SharedPreferences in a Singleton class and just pass a context as parameter at the getInstance method. You should be able to access your shared preferences at all Activities this way.
I work on the dependency injector for android, and content of shared preferences is already injectable into annotated fields ( see: https://github.com/ko5tik/andject , PreferenceInjector). Patches and improvements are welcome. Saving of preferences comes soon