我商店里已经有一个
iOS
应用程序,现在计划用新版本的 Flutter 来替换它 release
。
我想在 Flutter 代码中访问原生应用程序的
UserDefaults
数据。
使用 Flutter 文档中建议的方式,我得到了
null value
。我尝试过的是:
在我的
pubspec.yaml
文件中:
dependencies:
shared_preferences: ^0.5.12+4
我是我的
home.dart
类文件,我正在导入标头:
import 'package:shared_preferences/shared_preferences.dart';
这就是我尝试从 iOS
应用程序访问
native
应用程序中存储的数据的方式,我在 flutter 项目中使用相同的包 ID (包 ID) 来覆盖应用程序,并且它已成功覆盖。
@override
void initState() {
super.initState();
getFromLocalMemory('user').then((value) =>
userInfo = value
);
}
Future<String> getFromLocalMemory(String key) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String user = prefs.getString(key);
return user;
}
它总是返回 null。 而“user”键从 iOS 原生应用程序获取时有数据。
我们可以使用现有插件native_shared_preferences。它允许我们在
Android上访问本机
SharedPreferences
和在 iOS上访问本机
UserDefaults
。
通过键“SomeKey”读取值的示例代码:
final someKey = "SomeKey";
var prefs = await NativeSharedPreferences.getInstance();
if (prefs.containsKey(someKey)) {
print("Value for SomeKey: ${prefs.get(someKey)}");
}
可能为时已晚,但对于将来的搜索可能会有所帮助。 这是我从本机应用程序获取必要的令牌和一个 int 值的方法。
首先,您需要 path_provider 来查找必要的文件,plist_parser 用于 iO,因为 iO 将用户默认值存储为 .plist 文件,以及 xml 来读取 Android 中具有共享首选项的 .xml 文件。
如何查找 iO 原生值:
if (Platform.isIOS) {
// Find the dir of the app.
final appDocumentsDir = await getLibraryDirectory();
// Create a list of contents in this dir, which includes files and dirs.
List contents = appDocumentsDir.listSync();
// Find in the list the dir with user preferences
Directory? prefsDir = contents.firstWhereOrNull((element) => element is Directory && element.path.contains('Preferences'));
if (prefsDir != null) {
// Get contents of the dir named 'Preferences'
List subContents = prefsDir.listSync();
// Find .plist file with package name of your app.
File? prefsFile = subContents.firstWhereOrNull((element) => element is File && element.path.contains('com.your_app.plist'));
if (prefsFile != null) {
// Parse the file
final plist = PlistParser().parseBinaryFileSync(prefsFile.path);
// With loop find necessary items
for (final item in plist.entries) {
if (item.key == 'access_token') {
print('${item.value as String}');
// your code to handle the value
}
if (item.key == 'city_id') {
print('${item.value as int}');
// your code to handle the value
}
// Here is an example to get stored data of Swift struct
if (item.key == 'selectedCity') {
// Create decoder
const asciiDecoder = AsciiDecoder();
// Get ASCII value, which stored like [56, 104, 92 ...]
final asciiValues = item.value;
// Convert it to string.
// It returns json string
final cityJson = asciiDecoder.convert(asciiValues);
// Convert json to the class with its factory.
// You may use https://app.quicktype.io to convert JSON
// to Flutter class and create necessary factories
final city = City.fromRawJson(cityJson);
// your code to handle the object of this class
}
}
}
}
}
如何从 Android 中的共享首选项中获取值。
import 'package:xml/xml.dart' as xml;
// Name it somehow you like for example 'xml' as far as it conflicts with dart.io
// You will need dart.io for Platform
if (Platform.isAndroid) {
// Find the dir of you app by package name
final appDocumentsDir = Directory('/data/data/com.your_app');
// Create a list of contents in this dir, which includes files and dirs.
List contents = appDocumentsDir.listSync();
// Find in the list the dir with shared preferences
Directory? prefsDir = contents.firstWhereOrNull((element) => element is Directory && element.path.contains('shared_prefs'));
if (prefsDir != null) {
// Get contents of the dir named shared_prefs
List subContents = prefsDir.listSync();
// Find .xml file with shared preferences.
// Check the name of this file in native code, or
// find it in Device Explorer of Android Studio.
File? prefsFile = subContents.firstWhereOrNull((element) => element is File && element.path.contains('your_name.xml'));
if (prefsFile != null) {
// Create XML document
final document = xml.XmlDocument.parse(prefsFile.readAsStringSync());
// Loop from root to children
for (final items in document.children) {
// Loop for each child
for (final item in items.childElements) {
// Read item as Sting
final itemString = item.outerXml;
// Check for your name in prefs
if (itemString.contains('access_token')) {
// If prefs store it as String it will look like
// '<string name="access_token">the token value</string>'
// Get the value in this key
final value = item.innerXml;
// your code to handle the value
}
// For int or float you need to do something different.
// Because prefs store it like '<int name="city_id" value="3" />'
if (itemString.contains('city_id')) {
// 'item.attributes' will return a list like
// [name="city_id", value="3"]
// and you need to get second value and parse it to int
final cityId = int.parse(item.attributes[1].value);
// You code to handle the value 'cityId'
}
}
}
}
}
}
}
.firstWhereOrNull 是来自 getX 非常有用的库的函数。 或者您可以使用下面的扩展。
extension IterableX<T> on Iterable<T> {
T? firstWhereOrNull(bool Function(T) test) {
T? firstItem;
for (var item in this) {
if (test(item)) {
firstItem = item;
break;
}
}
return firstItem;
}
}