I have prepared a complete and simple test case for my question: ValidatePrefs app at GitHub:
When you click the "Settings" icon in the top right corner, SettingsActivity is displayed.
I would like to validate the 3 EditTextPreference
fields by returning true
or false
from the onPreferenceChange
method, but it is never called:
public class SettingsActivity extends PreferenceActivity implements Preference.OnPreferenceChangeListener {
private static final String TAG = SettingsActivity.class.getSimpleName();
public static final String ADDRESS = "address";
public static final String USERNAME = "username";
public static final String PASSWORD = "password";
@Override
public void onCreate(Bundle savedInstanceBundle) {
super.onCreate(savedInstanceBundle);
addPreferencesFromResource(R.xml.settings);
}
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
if (! (preference instanceof EditTextPreference)) {
return false;
}
EditTextPreference editTextPreference = (EditTextPreference)preference;
String key = editTextPreference.getKey();
String text = editTextPreference.getText();
if (key == null || key.isEmpty() || text == null || text.isEmpty()) {
return false;
}
switch (key) {
case ADDRESS: {
try {
new URI(text);
} catch (URISyntaxException ex) {
ex.printStackTrace();
return false;
}
return true;
}
case USERNAME: {
return text.length() > 0;
}
case PASSWORD: {
return text.length() > 0;
}
}
return false;
}
}
UPDATE:
After adding findPreference
and setOnPreferenceChangeListener
calls in the SettingsActivity the method onPreferenceChange
is finally called:
@Override
public void onCreate(Bundle savedInstanceBundle) {
super.onCreate(savedInstanceBundle);
addPreferencesFromResource(R.xml.settings);
EditTextPreference address = (EditTextPreference) findPreference(ADDRESS);
EditTextPreference username = (EditTextPreference) findPreference(USERNAME);
EditTextPreference password = (EditTextPreference) findPreference(PASSWORD);
address.setOnPreferenceChangeListener(this);
username.setOnPreferenceChangeListener(this);
password.setOnPreferenceChangeListener(this);
}
However I still can not validate and prevent saving wrong data, because the text
variable contains the old value.
You can see it in the debugger screenshot below - I enter the new (and invalid) value of an empty string, but the variable text
still contains the old value of user1
:
UPDATE 2:
Okay, I was wrongly inspecting the old value stored in Preference
, I should have looked at the new value, passed as 2nd argument to onPreferenceChange
method. Here the fixed version of the method in my SettingsActivity:
@Override
public boolean onPreferenceChange(Preference preference, Object obj) {
if (!(preference instanceof EditTextPreference && obj instanceof String)) {
return false;
}
EditTextPreference editTextPreference = (EditTextPreference)preference;
String key = editTextPreference.getKey();
String oldValue = editTextPreference.getText();
String newValue = String.valueOf(obj);
Log.d(TAG, String.format("key %s, value %s -> %s", key, oldValue, newValue));
// TODO validate the newValue and return true or false
However that method is never called.
It seems to me you have forgotten to register setOnPreferenceChangeListener()
, that's why the callback is not called.