Reputation: 389
Am new to android and currently while working on Preferences, I had the following doubt, API says the following: http://developer.android.com/reference/android/content/SharedPreferences.html Modifications to the preferences must go through an SharedPreferences.Editor object to ensure the preference values remain in a consistent state
But in another link, the following code style is followed:
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(KEY_PREF_SYNC_CONN)) {
Preference connectionPref = findPreference(key);
connectionPref.setSummary(sharedPreferences.getString(key, ""));
}
}
So is it fine to edit a Preference obj without using edit and commit??
EDIT
Problem was I was not able to set Default values in summary Here is the complete code that I used to fix this problem....
public class Settings extends PreferenceActivity implements
OnSharedPreferenceChangeListener {
//initializations
protected void onCreate(Bundle savedInstanceState) {
bla bla
PreferenceManager.setDefaultValues(getBaseContext(), R.xml.preferences, false);
addPreferencesFromResource(R.xml.preferences);
keys = getResources().getStringArray(R.array.prefKeys);
p = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
//Gets the keys of the preferences
for (int i = 0; i < keys.length; i++) {
setSummary(p, keys[i]);
}
}
//Listener to detect changes
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
Preference p = findPreference(key);
if (p instanceof EditTextPreference) {
p.setSummary(sharedPreferences.getString(key,(String) p.getSummary()));
}
else if (p instanceof ListPreference) {
p.setSummary((String) ((ListPreference) p).getEntry());
}
}
//First time initialization
private void setSummary(SharedPreferences sharedPreferences, String key) {
Preference p = findPreference(key);
if (p instanceof EditTextPreference) {
//This was the mistake I did
//p.setSummary(sharedPreferences.getString(key,(String) p.getSummary()));
p.setSummary(((EditTextPreference) p).getText());
}
else if (p instanceof ListPreference) {
//This was the mistake I did
//p.setSummary((String) ((ListPreference) p).getEntry());
p.setSummary((String) ((ListPreference) p).getEntry());
}
}
}
Upvotes: 1
Views: 1602
Reputation: 11518
You are talking about two different topics there champ.
First, you have the SharedPreferences object, which as the guide states must and can only be edited through a SharedPreferences.Editor object. See the following bit:
/**
* This function writes the user's current score to persistent storage via {@link SharedPreferences}
* @param key The Key to store the value with, this is the same value that must be used to retrieve the preference value at a later time.
* @param value The Actual Value to store for the supplied key.
*/
private void saveScore (String key, int value) {
//First, get the instance of the SharedPreference, this is a default file that has the Package name as it's own file name.
SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
//Get an instance of an editor by calling .edit()
SharedPreferences.Editor mEditor= mPreferences.edit();
//stage the changes
mEditor.putBoolean("your-key", true || false);
//Call commit to persit changes
mEditor.commit();
}
When you talk about onSharedPreferenceChanged
, that is simply an interface that allows you to know when a SharedPreference gets changes, it doesn't actually write/edit the preference file.
The onSharedPreferenceChanged
interface is particuarly helpful when used alongside a PreferenceActivity
or a PreferenceFragment
to make changes to the User interface if needed, based on the changes to the current user preferences.
See this for instance:
public class Settings extends PreferenceActivity {
/**
* The Key to be used to access the preference. This should be defined already on your preferences.xml file
*/
public static final String KEY_CURRENT_THEME = "pref_current_theme";
/**
* The instance of the Theme Preference.
*/
Preference mThemePreference;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Find the preference
mThemePreference = findPreference(KEY_CURRENT_THEME);
//Set the listener
mThemePreference.setOnPreferenceChangeListener(mOnPreferencedChanged);
//Call onPrerenceChanged to begin with in case the settings may have changed
//The system will call this later each time the preference gets updated by the user via Settings
mChangeListener.onPreferenceChange(
mThemePreference,
PreferenceManager.getDefaultSharedPreferences(
mThemePreference.getContext()).getString(mThemePreference.getKey(),
""));
}
private OnPreferenceChangeListener mOnPreferencedChanged = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Resources mResources = preference.getContext().getResources();
//You can check to see what change in two different ways.
//a) you can check the TypeOf the preference that changed.
if (preference instanceof CheckBoxPreference) {
//If the preference that changes is a CheckBoxPreference, then do such and such changes.
}
//Or, you can check if it's a specific preference that changed
if (preference == mThemePreference) {
//If the preference is actually the Theme Preference itself, then do such and such changes.
}
//Always return true so that the preference value change can be persisted, false otherwise.
return true;
}
};
I hope this helps! :)
Edit
Your question: Where is the preference file stored, and how do I access it?
Where? The file that is created/edited via a PreferenceActivity
, a PreferenceFragment
or by calling PreferenceManager.getDefaultSharedPreferences(context)
is stored at /data/data/your.package.name/shared_prefs/your.package.name_preferences.xml
However, where this file is stored should be irrelevant to you as a developer, since you should only access this file by making a call to PreferenceManager.getDefaultSharedPreferences(context)
For instance, say you have a CheckBoxPreference
that defines whether to use Holo Dark or Holo Light as your activity's theme, say, that looks something like this:
Each Time the user Checks or unchecks the preference, the system will persist that change to the default preference file discussed above for you, there is no need for you to save this change manually, since it does it for you already.
If you want to make more than just persist the change, you can intercept the event by implementing the OnPreferenceChangeListener
that I provided above, and you can even tell the system whether or not it should persist the change by returning true
to persist, or false
to not persist.
How to access it? In order to know what is the current value of the theme preference, say to actually apply UI changes based on the preference value, you can do the following:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//We update the preference dependent values **before** setting the content view
updatePrefDependentValues();
setContentView(R.layout.activity_empty_container);
}
private void updatePrefDependentValues() {
//get the instance of the SharedPreference Object.
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
//Update the boolean value based on the current preferences
//The second parameter to getBoolean is a default value, we want false as default value.
mUseDarkTheme = mPreferences.getBoolean("whatever_key_you_set_for_this_preference", false);
if (mUseDarkTheme) {
//If we are using dark theme, set such theme.
setTheme(R.style.DarkTheme);
}
else if (!mUseDarkTheme) {
//If we are **not** using dark theme, set light theme.
setTheme(R.style.LightTheme);
}
}
Let me know if you have further questions.
Edit number three:
You don't need to access the file on Eclipse, I imagine you want to open it to set default values, well, that is what the preferences.xml file is for.
Imagine you will have a few things on Settings, you have a CheckBoxPreference
for the Theme, just as above, you have another CheckBoxPreference
for enabling and disabling Background Sync, and you have a ListPreference
for storing how often to sync in the background.
All of the above settings must be declared with a default value, in the case of a CheckBoxPreference
, the default value is a boolean, either true or false, and in the case of a ListPreference
the default value is whatever you want it to be, depending on the values you supply to the entries.
For instance, here's a very simple preference.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Preference Categories are a good way to keep your Settings organized -->
<!-- android:key represents a String that is used to write and read from the preference file stored at /data/data/your.package.name -->
<PreferenceCategory
android:title="@string/pref_title_general"
android:key="pref_title_general"
>
<!-- CheckBoxPreference are pretty simple, they only need a title, a key and a default value -->
<!-- android:key is a MUST in each Preference as otherwise the system cannot persist changes to it. -->
<!-- android:key would be the same String you pass a "Key"
when calling mPreference.getBoolean(String key, Boolean default) from the Activity -->
<CheckBoxPreference
android:title="@string/pref_title_enable_dark_theme"
android:key="pref_key_dark_theme"
android:defaultValue="false"
/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/pref_title_sync_preferences"
android:key="pref_title_navigation"
>
<CheckBoxPreference
android:title="@string/pref_title_enable_background_sync"
android:key="pref_key_background_sync"
android:defaultValue="false"
/>
<!-- ListPreference are a bit more complex, they require a Key to persist the changes
android:entries represents the values displayed to the user when setting the preference
android:entryValues represent the values that will be persisted, this array is the same size as the entries one.
For instance, an Entry could be "Every 10 Minutes", and the entry value would be: "10" or "ten"
This also requires a default value, which in this case MUST be a part of the entryValues array.
-->
<ListPreference
android:title="@string/pref_title_sync_frequency"
android:key="pref_key_sync_frequency"
android:entries="@array/pref_entries_sync_frequency"
android:entryValues="@array/pref_entries_values_sync_frequency"
android:defaultValue="@string/pref_default_sync_frequency"
/>
</PreferenceCategory>
Again, if you use a PreferenceActivity
or PreferenceFragment
correctly, the changes the user makes will be persisted, and there's really nothing you should do to make the changes be there the next time the user accesses settings.
If you want to know more about Settings and Preferences, see the following: http://developer.android.com/guide/topics/ui/settings.html
Now, if what you want to do is persist other data, that may not be displayed on a PreferenceActivity
or PreferenceFragment
, say a user name, or an email address, then you can persisted as stated above via the saveScore example.
Here's a link with more info on SharedPreferences: http://developer.android.com/training/basics/data-storage/shared-preferences.html
Upvotes: 1
Reputation: 152787
Preference
and SharedPreferences
are not the same. However, they are often used together.
Preference
is a UI class for displaying and editing preferences by the user.
SharedPreferences
is a non-UI class for persisting application settings. To make changes to these settings, you obtain a SharedPreferences.Editor
instance with edit()
and then store the changes with commit()
.
Typically, Preference
values are stored in SharedPreferences
.
Upvotes: 1