addPrefixToKey called before ELEMENT_PREFERENCES_KEY_PREFIX is set
Hi, I encountered an issue when reading a value with a preferencesKeyPrefix specified on Android.
It looks like when I try to read a value after the app starts fresh the ELEMENT_PREFERENCES_KEY_PREFIX field in FlutterSecureStorage.java has not been set as the " String key = getKeyFromCall(call);" line in FlutterSecureStoragePlugin is called before ensureInitialized() has been run in FlutterSecureStorage. This results in that the ELEMENT_PREFERENCES_KEY_PREFIX default value is used, and not the specified one.
If you run the sample app below, and click the write button and then closes the app, and then open the app again, press the read button the first read will return null as the returned key returned from getKeyFromCall is wrong.
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'flutter_secure_storage',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _flutterSecureStorage = const FlutterSecureStorage(
aOptions: AndroidOptions(
encryptedSharedPreferences: true,
keyCipherAlgorithm: KeyCipherAlgorithm.RSA_ECB_OAEPwithSHA_256andMGF1Padding,
preferencesKeyPrefix: "prefix",
sharedPreferencesName: "shared_prefs",
storageCipherAlgorithm: StorageCipherAlgorithm.AES_GCM_NoPadding,
),
iOptions: IOSOptions(
// The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.
// Items with this attribute do not migrate to a new device.
accessibility: KeychainAccessibility.first_unlock_this_device,
// kSecAttrSynchronizable - A key whose value is a string indicating whether the item is synchronized through iCloud.
synchronizable: false,
));
final _prefsKey = "prefs_key";
Future<void> _readData() async {
final value = await _flutterSecureStorage.read(key: _prefsKey);
print("Read data value = $value");
}
Future<void> _writeData() async {
await _flutterSecureStorage.write(key: _prefsKey, value: "test_string");
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
TextButton(
onPressed: () {
_readData();
},
child: const Text("Read"),
),
TextButton(
onPressed: () {
_writeData();
},
child: const Text("Write"),
)
],
),
);
}
}