Access Flutter Sharedpreferences in Swift

Read shared preferences in Flutter app that were previously stored in a native app

Since there was no satisfying answer to my question that works for both of the major operating systems and taking into account the distribution over multiple resource files, I have written a platform channel solution myself.

On Android (Kotlin) I let the caller provide a "file" argument because it's possible to have the data spread over multiple resource files (like I described in my question).

package my.test

import android.content.*
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity: FlutterActivity() {
private val CHANNEL = "testChannel"

override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
call, result ->
when (call.method) {
"getStringValue" -> {
val key: String? = call.argument<String>("key");
val file: String? = call.argument<String>("file");

when {
key == null -> {
result.error("KEY_MISSING", "Argument 'key' is not provided.", null)
}
file == null -> {
result.error("FILE_MISSING", "Argument 'file' is not provided.", null)
}
else -> {
val value: String? = getStringValue(file, key)
result.success(value)
}
}
}
else -> {
result.notImplemented()
}
}
}
}

private fun getStringValue(file: String, key: String): String? {
return context.getSharedPreferences(
file,
Context.MODE_PRIVATE
).getString(key, null);
}
}

On iOS (Swift) this is not necessary as I'm working with UserDefaults

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let platformChannel = FlutterMethodChannel(
name: "testChannel",
binaryMessenger: controller.binaryMessenger
)

platformChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
guard call.method == "getStringValue" else {
result(FlutterMethodNotImplemented)
return
}

if let args: Dictionary<String, Any> = call.arguments as? Dictionary<String, Any>,
let number: String = args["key"] as? String, {
self?.getStringValue(key: key, result: result)
return
} else {
result(
FlutterError.init(
code: "KEY_MISSING",
message: "Argument 'key' is not provided.",
details: nil
)
)
}
})

GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

private func getStringValue(key: String, result: FlutterResult) -> String? {
let fetchedValue: String? = UserDefaults.object(forKey: key) as? String
result(fetchedValue)
}

I'd wish for the SharedPreferences package to add the possibility of omitting the flutter prefix, enabling the developer to migrate content seamlessly from native apps.

I also wrote a blog post that explains the problem and the solution in a little bit more details: https://www.flutterclutter.dev/flutter/tutorials/read-shared-preferences-from-native-apps/2021/9753/

How to access iOS UserDefaults stored data in Flutter SharedPrefrences

In that case, I suggest you use platform channel method

platform channels

iOS doesn't seem to allow flutter framework to access NSUserDefaults, when it didn't create it from the beginning,..

I hope it will work for you.

how to check if SharedPreferences exists for this application in flutter

You need to check if the key exists yet by using prefs.containsKey('username').

How to use shared preferences to keep user logged in flutter?

You can navigate to the Login page if the user details are saved in the storage else to the Home page with the below code

  Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences prefs = await SharedPreferences.getInstance();
var email = prefs.getString('email');
print(email);
runApp(MaterialApp(home: email == null ? Login() : Home()));
}

Save the required user details after the successful login

class Login extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: () async {
//after the login REST api call && response code ==200
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('email', 'useremail@gmail.com');
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext ctx) => Home()));
},
child: Text('Login'),
),
),
);
}
}

clear the details on logout

class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: RaisedButton(
onPressed: () async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.remove('email');
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext ctx) => Login()));
},
child: Text('Logout'),
),
),
);
}
}

Hope it helps!



Related Topics



Leave a reply



Submit