Listening for Preference change - android

I am implementing Preferences according to Google tutorial. But I do not receive changes in my event listener. I realized that it is because I unregister the listener in onResume, like Google recommended. Did I miss something or is google advice wrong?
For proper lifecycle management in the activity, we recommend that you
register and unregister your
SharedPreferences.OnSharedPreferenceChangeListener during the
onResume() and onPause() callbacks, respectively:
public class MyActivity extends AppCompatActivity implements
NavigationView.OnNavigationItemSelectedListener,
SharedPreferences.OnSharedPreferenceChangeListener {
public boolean onOptionsItemSelected(MenuItem item) {
case R.id.action_level: {
Intent intent = new Intent();
intent.setClass(this, GamePreferenceActivity.class);
startActivity(intent);
return true;
...
protected void onPause() {
Log.d(logTag, "onPause()");
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
sharedPref.unregisterOnSharedPreferenceChangeListener(this);
super.onPause();
}
protected void onResume() {
Log.d(logTag, "onResume()");
super.onResume();
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
sharedPref.registerOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(MyPreferenceActivity.KEY_COMPLEXITY)) {
String value = sharedPreferences.getString(key, "EASY");
logic.setLevel(Level.valueOf(value));
restartGame(null);
}
}
My activity starts an intent with preferences activity.
public class GamePreferenceActivity extends Activity {
public static final String KEY_COMPLEXITY = "prefGameComplexity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new GamePreferenceFragment())
.commit();
PreferenceManager.setDefaultValues(this, R.xml.game_prefs, false);
}
}
public class GamePreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.game_prefs);
}
}

You need to call commit() or apply() to save changes in preferences.
Example:
// Access the default SharedPreferences
SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(this);
// The SharedPreferences editor - must use commit() to submit changes
SharedPreferences.Editor editor = preferences.edit();
// Edit the saved preferences
editor.putString("UserName", "JaneDoe");
editor.putInt("UserAge", 22);
editor.commit(); //or editor.apply() -- Read below for difference between these two
Difference between commit() and apply():
apply() was added in 2.3, it commits without returning a boolean indicating success or failure.
commit() returns true if the save works, false otherwise.
apply() was added as the Android dev team noticed that almost no one took notice of the return value, so apply is faster as it is asynchronous.

This is the way how I register and unregister listener:
#Override
public void onResume() {
super.onResume();
// Register the listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
super.onPause();
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
Show us your onSharedPreferenceChanged, maybe you made mistake there.

Related

PreferencesActivity trigger OnSharedPreferencesChange twice

I have a Preference Activity that implement the changed preference listener in the following way:
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceManager
.getDefaultSharedPreferences(getApplicationContext())
.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onDestroy(){
super.onDestroy();
PreferenceManager
.getDefaultSharedPreferences(getApplicationContext())
.unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d("TAG", "preference " + key + " changed");
}
}
When I change a value of the Preferences the listener is triggered twice which I don't understand why. Accordinly to the documentation it should be triggered only when the new value is persisted.
This is my log:
12-17 13:31:24.434 27391-27391/xxx D/> TAG: preference ABC
12-17 13:31:24.435 27391-27391/xxx D/> TAG: preference ABC
And there is 1 millisecond between the two times the listener is trigged. How can I fix this? It is wrong because I change the value only once and I am receiving two calls which is not supposed to happen
Found the problem so instead of deleting the question I'll rather answer.
The listener must be registered in a different location:
#Override
public void onResume(){
super.onResume();
PreferenceManager
.getDefaultSharedPreferences(getApplicationContext())
.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause(){
super.onPause();
PreferenceManager
.getDefaultSharedPreferences(getApplicationContext())
.unregisterOnSharedPreferenceChangeListener(this);
}

My shared pref listener wont' listen

I have followed the Google dev docs and come up with the following shared preference activity:
public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
public static class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// TODO Auto-generated method stub
Toast.makeText(this, "Pref changed", Toast.LENGTH_SHORT).show();
}
#Override
protected void onResume() {
super.onResume();
getApplicationContext().getSharedPreferences(this.getLocalClassName(), MODE_PRIVATE).registerOnSharedPreferenceChangeListener(this);
//Toast.makeText(this, "registered pref listener", Toast.LENGTH_SHORT).show();
}
#Override
protected void onPause() {
super.onPause();
getApplicationContext().getSharedPreferences(this.getLocalClassName(), MODE_PRIVATE).unregisterOnSharedPreferenceChangeListener(this);
}
}
As you can see, I have a simple toast message in the onSharedPreferenceChanged method so I can see it working, but it doesn't seem to work.
The only difference with the Google docs is that I am using getApplicationContext() instead of getPreferenceScreen() in the onResume(), because getPreferenceScreen() is showing up as deprecated.
I just need to figure out why its not listening - my preference screen is just full of checkboxes, so I would assume, when I click any of them, the onSharedPreferenceChanged() method is called and I would see my toast.
This simple one has got me stumped.
You are registering your listener to a wrong preference.
Loaded preference from XML resource in SettingsFragment uses default shared preferences so you should register the listener like this:
#Override
public void onResume() {
super.onResume();
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
pref.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
pref.unregisterOnSharedPreferenceChangeListener(this);
super.onPause();
}

PreferenceActivity do something when preference are changed

I have preference xml and following code:
public class MainActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener
{
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Toast.makeText(getApplicationContext(), "DO SOMETHING", Toast.LENGTH_LONG).show();
}
}
I want to get notified over toast message, when one or more preferences are changed. I think upper code should work, but for some reason it doesn't.
I have for example CheckBoxPreference in my xml file. And when I check or uncheck CheckBox I want to be notified.
You have to set the listener like this for example:
PreferenceManager.getDefaultSharedPreferences(this).
registerOnSharedPreferenceChangeListener(this);
or, if You don´t use the default shared preferences, You have to get Your prefs and then register them:
SharedPreferences preferences = getSharedPreferences("your_shared_prefs", Context.MODE_PRIVATE);
preferences.registerOnSharedPreferenceChangeListener(this);
You should register to listen to the shared preference changes:
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}

What's different between OnPreferenceChangeListener and OnSharedPreferenceChangeListener

I want to get value of a checkboxpreference. which method is suitable for listen to preference?
And what's real difference between OnPreferenceChangeListener and OnSharedPreferenceChangeListener ?!
UPDATE
Why onSharedPreferenceChanged not called?
public class Setting extends PreferenceActivity implements
OnSharedPreferenceChangeListener // ,OnPreferenceChangeListener
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);// deprecated warning
}
#Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {// DO Stuff
}
#Override
protected void onResume() {
super.onResume();
// getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
// PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
this.getSharedPreferences("myPrefDB", MODE_PRIVATE)
.registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onPause() {
super.onPause();
// getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
// PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
this.getSharedPreferences("myPrefDB", MODE_PRIVATE)
.unregisterOnSharedPreferenceChangeListener(this);
}
}
The difference between these 2 is that OnPreferenceChangeListener is a callback called only when its preference changes (applies to a single key), while OnSharedPreferenceChange is a callback called whenever any of the preferences in that SharedPreferences object changes (applies to all keys).
So, in your case, you need to use the OnPreferenceChangeListener with your CheckBoxPreference.
Here is an example:
Preference ckboxPref = this.findPreference(CKBOX_PREF_KEY);
ckboxPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference,
Object newValue) {
//Do stuff
}
});
The method findPreference does not work if you use fragments, but you aren't using any so it is fine.

Check and Format preference string value before committing back to preferences

I have an EditTextPreference. After the user has edited the preference and pressed ok I then want to check the value for formatting errors before committing.
public class Preferences_Default extends PreferenceActivity implements OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.layout.prefs_default);
}
}
#Override
protected void onResume() {
super.onResume();
// Set up a listener whenever a key changes
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onPause() {
super.onPause();
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
//This just calls a function to update the Pref Summary
Preference pref = findPreference(key);
initSummary(pref);
}
Where would I put the call to the function that checks the value and what is the code to re-commit the preference value if altered.
Friend, as you just specified, you have to check this in your code: you have to put it first line before it gets updated
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
//function to check
boolean b=check();
//This just calls a function to update the Pref Summary
if(b)
{
Preference pref = findPreference(key);
initSummary(pref);}
else{
//whatever you want to do show error
}
}

Categories

Resources