11

I have a big problem with the SharedPreferences in Android. The preferences are adding unwanted chars to one of my string values once the application is closed. Actually it is a configurable escape sequence.

I have a simple setup, a MainActivity containing

@Override
protected void onStart() {
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
    sequence = prefs.getString("escape_sequence", "");
}

And a preferences screen where the value is set. When i open the app go to the prefences screen, set the value correctly to \n\n and go back to the MainActivity the breakpoint is correctly displaying the sequence as Java.lang.String, value(char[2])= "\n\n", count=2. When i am now restarting the app through android studio the same breakpoint in the code suddenly displays: Java.lang.String, value(char[6])= "\n\n ", count=6, containing 4 Space and 10 escape \u0000 characters.

Can anybody why this is happening and what i can do about that?

BTW i'm not touching the SharedPreferences.Editor anywhere in the App so far. I is strictly done via the PreferencesScreen. So no overwrite is done anywhere in the app. The default values shouldn't be applied either, however the setting is android:defaultValue="\n\n" anyway.

EDIT:

I found the reason: android adds the spaces if a newline is at the end of the preference. I have no idea why.

EDIT:

Here is the custom preference code:

public class SequencePreference extends DialogPreference {
    EditText sequenceInput;

    public SequencePreference(Context context, AttributeSet attrs) {
        super(context, attrs);

        setDialogLayoutResource(R.layout.dialog_preference_sequence);
        setPositiveButtonText(R.string.settings_sequence_ok);
        setNegativeButtonText(R.string.settings_sequence_cancel);

        setDialogIcon(null);
    }

    @Override
    protected View onCreateDialogView() {
        View view = super.onCreateDialogView();
        sequenceInput= (EditText)view.findViewById(R.id.sequence_input);

        return view;
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        // When the user selects "OK", persist the new value
        if (positiveResult) {
            String sequenceValue = new String( sequenceInput.getText().toString() );

            String[] parts = sequenceValue.split("-");
            if(parts.length == 2) {
                persistString(parts[1]);
            }
        }
    }
}
gobernador
  • 5,659
  • 3
  • 32
  • 51
patman
  • 2,780
  • 4
  • 30
  • 54
  • Did you look inside your preference file on device? Maybe it is a file format/permission problem and it is stuck this way and won't updated by application. – weaknespase Dec 26 '15 at 14:10
  • Hey thanks for your comment. First of all: why would that happen and wouldn't the android preferences framework take care of that? But besides that i would wonder where the value would come from in the first place, and furthermore i can change every other setting and save it. I even tried changing several settings including the troubling one and it worked but the spaces still where appended to the one setting. So i doubt this is the reason. – patman Dec 26 '15 at 14:23
  • Version of android? Test/Release build? Emulator/Real device? Is it happens with every property of string type or just with this one? Have you tried different name for it? – weaknespase Dec 26 '15 at 14:26
  • It happens on a real device (4.4.2, API 19) as well as in the emulator (i.e. 6.0, API 23), debug build out of android studio. Just this one string preference is affected others work fine. Renaming it produces the same result, so probably really something in code... I use a custom Preference but i guess there's nothing special about that. I posted it above – patman Dec 26 '15 at 17:42
  • Seems like it should be fine. My Android is little rusty, but how you manage to input line break character in text edit widget? As i remember it was single-line. – weaknespase Dec 26 '15 at 17:56
  • I also tried by changing the Preference to `EditTextPreference`, but still the same result. But i found the reason for this behaviour: it's because of the new line characters (if i save other chars it is fine, if i save other chars with new lines at the end android still adds 4 spaces). (Yes you can enter new lines) – patman Dec 26 '15 at 17:57
  • Ok, then I can only propose to input line break characters escaped and then translating escape sequences and vice-versa for displaying them. For a mere few chars it would be an easy task, just a few replaces. `android:singleLine` will prevent input of unwanted line breaks. – weaknespase Dec 26 '15 at 18:00
  • Thank you. Actually line breaks in that case are needed and wanted. Escaping might be an option, probably via TextWatcher or something. Hacky solution for now: Add a custom escape sequence to the end (like "ABC") and remove when reading the value. – patman Dec 28 '15 at 12:36

2 Answers2

11

I think this is a bug in Android API 18 and newer where extra whitespace is injected when a SharedPreferences string ends with \n. For more information, see:

https://code.google.com/p/android/issues/detail?id=159799#c6 https://code.google.com/p/android/issues/detail?id=159799#c7

CompareAndSwap
  • 111
  • 1
  • 4
0

after you retrieve the saved string, place a trim(). example

String sequence2 = sequence.trim()
Jose Tovar
  • 149
  • 2
  • 13