kobowo
kobowo

Reputation: 2787

Using Platform-Specific packages in Flutter

I'm not sure if this is the appropriate stack exchange site but I think it fits more of here than the others that I can think of. Anyways, I work for a mobile app development team and we're looking into using Flutter to develop our future mobile apps as it reduces the amount of work needed when developing for both iOS and Android (we're just a small team).

I read through a bit about Flutter and checked the available packages and the Dart/Flutter Pub and there are some packages that aren't available yet for Flutter that we use for Android and iOS. Take MSAL (Microsoft Authentication Library) for example. After reading through the documentation, I read about Platform Channels and how you can run some KT/Swift etc specific code and return it through something like the MethodChannel in Kotlin but the example from the Flutter docs show an example of only returning specific data types or simple values. What if I wanted to authenticate a user using MSAL? that would involve some UI work that doesn't happen in Flutter specifically since it relies on either the browser or a webview (depending on your MSAL config)

My question here is probably gonna be in 2 main things:

  1. If you have a package that kind of relies on the UI of either iOS or Android for something that isn't gonna take up the entirety of your app's functions, how would it be possible to still use Flutter to develop the rest of your apps while still making use of the platform-specific packages?
  2. Is it possible to have like more than 1 Activity or ViewController that does this and then go to the Flutter part afterwards? Cuz I think thats one possible solution to the previous question.

Note:

I'm aware that there are packages for authentication in the Dart Pub but I'm just using MSAL as an example, we also use other packages that kind of rely on displaying custom views to authenticate users.

Upvotes: 1

Views: 1464

Answers (1)

kobowo
kobowo

Reputation: 2787

I got this to work using platform channels. To answer my specific questions:

  1. This can still be handled by platform channels. As an example, I am using MSAL with a webview and it still returns to the original FlutterActivity after authenticating my user.
  2. I am not 100% sure about this because I didn't create an Activity myself but the package was able to open its own webview so it should work

MainActivity

private val LOGIN_CHANNEL = "flutter.android/msal"
private val scopes = arrayOf("https://graph.microsoft.com/User.Read", "https://graph.microsoft.com/User.ReadBasic.All")

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    GeneratedPluginRegistrant.registerWith(this)
    MyLibrary.setupClientApp(applicationContext, R.raw.auth_config, scopes)
    MethodChannel(flutterView, LOGIN_CHANNEL).setMethodCallHandler { call, result ->
        if (call.method == "login") {
            login{
                result.success(it)
            }
        }
    }
}

private fun login(callback: (String?) -> Unit) {
    MyLibrary.instance!!.acquireToken(
            this,
            scopes,
            MyLibrary.getAuthInteractiveCallback {
                callback(MyLibrary.getUser()?.displayName)
            }
    )
}

MyHomePage (State)

class _MyHomePageState extends State<MyHomePage> {
  String _responseFromNativeCode = "";
  static const platform = const MethodChannel('flutter.android/msal');

  Future _login() async {
    String response = "";
      try {
        response = await platform.invokeMethod('login');
      } on PlatformException catch (e) {
        response = "Failed to Invoke: '${e.message}'.";
      }
      setState(() {
        _responseFromNativeCode = response;
      });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'Hi $_responseFromNativeCode',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _login,
        tooltip: 'Login',
        child: Icon(Icons.lock),
      ),
    );
  }
}

Upvotes: 1

Related Questions