Referencing another preference in onPreferenceChange(preference, value) - android

I have two preferences that are related (units and distance)
When units changes I want to convert the distance accordingly. For example if distance is 1610 meters and units changes to miles I want to convert it to 1 mile.
For this I use the code provided by Android studio SettingsActivity code.
But how do I find the distance preference when the units preference changes?
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
...
// I need to address also the distance preference value here
// It is not the preference given in the arguments (units)
// The distance preference is in another preferences fragment
...
}
};

If you can't put it in the listener you can just override the onSharedPreferencesChanged() method and access like this:
SharedPreferences prefs = getSharedPreferences(String str, Context.MODE_PRIVATE)
SharedPreferences.Editor prefEditor = prefs.edit()
editor.putInt("distance", 1610)
editor.apply()
Otherwise use an application context from a singleton.
Update in response to comment:
My apologies for misunderstanding your question. In that case something like:
SharedPreferences prefs = getDefaultSharedPreferences(appContext);
int distance = prefs.getInt("distance", defaultValue);
preference.setSummary(/* whatever value you wish to pass*/);

Related

Storing boolean datas and textview datas in android

I want to store a boolean variable and textview text on the device the app is running, so that even after clearing in recent apps i can use the recent booleab states to make changes remain the same. Or is there any way to get the last state even after clearing the app from the recent apps or onDestroy
You should check out Shared Preferences in Android.
Write to Shared Preferences:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(getString(R.string.saved_high_score), newHighScore);
editor.commit();
Read from Shared Preferences:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
int defaultValue = getResources().getInteger(R.string.saved_high_score_default);
long highScore = sharedPref.getInt(getString(R.string.saved_high_score), defaultValue);
#apelsoczi's answer is essentially correct, but here is a more detailed example which also includes boolean values, and String values, as asked in your question.
First get a reference to your apps Shared Preferences like this:
SharedPreferences prefs = getActivity().getPreferences(Context.MODE_PRIVATE);
Then save your string and your boolean like this:
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(YOUR BOOLEAN KEY, YOUR BOOLEAN);
editor.putString(YOUR STRING KEY, YOUR TEXT VIEW STRING);
editor.commit(); // if commit is not called then data not saved!
To retrieve the values do this:
boolean b = prefs.getBoolean(YOUR BOOLEAN KEY, OPTIONAL DEFAULT VALUE IF ITS NOT FOUND);
String s = prefs.getString(YOUR STRING KEY, OPTIONAL DEFAULT VALUE IF ITS NOT FOUND);
Shared Preferences is a way to store simple key value pairs of data - very useful for settings. For example say you have a value false for your boolean, and you want to save it, so what you do is you pass in a name for it (passing a name is important because you need that name to retrieve the value) and the actual value to save. When you want to retrieve it, you again pass in the name you had assigned it when saving it.

Get current ListPreference label from MainActivity

As explained here:
Get Key, not value, of the ListPreference selection - Possible?
and many other places, it is quite easy to access ListPreferences labels from PreferenceActivity.
What I need to do is to read the label corresponding to the current selected from the main activity.
But I can't find a way.
For example, in my main activity I have
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
I would like to use something like:
ListPreference listPreference = (ListPreference) settings.findPreference("list_of_countries");
And then handle it to get current value and label.
Update 01
I tried to handle another way to retrieve the summary (the name of a country in my example) value which I need to say the customer what he selected. I can't give him the code!
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
String stringSummary = preference.getSummary().toString();
String stringKey = preference.getKey().toString();
if (stringKey.equals("list_of_countries")){
MyActivity.countryName = stringSummary;
}
Nothing to do... the OnPreferenceChangeListener is called.... BEFORE the preference change, i.e., when one item is clicked, so what I succeed to retrieve is just the past summary.
I found no way.

Best Practices for SharedPreferences

A set of questions about SharedPreferences that I was looking for:
What, Why, When?
How does it work inside?
The Best Practice to use it?
Only some of those question were answered here. That's why I made some investigations, and tests.
As I've answered on my own question I've decided to share answer with other people.
I've wrote a little article that can also be found here.
Best Practice: SharedPreferences
Android provides many ways of storing application data. One of those ways leads us to the SharedPreferences object which is used to store private primitive data in key-value pairs.
All logic are based only on three simple classes:
SharedPreferences
SharedPreferences.Editor
SharedPreferences.OnSharedPreferenceChangeListener
SharedPreferences
SharedPreferences is main of them. It's responsible for getting (parsing) stored data, provides interface for getting Editor object and interfaces for adding and removing OnSharedPreferenceChangeListener
To create SharedPreferences you will need Context object (can be an application Context)
getSharedPreferences method parses Preference file and creates Map object for it
You can create it in few modes provided by Context, it's strongly recommended to use MODE_PRIVATE because creating world-readable/writable files is very dangerous, and likely to cause security holes in applications
// parse Preference file
SharedPreferences preferences = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
// get values from Map
preferences.getBoolean("key", defaultValue)
preferences.get..("key", defaultValue)
// you can get all Map but be careful you must not modify the collection returned by this
// method, or alter any of its contents.
Map<String, ?> all = preferences.getAll();
// get Editor object
SharedPreferences.Editor editor = preferences.edit();
//add on Change Listener
preferences.registerOnSharedPreferenceChangeListener(mListener);
//remove on Change Listener
preferences.unregisterOnSharedPreferenceChangeListener(mListener);
// listener example
SharedPreferences.OnSharedPreferenceChangeListener mOnSharedPreferenceChangeListener
= new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
}
};
Editor
SharedPreferences.Editor is an Interface used for modifying values in a SharedPreferences object. All changes you make in an editor are batched, and not copied back to the original SharedPreferences until you call commit() or apply()
Use simple interface to put values in Editor
Save values synchronous with commit() or asynchronous with apply which is faster. In fact of using different threads using commit() is safer. Thats why I prefer to use commit().
Remove single value with remove() or clear all values with clear()
// get Editor object
SharedPreferences.Editor editor = preferences.edit();
// put values in editor
editor.putBoolean("key", value);
editor.put..("key", value);
// remove single value by key
editor.remove("key");
// remove all values
editor.clear();
// commit your putted values to the SharedPreferences object synchronously
// returns true if success
boolean result = editor.commit();
// do the same as commit() but asynchronously (faster but not safely)
// returns nothing
editor.apply();
Performance & Tips
SharedPreferences is a Singleton object so you can easily get as many references as you want, it opens file only when you call getSharedPreferences first time, or create only one reference for it.
// There are 1000 String values in preferences
SharedPreferences first = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
// call time = 4 milliseconds
SharedPreferences second = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
// call time = 0 milliseconds
SharedPreferences third = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
// call time = 0 milliseconds
As SharedPreferences is a Singleton object you can change any of It's instances and not be scared that their data will be different
first.edit().putInt("key",15).commit();
int firstValue = first.getInt("key",0)); // firstValue is 15
int secondValue = second.getInt("key",0)); // secondValue is also 15
When you call get method first time it parses value by key and adds this value to the map. So for second call it just gets it from map, without parsing.
first.getString("key", null)
// call time = 147 milliseconds
first.getString("key", null)
// call time = 0 milliseconds
second.getString("key", null)
// call time = 0 milliseconds
third.getString("key", null)
// call time = 0 milliseconds
Remember the larger the Preference object is the longer get, commit, apply, remove and clear operations will be. So it's highly recommended to separate your data in different small objects.
Your Preferences will not be removed after Application update. So there are cases when you need to create some migration scheme. For example you have Application that parse local JSON in start of application, to do this only after first start you decided to save boolean flag wasLocalDataLoaded. After some time you updated that JSON and released new application version. Users will update their applications but they will not load new JSON because they already done it in first application version.
public class MigrationManager {
private final static String KEY_PREFERENCES_VERSION = "key_preferences_version";
private final static int PREFERENCES_VERSION = 2;
public static void migrate(Context context) {
SharedPreferences preferences = context.getSharedPreferences("pref", Context.MODE_PRIVATE);
checkPreferences(preferences);
}
private static void checkPreferences(SharedPreferences thePreferences) {
final double oldVersion = thePreferences.getInt(KEY_PREFERENCES_VERSION, 1);
if (oldVersion < PREFERENCES_VERSION) {
final SharedPreferences.Editor edit = thePreferences.edit();
edit.clear();
edit.putInt(KEY_PREFERENCES_VERSION, currentVersion);
edit.commit();
}
}
}
SharedPreferences are stored in an xml file in the app data folder
// yours preferences
/data/data/YOUR_PACKAGE_NAME/shared_prefs/YOUR_PREFS_NAME.xml
// default preferences
/data/data/YOUR_PACKAGE_NAME/shared_prefs/YOUR_PACKAGE_NAME_preferences.xml
Android guide.
Sample Code
public class PreferencesManager {
private static final String PREF_NAME = "com.example.app.PREF_NAME";
private static final String KEY_VALUE = "com.example.app.KEY_VALUE";
private static PreferencesManager sInstance;
private final SharedPreferences mPref;
private PreferencesManager(Context context) {
mPref = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
}
public static synchronized void initializeInstance(Context context) {
if (sInstance == null) {
sInstance = new PreferencesManager(context);
}
}
public static synchronized PreferencesManager getInstance() {
if (sInstance == null) {
throw new IllegalStateException(PreferencesManager.class.getSimpleName() +
" is not initialized, call initializeInstance(..) method first.");
}
return sInstance;
}
public void setValue(long value) {
mPref.edit()
.putLong(KEY_VALUE, value)
.commit();
}
public long getValue() {
return mPref.getLong(KEY_VALUE, 0);
}
public void remove(String key) {
mPref.edit()
.remove(key)
.commit();
}
public boolean clear() {
return mPref.edit()
.clear()
.commit();
}
}
Yakiv has mentioned everything about preferences so neatly and nicely. I just want to add one more point. While editing data in shared preferences we usually do
mPref.edit()
which creates a new object of SharedPreferences.Editor type every time which can result in unnecessary objects in memory. So you can maintain a reference to editor object too and save memory and object creation time and corresponding garbage collection time.

android default values for shared preferences

I am trying to understand the SharedPreferences of Android. I am a beginner
and don't know a lot about it.
I have this class I implemented for my app Preferences
public class Preferences {
public static final String MY_PREF = "MyPreferences";
private SharedPreferences sharedPreferences;
private Editor editor;
public Preferences(Context context) {
this.sharedPreferences = context.getSharedPreferences(MY_PREF, 0);
this.editor = this.sharedPreferences.edit();
}
public void set(String key, String value) {
this.editor.putString(key, value);
this.editor.commit();
}
public String get(String key) {
return this.sharedPreferences.getString(key, null);
}
public void clear(String key) {
this.editor.remove(key);
this.editor.commit();
}
public void clear() {
this.editor.clear();
this.editor.commit();
}
}
The thing is that I would like to set default preferences. They would be set when the app is installed and could be modified after by the application and stay persistent.
I heard about a preferences.xml but I don't understand the process.
Could someone help me?
Thanks for you time
Simple, if you want a separate default value for each variable, you need to do it for each one, but on your method:
public String get(String key) {
return this.sharedPreferences.getString(key,"this is your default value");
}
If the variable was never accessed by the user or was never created, the system will set the default value as value and if you or the user changed this value, the default value is ignored. See http://developer.android.com/guide/topics/data/data-storage.html#pref
Directly from the Android Documentation:
The SharedPreferences class provides a general framework that allows
you to save and retrieve persistent key-value pairs of primitive data
types. You can use SharedPreferences to save any primitive data:
booleans, floats, ints, longs, and strings. This data will persist
across user sessions (even if your application is killed).
Could you use the default value parameter of the getX() method?
For example, to get a String called 'username', you could use this:
String username = prefs.getString("username_key", "DefaultUsername");
You can simply define your default values in your Preferences class.
You can store default values in string resource:
<string name="key_name">default_value</string>
and then get it as it follows:
int ResId = context.getResources().getIdentifier(key_name, "string", context.getPackageName()));
prefs.getString(key_name,context.getResources().getString(ResId);

Why cannot save INT to SharedPreferences?

I have a strange problem. I have never had it before. When I try to save int value to my SharedPreference and then restore in other Activity. Value is always 0 even if I save there other value (for example: 1);
private String Number;
private String Profile;
and then saving values (in this case "1") to SharedPreferences in first Activity:
SharedPreferences a = FirstActivity.this.getSharedPreferences("a", MODE_PRIVATE);
SharedPreferences.Editor prefsEditorProfiles = a.edit();
prefsEditorProfiles.putInt(Profile, 1);
prefsEditorProfiles.putInt(Number, 1);
prefsEditorProfiles.commit();
then restore SharedPreferences in other Activity:
SharedPreferences a = SecondActivity.this.getSharedPreferences("a", MODE_PRIVATE);
int ab = a.getInt(Number, 0);
And application shows me 0 instead of 1. My other SharedPreferences works great. I don't know where is the problem.
I'd check what's the value of the Number and Profile variables you declared... you are using their values as keys, so if they have conflicting names, you might be overwriting one setting with the other even though the code looks right.
I'd recommend replacing this:
private String Number;
private String Profile;
With this:
private final String NUMBER = "Number";
private final String PROFILE = "Profile";
And then using those constants when setting/getting your preference value.
Do you ever set a value for
"Number" and "Profile"?
If not then that is your problem -those strings are null.
Please try to use
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
rather than using
SharedPreferences prefs = getActivity().getSharedPreferences ("PREFS_KEY", 0);
when Storing int in shared preference
I've been trying for a while to use putInt like you but it always give an error.
prefsEditorProfiles.putInt(Number, 1);
by just changing a.putInt to a.putString and retrieving it with a.getString I was able to have the correct value.
so, I guess there should be something wrong with putInt and getInt.
Anyway, try that also to have the correct value you need to continue for application.

Categories

Resources