EditTextPreference.setText(value) not updating as expected - android

I'm trying to prevent the user from entering an empty string into an EditTextPreference (in the example, catName). I use a OnPreferenceChangeListener to detect when a change is made to the EditTextPreference, and if there is a change and the string is blank, I use the EditTextPreference.setText() command to reset to the old value. However, the new value doesn't show up properly if I reopen the EditTextPreference in the GUI (the string is blank), and if I go back into the main app, I can verify that a blank value is being saved to the preferences.
I've verified that the if statement executes as expected, and that my parameter keeping track of the old name (oldCatName) is updating as expected. I can even log the catName.getText() value right before the setOnPreferenceChangeListener finishes execution and I always see the value I expect (the new value set by the user, and when they enter a blank value, it properly resets to the old value). I'm not sure why setting the value to the EditTextPreference isn't saving the value to the preferences file or updating the GUI.
public class SettingsActivity extends PreferenceActivity {
private String oldCatName;
private EditTextPreference catName;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
catName = (EditTextPreference) findPreference("cat_name");
oldCatName = catName.getText();
catName.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newVal) {
final String value = (String) newVal;
if (value.equals("")) {
catName.setText(oldCatName);
Log.e("new value", catName.getText());
}
else
oldCatName = value;
return true;
}
});
}
}
Thanks for the help!
-Michael
Edit: A clarification. The logic in the if statement is executing correctly. The string value of the EditTextPreference is even updating correctly. However, the value in the GUI if the user taps on the EditTextPreference again does not correctly update, and the value in the app's shared preferences does not update correctly. It stays blank.

Finally found a solution by doing the following:
I used a SharedPreferences.OnSharedPreferenceChangeListener instead of a Preference.OnPreferenceChangeListener. The Preference.OnPreferenceChangeListener looks for when the user changes a preference through the settings menu, and behaves before the change is committed to the preference data. The SharedPreferences.OnSharedPreferenceChangeListener listens for changes to the actual preference data, not changes in the GUI, so it happens a little later. I noticed that in my first attempt, I could run setText() immediately followed by getText() on my EditTextPreference object, and the getText() value wouldn't match what I had just set the setText() value to. I'm not sure why this happens, but waiting for the changes to actually commit before trying to run setText() led to the correct response. Maybe it was a timing issue?
I run setPreferenceScreen(null) and addPreferencesFromResource(R.xml.settings) after updating the value in the EditTextPreference. If I didn't do this, sometimes when the user would click on the EditTextPreference again, the value in the field would appear blank even though the value in the settings file wasn't. This forces the settings page to, more or less, refresh itself.
The working code is below:
public class SettingsActivity extends PreferenceActivity {
private String oldCatName;
private EditTextPreference catName;
private SharedPreferences.OnSharedPreferenceChangeListener listener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
createListener();
catName = (EditTextPreference) findPreference("cat_name");
oldCatName = catName.getText();
}
private void createListener() {
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
String value = sharedPreferences.getString("cat_name", "NULL");
if (value.equals("")) {
catName.setText(oldCatName);
setPreferenceScreen(null);
addPreferencesFromResource(R.xml.settings);
} else {
oldCatName = value;
}
}
};
PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
.registerOnSharedPreferenceChangeListener(listener);
}
}

~9 yrs late, Hope this helps some one else.
I too faced similar issue. It can be done simply by returning false. As the documentation states returning true will update the value and you want to ignore changes.
catName.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newVal) {
final String value = (String) newVal;
if (value.equals("")) {
catName.setText(oldCatName);
Log.e("new value", catName.getText());
return false ; // <----------------------------------
}
else
oldCatName = value;
return true;
}
});

Related

SharedPreferences.getBoolean returns true everytime

I made a class for handling important data changes such as App Purchase Status and other stuff .
For this goal I have created a class which does the setting and reading of the values. but the problem is whenever I call the appIsPurchased() method, the result is true while it hasen't been changed since app installation and its first initial launch.
This is my code:
/**
* Created by neemasa on 5/29/14.
* This class handles more crucial data values within app.
*/
public class AppCore {
private SharedPreferences settings;
private String keyPurchase = "app_purchased";
private Context context;
public AppCore(Context context){
this.context = context;
settings = PreferenceManager.getDefaultSharedPreferences(context);
}
public void setAppInPurchasedMode(String status){
if (status.equals("successful")){
settings.edit().putBoolean(keyPurchase, true).commit();
}else if (status.equals("failed")){
settings.edit().putBoolean(keyPurchase, false).commit();
}
}
public boolean appIsPurchased(){
boolean purchased = false;
if (settings.getBoolean(keyPurchase,true)){
purchased = true;
}
return purchased;
}
}
Question 1st: is there something wrong with my code? if there is then why appIsPurchased() always return true?
Question 2nd: do all values in the shared preferences are true by default?
Meanwhile when I use this class in my code the toast "Purchased!" runs even when app is running for the first time.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AppCore appCore = new AppCore(getApplicationContext());
if (appCore.appIsPurchased()){
Toast.makeText(getApplicationContext(),"Purchased!",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(getApplicationContext(),"Not Purchased!",Toast.LENGTH_SHORT).show();
}
}
Actually there is a problem in your code!! thats why its always showing purchased!!
if (settings.getBoolean(keyPurchase,true)){
purchased = true;
}
in this lines if the keyPurchased tag if not used , u are passing true value by default
so when u call
if (appCore.appIsPurchased()){
it always return a true value.. The solution is that make sure that the preference values are set before u call them.. hope this helps
Found It, the problem is that I was thinking
settings.getBoolean(keyPurchase,false)
returns the value of keyPurchased variable but the fact is it only returns the variable itself not its value so I fixed the problem by changing the method of my class to this:
public boolean appIsPurchased(){
return settings.getBoolean(keyPurchase,false);
}
you are setting the default value to true, so either your sharedpreference does not contains an entry for key_purchased or setAppInPurchasedMode is never called or is called wit status successful. On the minor side, your
public boolean appIsPurchased(){
boolean purchased = false;
if (settings.getBoolean(keyPurchase,true)){
purchased = true;
}
return purchased;
}
can be implemented like:
public boolean appIsPurchased(){
return settings.getBoolean(keyPurchase, false);
}
about setAppInPurchasedMode, if I were in you I would change the way you compare status, this way:
public void setAppInPurchasedMode(String status){
if ("successful".equals(status)){
settings.edit().putBoolean(keyPurchase, true).commit();
} else if ("failed".equals(status)){
settings.edit().putBoolean(keyPurchase, false).commit();
}
}
the difference is that if status is null, the way you implemented will crash your application with NPE. With my implementation you'll get false, because "successful" instanceof null is always false, and instanceof is the first check for equals
For those still having a problem, remember to apply the changes to your preferences.
private SharedPreferences sharedPreferences ;
private SharedPreferences.Editor sharedPreferencesEditor;
sharedPreferencesEditor.putBoolean("myVariable", false);
sharedPreferencesEditor.apply();

Enable and disable option in PreferenceActivity

I am new to creating PreferenceActivity. My question is how to enable and disable option in preference screen by changing other preference?
My prefs.xml:
<ListPreference
android:entries="#array/units"
android:entryValues="#array/lunits"
android:key="listUnits"
android:summary="Units schosssing"
android:title="Units" android:defaultValue="C"/>
<ListPreference
android:entries="#array/palette"
android:entryValues="#array/lpalette"
android:key="listpalette"
android:summary="Palette schosssing"
android:title="Palette"
android:defaultValue="1"/>
In the listUnits there are 2 options, Celsius and Fahrenheit, so if user selects Celsius the listpalette should get enabled, and if user selects Fahrenheit becomes disabled, how can I do this?
My settings activity:
public class SettingsActivity extends PreferenceActivity
{
#Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
}
public static class MyPreferenceFragment extends PreferenceFragment
{
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
}
}
}
This code may be useful to you. Can take as reference.
First take instance of both of the ListPreference and apply this method.
ListPreference mlistUnits, mlistPalette;
mlistUnits= (ListPreference)findPreference("listUnits");
mlistPalette= (ListPreference)findPreference("listpalette");
mlistUnits.setEnable(false);
mlistPalette.setEnabled(true);
and use below listner
OnPreferenceChangeListener listener = new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// newValue is the value you choose
return false;
}
};
apply listener to ListPreference
mlistPalette.setOnPreferenceChangeListener(listener);
Firstly you can set default value for your listUnits listpreference to celcius or Fahrenheit ,according this you can make enable-disable your second listpreference.
Now when changing your Preference by selecting anyone of them you can follow below procedure.
1) implement OnSharedPreferenceChangeListener in your MyPreferenceFragment class and override the method onSharedPreferenceChanged
2) Code like below in your method
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
// TODO Auto-generated method stub
if (key.equals("listUnits")) {
final String value = sharedPreferences.getString(key, "");
Preference Pref_cec=findPreference("listpalette");
if (value.equals("celcius")) {
wallpaperPref_admin.setEnabled(true);
}else{
wallpaperPref_admin.setEnabled(false);
}
}
}
Hope it will Help. Let me know if anything missing in my post.
As your second list is evaluated on basic of first list, what you may do
Look for preference click on the First list, get the value of preference clicked.
Using this value simply enable/disable your second list.

Is it possible to normalize an Android preference value upon change?

In Android 4, I have a preference value that I want to appear in the standard form E2C56DB5-DFFB-48D2-B060-D0F5A71096E0. But the user may enter the value without dashes. I would like to allow the user to enter it with any combination of whitespace or dashes, and simply have my code normalize it.
I am using the code below, and I see the log line, but it does nothing. I am guessing this is because Android has another Editor object open that overwrites my changes. Is there any other way to accomplish this?
public class UuidFragment extends PreferenceFragment {
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
this.getPreferenceScreen().findPreference("pref_uuid").setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference,
Object newValue) {
if (newValue.toString().length() != 0) {
String normalizedUuid=normalizeUuid(newValue.toString());
// TODO: this code runs but does nothing, I think because after committing the change, there is a higher level editor that commits the old value
// thereby undoing this change
if (!normalizedUuid.equals(newValue.toString())) {
Log.d(TAG, "Adjusting uuid from "+newValue.toString()+" to "+normalizedUuid);
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(UuidFragment.this.getActivity());
SharedPreferences.Editor editor = settings.edit();
editor.putString(preference.getKey(), normalizedUuid);
editor.commit();
}
return true;
}
}
});
}
}
Try subclassing EditTextPreference and overriding setText(). In your setText() method, fix up the passed-in string before chaining to the superclass. Then, reference your EditTextPreference subclass from your preference XML.

How to get updated text value from EditTextPreference - it gets old value

I am trying to setup a new password using EditTextPreference. In this Android 4.0.3, clicking the EditTextPreference opens a dialog window where user can enter text. However, on pressing ok, it still shows the old text value and not the newly entered value.
public class MyPreferencesActivity extends PreferenceActivity {
EditTextPreference edp_password = (EditTextPreference) findPreference("pref_key_account_password");
edp_password.setOnPreferenceChangeListener(new OnPreferenceChangeListener(){
public boolean onPreferenceChange(Preference preference, Object newValue) {
String password = edp_password.getText();
Log.v(TAG, "Password is: " + password);
return true;
}
});
I spend a while trying to make it work, but couldn't find any good solution. How can I retrive the newly entered text after user presses Ok.
Try this way:
EditTextPreference pref_dayCount = (EditTextPreference)findPreference("pref_dayCount");
pref_dayCount.setDefaultValue(30);
pref_dayCount.setSummary(getResources().getString(R.string.pref_plan_days_number_summary)+" "+pref_dayCount.getText());
pref_dayCount.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
preference.setSummary(getResources().getString(R.string.pref_plan_days_number_summary)+" "+newValue.toString());
return true;
}
});
ok i think i know what the problem is, from the android developers references, it says that this callback is invoked before the internal state has been updated, so i guess that why you see the old value.
the way you did it was fine, but i'm guessing you need to use the newValue object, maybe something like this:
public class MyPreferencesActivity extends PreferenceActivity {
EditTextPreference edp_password = (EditTextPreference) findPreference("pref_key_account_password");
edp_password.setOnPreferenceChangeListener(new OnPreferenceChangeListener(){
public boolean onPreferenceChange(Preference preference, Object newValue) {
Log.v(TAG, "Password is: " + (EditText)newValue.getText());
return true;
}
});
i'm not sure if this works, i only free write it :P
password.getText will not get the updated value. Use:
String password = newValue.toString();

Android: Reverse Preference dependencies [duplicate]

Is there XML attribute that does the exact opposite of android:dependency?
What I would like the dependent preference to be enabled when the other is NOT checked and disabled when it IS checked.
edit: maybe the issue isn't with android:dependency maybe there is an xml attribute that I can add to make the default for that preference disabled and then android:dependency will toggle it the opposite way like i want.
edit again:
I tried setting android:enabled="false" in the preference and it disables it like i want but even with it being dependent on the other preference it didn't enable it like i had hoped
Actually found it on my own and figured I'd just post it here to help anyone that might have this same issue:
android:disableDependentsState="true"
Put that in the controlling preference.
Dmytro Zarezenko asked what if you wanted some dependencies to be enabled when the preference on which they depend is true and some to be enabled when that preference is false.
Use the method described above to set the all the dependant preferences of one type (which ever have the greater number). Then (with the class having implements OnSharedPreferenceChangeListener) have code like this in the Preference Activity and/or Preference Fragment:
#Override
public void onResume()
{
super.onResume();
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause()
{
super.onPause();
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
{
if (key.equals("pref_that_they_depend-upon")
{
// Iterate over the preferences that need to be enabled or disabled,
// lets say there is just one called the_awkward_one.
Preference preference = findPreference("the_awkward_one");
// Or preference.setEnabled(! sharedPreferences.getBoolean(("pref_that_they_depend-upon", defaultValue));
preference.setEnabled(sharedPreferences.getBoolean(("pref_that_they_depend-upon", defaultValue));
}
}
This is my code sample for doing this from code and not XML.
String eitherKey = "either";
String orKey = "or";
CheckBoxPreference either = new CheckBoxPreference(this);
either.setKey(eitherKey);
either.setTitle("Either");
either.setSummary("It is either one or");
either.setDefaultValue(false);
either.setDisableDependentsState(true);
inlinePrefCat.addPreference(either);
try
{
//Crossfade Time
CheckBoxPreference or = new CheckBoxPreference(this);
or.setKey(orKey);
or.setTitle("Or");
or.setSummary("the other");
inlinePrefCat.addPreference(or);
or.setDependency(eitherKey);
}
catch (Exception e)
{
}
I need to change value of dependent preference, so i post my code below, if anyone wants to do this:
#Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if(preference.getKey().equals("key_a")) {
((CheckBoxPreference)findPreference("key_b").setChecked(false);
}
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
Make your PreferenceActivity implement
SharedPreferences.OnSharedPreferenceChangeListener
declare in PreferenceActivity:
SharedPreferences prefs;
initialize in onCreate:
SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs = sPrefs;
and register on shared preference change listener
prefs.registerOnSharedPreferenceChangeListener(this);
do the same as Steve said in onResume and onPause methods.
implementation of onSharedPreferenceChanged listener:
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d("SettingsActivity","onSharedPreferenceChanged LISTENER FIRED");
if (key.equals(getString(R.string.key_call))) {
//if call true
if (sharedPreferences.getBoolean(getString(R.string.key_call), false)) {
Preference preference = findPreference(getString(R.string.key_record));
preference.setEnabled(false);
} else { // if call false
Preference preference = findPreference(getString(R.string.key_record));
preference.setEnabled(true);
}
}
if (key.equals(getString(R.string.key_record))) {
//if record true
if (sharedPreferences.getBoolean(getString(R.string.key_record), false)) {
Preference preference = findPreference(getString(R.string.key_call));
preference.setEnabled(false);
} else { // if record false
Preference preference = findPreference(getString(R.string.key_call));
preference.setEnabled(true);
}
}
}
In this case, I have 2 mutually exclusive Preferences in PreferenceActivity.
Call and Record.
When both are unchecked, both can be checked, but as user checks one of them, the other becomes disabled (greyed out).
As user unchecks the checked preference, the user can check the other one.
On both of them other preferences can depend and that can be worked out with android:dependancy attribute in XML file.

Categories

Resources