Why not use PreferenceManager.setDefaultValues(readAgain = true) in all apps? - android

Android Settings guide suggests to call PreferenceManager.setDefaultValues() with readAgain = false. In this case the defaults from preferences.xml are only loaded once when the app is launched for the 1st time (or after "clear data").
If a new preference is added, its android:defaultValue is not loaded, I checked.
So why nobody uses readAgain = true? Google results:
10 "PreferenceManager.setDefaultValues(this, R.xml.preferences, true)"
60k "PreferenceManager.setDefaultValues(this, R.xml.preferences, false)"
What are the drawbacks?

This parameter is typically set to false because this one ensure that default values are only set for shared preferences that are not initialized. Keeping this to false will ensure that you do not override the setting modified by the user. This field is useful if you allow your user to re-set all app settings to the initial app settings.

Related

How can I add a watch for getSharedPreferences (Where is it stored?)

I've been testing out a few sample weather app code projects looking for a 3 to 5 day forecast one that easily compiles in android studio. I can't find a simple one that is at my level of understanding yet but working with one that might help. (If anyone knows of a simple up to date weather forecast app then note it below please)
First line in question.
if (getSharedPreferences(KEY_PREF, 0).getBoolean(KEY_PREF, true)
&& servicesConnected())
From:
private static final String KEY_PREF = "firstrun";
if (getSharedPreferences(KEY_PREF, 0).getBoolean(KEY_PREF, true)
&& servicesConnected()) {
if (getSharedPreferences(KEY_PREF, 0).getBoolean(KEY_PREF, true)
&& servicesConnected()) {
// get current city lat lon
buildGoogleApiClient();
mClient.connect();
CommonUtils.showToast("Retrieving your current location...");
// this will be done one time only
getSharedPreferences(KEY_PREF, 0).edit()
.putBoolean(KEY_PREF, false).apply();
} else if (savedInstanceState == null) {
if (DBHelper.getInstance().getCityCount() == 0) {
// called only if the cities array is empty too add a city
getSupportFragmentManager()
.beginTransaction()
.add(R.id.container, new AddCityFragment(),
AddCityFragment.class.getSimpleName()).commit();
} else {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new WeatherFragment()).commit();
}
}
}
According to developer.android.com
boolean getBoolean (String key, boolean defValue)
Parameters: (1) String key: The name of the preference to retrieve. (2) defValue boolean: Value to return if this preference does not exist.
My original questions asked:
What exactly is getBoolean doing?
The documentation doesn't say what mode 0 means in the 2nd parameter of getSharedPreferences (String name, int mode). Any idea what?
How can I add a watch for getSharedPreferences to Android Studio's debugging
The Solution that I deduced with the help of you guys:
getSharedPreferences(KEY_PREF, 0) is looking for a KEY_PREF preference file on the android device. It returns an object to it which allows us to use getBoolean to determine if there is a key inside it with the same name. In this case it was looking for a "firstrun" file which doesn't exist during first run of the app on the actual android devices storage (saved as cache). Since the key didn't exist on the first run it sets the boolean value as true and continues running inside the if statement. If the key "firstrun" existed and it was set to false then it would return false and skip executing inside that part of the if statement.
Mode 0 is MODE_PRIVATE = the default mode, where the created file can only be accessed by the calling application (or all applications sharing the same user ID).
When I was trying to debug the issue I noticed that I can add a debugger watch for getSharedPreferences(KEY_PREF, 0) and drill inside the resulting preference file from withing the debugger to see that the mMap parameter to the SharedPreferences object creates a "firstrun" key with the value of "false". It was a first for me to see how it adds this value.
I also found a cool plug-in for android studio for mac and windows which is faster than going into the android device or virtual device and clearing the apps cache. It's called ADB idea and used with the CTRL+ALT+SHIFT+A hotkey combo.
Thanks everyone!
SharedPreference is just a way to store some small-size data.
1) Meaning why would it return true if it doesn't exist?
You can have it return false if you want. That's just the default value for that key. You should set default to true/false depending on the data logic. For their particular case, setting the default true for that key goes with their app logic.
For example, AFAIK android sdk doesn't provide us with any apis that would say that app is running for the first time. So, to know that if the app is running for the first time or not, you could get the boolean value for a key like "is_first_run" and have the default value be true. If the app is run for the first time, then this value would not exist in shared preference because you've not set it yet. So, the default value true makes sense. And if you find it to be true then set it to false, so that the next time the app is run, it'll return false. If you clear the cache, the value will be true once again because the cache is destroyed and the variable no longer exists.
2) question what is operating mode 0 for SharedPreferences getSharedPreferences (String name, int mode)
Operating mode 0 is just the PRIVATE_MODE. The developer should have used the variable instead of just setting it to zero. Their are multiple modes for the sharedpreference. You can look into the docs for more. Private mode means that this data can be accessed by this application only.
3) How can I add a watch for getSharedPreferences (Where is it stored?)
Not sure what you mean by adding a watch. Are you talking about an event listener on the sharedPreference? AFAIK, you can't do that. Also, shared preference is stored in app's cache directory which can be /data/app/appname/cache or something else (idk for sure)
Shared Preferences store data till you delete and reinstall the app
getBoolean( "this is the key" , true);
if getBoolean returns null then this whole statement evaluates to true
If getBoolean( "this is the key" , false);
This means that if it returns null then evaluate it to false
Meaning why would it return true if it doesn't exist?
This was your question right ?
It is the coder's choice to make it true or false like
At first when user has logged in when you did not even touch sharedPreferences
then it would probably return the second argument
like
if(SharedPreferences.getBoolean('isUserOld' , true)){
Toast.make( Context , "Welcome to Our App" , Long).show()
}
Here it is checking whether user is old or not
If user is not old then if blocks gets executed because the second param returns true
And this indicates that a new user has logged in

Shared preferences isn't gettingBoolean properly

I'm trying to load boolean value from Shared Preferences. On first launch it should be TRUE as I have never saved it to Shared Preferences. However, I'm somehow getting false.
See code below.
settings = context.getSharedPreferences(SAVED_PREFERENCES, 0);
isFirstLaunch = settings.getBoolean(FIRST_LAUNCH, true);
Log.d(TAG, "loadIsFirstLaunch: " + isFirstLaunch);
p.s. I haven't saved FIRST_LAUNCH value in shared preferences before 100%.
UPD1 I've double checked with empty project - code is working properly. Shared Preferences use Boolean class, not boolean primitive type. So it isn't the case that boolean by default is false. Also according to debug my shared preferences somehow includes FIRST_LAUNCH value by the time it is launched. So looking at how it got there.
UPD2 I finally stuck. Removed all mentionings of FirstLaunch, but it still somehow appears in SharedPreferences when another call to read other values is made. So question is - how can I get rid of saved value in Shared preference.
http://take.ms/Rr0Xf
UPD3 I've changed name to my saved preferences file and it worked. So problem was that SOMEHOW device was keeping info for saved preferences even after application clean install. PFM.
I can't commnet to your question because of less points So, if you're 100 sure that you didn't set any value to FIRST_LAUNCH, then 1. try to clean the app's data 2. Can you please provide the full source code
And #miller what if there are more than one sharedpreferences
Its because the boolean value by default sets its value to false .. it only takes the true value when there is empty value returned from the shared preference , but boolean value must have a value either true or false...it doesn't support null value.
so what you need to do is set the boolean value of the session to true programatically in the class before loading and then get the value from the session
So finally I found the problem and solution.
In android M and above versions Google keeps application backups in google driver, that's why even after reinstall shared preferences were restoring. I've disabled backups.
project manifest file under Application section set android:allowBackup="true" to false.

Default SharedPreference value being set weirdly

Say in version 1, I do not have this SharedPreference value.
Now, I manually updated the APK to version 2. After that I re-boot my phone. However, when I adb pull the .xml file that was created, it is set as false.
SharedPreference as below:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean optimus = prefs.getBoolean("prime", true);
I thought getBoolean sets the value as the default value it it does not exist (which doesn't. It's the first time it's being initialized).
This xml file is completely new and it did not exist before.
Why does this happen? Is there some native Android behavior I'm missing?
If you update the application (without first uninstalling), it will keep the preference that has been set in the previous version. So if "prime" was set to false previously in the old version then it will still be false in the new version, unless the old version is uninstalled first, before installing the new one. Uninstalling would delete the old preferences xml file.
Also, rebooting your phone will not clear preferences.
getBoolean(key, defaultValue) returns the defaultValue programmatically when this Java statement is executed if there is no value in the XML file for this key, so you won't find the defaultValue in the XML file you're talking about unless you call prefs.edit().putBoolean(key, myValue).apply()
Edit: In other words, prefs.getBoolean("prime", true) will always return true UNLESS you once called prefs.edit().putBoolean("prime", false).apply() at any point in time (from the time you installed the first version of the application and assuming you never uninstalled it or cleared data).

PreferenceManager.setDefaultValues readAgain parameter and new preferences

I'm using PreferenceManager.setDefaultValues(context,R.xml.preferences,false) to set the default values of the preferences in my application and I've noticed that if I add a new preference then my PreferenceFragment does not show a default value for it, even if it is set in the preferences.xml..
Is this due to the fact that I specify readAgain as false?
I know I can simply try-and-see, but I just wanted to be sure that the readAgain is meant for this purpose, i.e. re-read the default values not to re-set user settings but to set the new properties' default values. If this is exactly the purpose of the readAgain flag, then can you give me a reason not to always set readAgain to true, given that it does not reset user preferences?
Setting the readagain flag to true will ensure that all unset-default values are set again. That's the summary.
Setting the readagain will cause extra overhead since basically it means that, the code will go through the entire SharedPreference once more to check them. With the readAgain false,all it does is to check whether the file ( has_set_default_values.xml ) which is used as a marker for setting default values is present or not.
In any case, It won't set any values that are already set .

Load preferences according to application mode

I would like to load XML preferences according to application mode, like DEBUG, TEST or PRODUCION where different values are entered for the same keys.
Additionally the preferences default values must be set on start up.
This will allow easy testing in different circumstances.
Which is the best way to accomplish this.
PS: I don't want the user to see or have the option to change this settings.
You can add PreferenceCategory with say testCategory key and place all test related preferences tehere.
And if current mode is PRODUCTION, then just remove this testCategory from preferences in onCreate() function:
if(isProduction())
{
Preference testCategory = findPreference("testCategory");
getPreferenceScreen().removePreference(testCategory);
}

Categories

Resources