I want to evaluate checkboxpreference, tried some method from here but non of it worked. I need to get the value in the OnSharedPreferenceChangeListener, but not in PreferenceActivity. It gives an error like:
ava.lang.ClassCastException: android.app.SharedPreferencesImpl cannot be cast to android.support.v7.preference.CheckBoxPreference
Could somebody explain the problem?
sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d(MainActivity.this.getClass().getSimpleName(), "Einstellungen wurde geƤndert.");
prefsChanged = true;
if(key.equals("use_gps")) {
//TODO: CheckBox evaluate and LocationUpdate start or remove if it's not checked
CheckBoxPreference preference = (CheckBoxPreference) getSharedPreferences("use_gps", MODE_PRIVATE);
if(preference.isChecked()) {
requestLocationUpdates();
Log.d(getClass().getSimpleName(), "preference ischecked");
} else {
removeLocationUpdates();
Log.d(getClass().getSimpleName(), " preference isnotchecked");
}
}
}
};
Thanks for all the help, solution was in MAinActivity onCreate():
if(key.equals("use_gps")) {
//TODO: CheckBox auswerten udn ggfs. Standortbestimmung starten oder stoppen
boolean checkbox = sharedPreferences.getBoolean("use_gps", true);
if (checkbox == true){
Toast.makeText(MainActivity.this, "true", Toast.LENGTH_LONG).show();
requestLocationUpdates();
} else {
Toast.makeText(MainActivity.this, "false", Toast.LENGTH_LONG).show();
removeLocationUpdates();
}
}
}
This should help, instead of using OnSharedPreferenceChangeListener(), use registerOnSharedPreferenceChangeListener() to link listener to the any of your preference outside of the Preference an
Code snippet for the non-preference Activity where you want to attach the listener for a preference:
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener()
{
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
{
Log.v("CHANGE ", "YES");
boolean use_gps_stat = sharedPreferences.getBoolean("use_gps", true);
if(key == "use_gps")
{
Toast.makeText(getApplicationContext(), "Changed", Toast.LENGTH_LONG).show();
if(use_gps_stat)
{
Toast.makeText(getApplicationContext(), "Checked", Toast.LENGTH_LONG).show();
requestLocationUpdates();
Log.d(getClass().getSimpleName(), "preference ischecked");
}
else
{
Toast.makeText(getApplicationContext(), "Unchecked", Toast.LENGTH_LONG).show();
removeLocationUpdates();
Log.d(getClass().getSimpleName(), " preference isnotchecked");
}
}
}
});
In your preference activity add this to overriden onCreate:
bindPreferenceSummaryToValue_CheckBox(findPreference("use_gps"));
So it should look like this:
public static class MainPreferenceFragment extends PreferenceFragment
{
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preference);
bindPreferenceSummaryToValue_CheckBox(
findPreference("use_gps"));
.
.
.
And add bindPreferenceSummaryToValue_CheckBox outside onCreate:
private static void bindPreferenceSummaryToValue_CheckBox(Preference preference)
{
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getBoolean(preference.getKey(), true));
}
For sBindPreferenceSummaryToValueListener simply add to the class extending to AppCompatPreferenceActivity:
private static Preference.OnPreferenceChangeListener
sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener()
{
#Override
public boolean onPreferenceChange(Preference preference, Object newValue)
{
//Do something on prefernce change.
return true;
}
};
I recently tried this code structure and worked, if there are any queries let me know down in the comments.
Related
can anyone tell me how can I start/stop a location service (or any other service) when a SwitchPreference in a PreferenceScreen is toggled on/of?
I'm using a settingsFragemnt (extending PreferenceFragemntCompat), which is hosted in my settings activity.
You should add OnPreferenceChangeListener which will allow you to listen switch changes:
final SwitchPreference onOffRandomColor = (SwitchPreference) findPreference(this.getResources()
.getString(R.string.sp_key_on_off_random_color));
onOffRandomColor.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object o) {
if(onOffRandomColor.isChecked()){
}else {
}
return false;
}
});
Next step is to run service:
startService(new Intent(this, LocationService.class));
my fragment looks like this:
public class SettingsFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(#Nullable Bundle savedInstanceState, String rootKey){
setPreferencesFromResource(R.xml.prefs, rootKey);
// setting summaries for both list preferences ---------------------------------------------
ListPreference photo_quality = findPreference("photo_quality");
if (photo_quality != null){
photo_quality.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
}
ListPreference uploads = findPreference("upload_options");
if (uploads != null) {
uploads.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
}
// setting the visibility for location service ---------------------------------------------
if (!Auth.getCanDeactiveGps()){
Objects.requireNonNull(getPreferenceScreen()
.findPreference("location_category")).setVisible(false);
}
// handling locationSwitchPreference change ------------------------------------------------
SwitchPreference locationSwitch = findPreference("location");
if (locationSwitch != null){
locationSwitch.setChecked(Settings.getBoolean(Settings.DO_NOT_LOCATE,
false));
locationSwitch.setOnPreferenceChangeListener(
new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Settings.setBoolean(Settings.DO_NOT_LOCATE, true);
return false;
}
});
}
}
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();
}
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.
I have a settings.xml in my res folder to manage user settings. I load this into a fragment. I require to store these settings to a backend service for this I want to know what values have been by the user or whenever user changes a setting I want to know so that I update the server about the settings.
I have tried many approaches as shown in the code below but I am unable to read the value. I tried putting Toast and log statements to check the listeners but nothing is appearing which indicates that listener is not getting called. Am I doing something wrong?
UserSettingFragment.java
public class UserSettingFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
//Method 1
PreferenceScreen shared = getPreferenceScreen();
shared.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// TODO Auto-generated method stub
Toast.makeText(getActivity().getApplicationContext(), "Changed", Toast.LENGTH_LONG).show();
Log.d("preference", "change");
return true;
}
});
final SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
Preference gender = (Preference) findPreference("gender");
//Method 2
// Get the custom preference
Preference mypref = (Preference) findPreference("mypref");
mypref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// TODO Auto-generated method stub
String highScore = sharedPref.getString("gender", "Male");
Toast.makeText(getActivity().getApplicationContext(), "Changed to " + highScore, Toast.LENGTH_LONG).show();
Log.d("preference", "change");
return false;
}
});
} //Method 3
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
// TODO Auto-generated method stub
Toast.makeText(getActivity().getApplicationContext(), "Changed", Toast.LENGTH_LONG).show();
}
}
settings.xml
<?xml version="1.0" encoding="utf-8"?>
<SwitchPreference
android:key="gender"
android:title="I am"
android:switchTextOn="Female"
android:switchTextOff="Male"
/>
</PreferenceCategory>
Since you are using a PreferenceFragment you need to register and unregister OnSharedPreferenceChangeListener in the onResume and onPause methods for method #3 that you mentioned in your question.
public class UserSettingFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Toast.makeText(getActivity().getApplicationContext(), "Changed key: " + key, Toast.LENGTH_LONG).show();
}
}
Reference
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!