25
25
import java .util .HashSet ;
26
26
import java .util .List ;
27
27
import java .util .Map ;
28
+ import java .util .Objects ;
28
29
import java .util .Set ;
29
30
30
31
/** LegacySharedPreferencesPlugin */
31
32
public class LegacySharedPreferencesPlugin implements FlutterPlugin , SharedPreferencesApi {
32
33
private static final String TAG = "SharedPreferencesPlugin" ;
33
34
private static final String SHARED_PREFERENCES_NAME = "FlutterSharedPreferences" ;
35
+ // All identifiers must match the SharedPreferencesPlugin.kt file, as well as the strings.dart file.
34
36
private static final String LIST_IDENTIFIER = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBhIGxpc3Qu" ;
37
+ // The symbol `!` was chosen as it cannot be created by the base 64 encoding used with LIST_IDENTIFIER.
38
+ private static final String JSON_LIST_IDENTIFIER = LIST_IDENTIFIER + "!" ;
35
39
private static final String BIG_INTEGER_PREFIX = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBCaWdJbnRlZ2Vy" ;
36
40
private static final String DOUBLE_PREFIX = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBEb3VibGUu" ;
37
41
38
42
private SharedPreferences preferences ;
39
- private SharedPreferencesListEncoder listEncoder ;
43
+ private final SharedPreferencesListEncoder listEncoder ;
40
44
41
45
public LegacySharedPreferencesPlugin () {
42
46
this (new ListEncoder ());
@@ -100,7 +104,15 @@ public void onDetachedFromEngine(@NonNull FlutterPlugin.FlutterPluginBinding bin
100
104
}
101
105
102
106
@ Override
103
- public @ NonNull Boolean setStringList (@ NonNull String key , @ NonNull List <String > value )
107
+ public @ NonNull Boolean setEncodedStringList (@ NonNull String key , @ NonNull String value )
108
+ throws RuntimeException {
109
+ return preferences .edit ().putString (key , value ).commit ();
110
+ }
111
+
112
+ // Deprecated, for testing purposes only.
113
+ @ Deprecated
114
+ @ Override
115
+ public @ NonNull Boolean setDeprecatedStringList (@ NonNull String key , @ NonNull List <String > value )
104
116
throws RuntimeException {
105
117
return preferences .edit ().putString (key , LIST_IDENTIFIER + listEncoder .encode (value )).commit ();
106
118
}
@@ -131,14 +143,13 @@ public void onDetachedFromEngine(@NonNull FlutterPlugin.FlutterPluginBinding bin
131
143
132
144
// Gets all shared preferences, filtered to only those set with the given prefix.
133
145
// Optionally filtered also to only those items in the optional [allowList].
134
- @ SuppressWarnings ("unchecked" )
135
146
private @ NonNull Map <String , Object > getAllPrefs (
136
147
@ NonNull String prefix , @ Nullable Set <String > allowList ) throws RuntimeException {
137
148
Map <String , ?> allPrefs = preferences .getAll ();
138
149
Map <String , Object > filteredPrefs = new HashMap <>();
139
150
for (String key : allPrefs .keySet ()) {
140
151
if (key .startsWith (prefix ) && (allowList == null || allowList .contains (key ))) {
141
- filteredPrefs .put (key , transformPref (key , allPrefs .get (key )));
152
+ filteredPrefs .put (key , transformPref (key , Objects . requireNonNull ( allPrefs .get (key ) )));
142
153
}
143
154
}
144
155
@@ -149,7 +160,13 @@ private Object transformPref(@NonNull String key, @NonNull Object value) {
149
160
if (value instanceof String ) {
150
161
String stringValue = (String ) value ;
151
162
if (stringValue .startsWith (LIST_IDENTIFIER )) {
152
- return listEncoder .decode (stringValue .substring (LIST_IDENTIFIER .length ()));
163
+ // The JSON-encoded lists use an extended prefix to distinguish them from
164
+ // lists that are encoded on the platform.
165
+ if (stringValue .startsWith (JSON_LIST_IDENTIFIER )) {
166
+ return value ;
167
+ } else {
168
+ return listEncoder .decode (stringValue .substring (LIST_IDENTIFIER .length ()));
169
+ }
153
170
} else if (stringValue .startsWith (BIG_INTEGER_PREFIX )) {
154
171
// TODO (tarrinneal): Remove all BigInt code.
155
172
// https://github.com/flutter/flutter/issues/124420
0 commit comments