Change in shared preference not firing - android

I have a Floating Action Button in my layout. Users can choose the position of this button, left or right. This can be selected in the preferences.
The code to do this works OK, but a change in the preference is not detected by the listener.
If the app is restarted, the Floating Action Button is displayed according to the new preference, so I know the process with this preference works, but unfortunately the listener seems to fail.
What do I have to do to get the listener firing when the preference has changed?
Listener in my MainActivity:
private final SharedPreferences.OnSharedPreferenceChangeListener
mPositionFabListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.e(TAG,"Are we getting here?");
// We do not get here when preference has changed. Why not??
// Code to update Floating Action Button to new position
}
};
I register the listener in the onResume() method of the MainActivity and unregister in the onPause().
#Override
protected void onResume() {
super.onResume();
PrefUtils.registerOnPrefChangeListener(mPositionFabListener);
}
#Override
protected void onPause() {
PrefUtils.unregisterOnPrefChangeListener(mPositionFabListener);
super.onPause();
}
The registerOnPrefChangeListener method is declared in a seperate class:
public class PrefUtils {
public static boolean getBoolean(String key, boolean defValue) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext());
return settings.getBoolean(key, defValue);
}
public static void putBoolean(String key, boolean value) {
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext()).edit();
editor.putBoolean(key, value);
editor.apply();
}
public static int getInt(String key, int defValue) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext());
return settings.getInt(key, defValue);
}
public static void putInt(String key, int value) {
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext()).edit();
editor.putInt(key, value);
editor.apply();
}
public static void registerOnPrefChangeListener(OnSharedPreferenceChangeListener listener) {
try {
PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext()).registerOnSharedPreferenceChangeListener(listener);
} catch (Exception ignored) {}
}
public static void unregisterOnPrefChangeListener(OnSharedPreferenceChangeListener listener) {
try {
PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext()).unregisterOnSharedPreferenceChangeListener(listener);
} catch (Exception ignored) {}
}
}
UPDATE:
In the GeneralPrefsFragment class I put in this listener for testing purposes. This listener is working. So why does it not work in the MainActivity?
public class GeneralPrefsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Preference preference = findPreference(PrefUtils.POSITION_FLOATING_MENU_BUTTON);
Preference.OnPreferenceChangeListener mListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
PrefUtils.putBoolean(PrefUtils.POSITION_FLOATING_MENU_BUTTON, Boolean.TRUE.equals(newValue));
PreferenceManager.getDefaultSharedPreferences(MainApplication.getContext()).edit().commit(); // to be sure all prefs are written
Log.e(TAG, "The listener in " + TAG + " is listening");
// This listener is fired as soon as changes in the preference are made!
// Why is the same kind of listener not fired in the MainActivity?
return true;
}
};
preference.setOnPreferenceChangeListener(mListener);
}
}
SOLUTION:
I got a fix. I still do not know why the former setup didn't work, but I got it working, thanks to the code in this answer.
In the MainAcivity's onCreate() method I placed the following listener and this one gets triggered when the preferences have changed.
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.OnSharedPreferenceChangeListener mPrefsFabListener =
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (PrefUtils.POSITION_FLOATING_MENU_BUTTON.equals(key)) {
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
CoordinatorLayout.LayoutParams paramsFab = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
if (PrefUtils.getBoolean(PrefUtils.POSITION_FLOATING_MENU_BUTTON, false)) {
paramsFab.gravity = Gravity.BOTTOM | Gravity.START;
} else {
paramsFab.gravity = Gravity.BOTTOM | Gravity.END;
}
}
}
};
prefs.registerOnSharedPreferenceChangeListener(mPrefsFabListener);

The OnSharedPreferenceChangeListener gets unregistered in the onPause() method of the MainAcitivity. That is a problem, because the MainActivity gets paused as soon as the General Preferences Activity is started in order to change the preferences. So, the listener is unregistered and therefore not listening right at the point where it is needed!
I removed the unregisterOnPrefChangeListener from the onPause() and put in the following code. This worked perfectly!
#Override
protected void onDestroy() {
PrefUtils.unregisterOnPrefChangeListener(mPositionFabListener);
super.onDestroy();
}

Related

Listening for Preference change

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.

Android setOnPreferenceChangeListener not being called correctly

I have a ListPreferenece in my preference screen and when It changes I need to execute a method. Problem is when I first change the preferenece list nothing happens but it works the second time round...
public static class DisplayFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
cPPreference cPBg;
cPPreference cPFt;
cPPreference cPTm;
cPPreference cPLg;
ListPreference colorThemeList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.display_preferences);
cPBg = (cPPreference) getPreferenceScreen().findPreference("ambilBg");
cPFt = (cPPreference) getPreferenceScreen().findPreference("ambilFt");
cPTm = (cPPreference) getPreferenceScreen().findPreference("ambilTm");
cPLg = (cPPreference) getPreferenceScreen().findPreference("ambilLg");
/**
* When this list changes I need to exectue a method
*/
colorThemeList = (ListPreference) getPreferenceScreen().findPreference("colorTheme");
colorThemeList.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
ThemeHandler.setTheme(cPBg, cPFt, cPTm, cPLg, colorThemeList.getValue());
return true;
}
});
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
setSummarys();
}
}
Any help greatly appreciated
O.k ...found solution
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("colorTheme")) {
ThemeHandler.setTheme(colorPickerBg, colorPickerFt, colorPickerTm, colorPickerLg, colorThemeList.getValue());
}
}
A simple check in the onSharedPreferneceChanged method :)

How to obtain the value of the key passed to onSharedPreferenceChanged

In my PreferenceFragment I have implemented a OnSharedPreferenceChanged listener. It works. and I am able to see in the Log.i that the "key" matches the property that I am modifying (a switch preference).
But what I am unable to determine is how can I obtain the 'value' of the key? I have been struggling with this for about a day and a half and I know it has to be possible.
public class PrefsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
// set all text correctly
onSharedPreferenceChanged(null, "");
}
#Override
public void onResume() {
super.onResume();
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
super.onPause();
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference preference = findPreference(key);
Log.i("TAG", String.valueOf(key));
}
}
You need use sharedPreferences attribute to get the value of the key.
public class PrefsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
// set all text correctly
onSharedPreferenceChanged(null, "");
}
#Override
public void onResume() {
super.onResume();
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
super.onPause();
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
String value = sharedPreferences.getString(key, "");
Log.i("TAG", value);
}
}
The second parameter of getString() is a default value if the method does not find anything with that key (don't returns null)
You have to make sure that the type stored in the preferences corresponds with which you recover (String in this case). In other case you need use getInt(), or getFloat()...
I just got it like I do elsewhere in the program:
if (key.equals("save_login")) {
boolean saveLogin = AppObject.defaultPrefs.getBoolean("save_login", true);
if(!saveLogin) {
// clear login info that may already have been saved, by default 'true'
SharedPreferences.Editor ed = AppObject.defaultPrefs.edit();
ed.putString("username", "");
ed.putString("password", "");
ed.commit();
}
}
if ("my_switch_preference_key".equals(key)) {
boolean newValue = sharedPreferences.getBoolean(key, false);
// use the new value
}
Replace "my_switch_preference_key" with the actual switch preference key.
Its a little late but I think we don't have to if-else to obtain the value of a key by following code:
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Map<String, ?> all = sharedPreferences.getAll();
Object value = all.get(key);
Log.d("TAG", "Key is: " + key);
Log.d("TAG", "Value is: " + String.valueOf(value));
}
You got an Object value of the key.

EditTextPreference validate data before saving

I have a method to validate a EditTextPreference. My method is executed after the confirmation of data by implementing the onSharedPreferenceChanged class.
However, only occurs after you confirm the information. I would perform the check without closing the dialog box. And if ok then close or keep open for user to enter the data correctly.
If it's not possible, I would reopen the dialog box if the validation is false.
SettingsActivity.java
class SettingsActivity extends PreferenceActivity implements
OnSharedPreferenceChangeListener {
protected static final String TAG = "SettingsActivity";
private SharedPreferences prefs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
// TODO Auto-generated method stub
SharedPreferences.Editor prefEditor = prefs.edit();
if(key.equals("pref_Url")){
String url = prefs.getString(key, "");
boolean response = (!new ConnectUtils().isConnected(this, url));
if(!response){
prefEditor.putString(key, Config.SERVER_URL_DEF_VALUE);
prefEditor.commit();
reload();
Toast.makeText(this,R.string.msgToast_server_url_invalid,Toast.LENGTH_SHORT).show();
}
}else if (key.equals("pref_Id")){
String url = Config.SERVER_URL_ID;
boolean reponse = (!new ConnectUtils().isConnected(this,url));
if(!reponse){
prefEditor.putString(key,Config.ID_DEF_VALUE);
prefEditor.commit();
reload();
Toast.makeText(Config.getContext(), R.string.msgToast_Id_invalid, Toast.LENGTH_SHORT).show();
}
}
}
private void reload(){
startActivity(getIntent());
finish();
}
}
'onPreferenceChangeListener' is a listener that is executed every time a preference is changed by the user. You can return true if data complains validation or false otherwise.
For example:
public class Preferences extends PreferenceActivity implements OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
findPreference("pre_mail").setOnPreferenceChangeListener(
new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
return Pattern.matches(Constants.MAILPATTERN, (String) newValue);
}
});
}
}
Hope this help!

How to update ListPreferences after implementing OnChangeListener

I have PrefActivity and I use OnChange Listener to make a toast when ever user change any button in list preferences.
But now I have 2 problems:
1-first time that user change an option toast is not shown
2-after that, when ever user change prefrences, the value of list is not updated, and is always set on second value.
this is my code:
public class PrefsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener{
private ListPreference myPreference;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged(SharedPreferences arg0, String key) {
ListPreference lp = (ListPreference) findPreference("blocktype");
lp.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// TODO Auto-generated method stub
Toast.makeText(PrefsActivity.this, "second", Toast.LENGTH_LONG).show();
return false;
}
});
}
}
What is
As no one answered my question I figured out, where is problem.
return false
should be changed to
return true
in order to update the preferences

Categories

Resources