在Flutter中使用特定于平台的软件包

时间:2019-07-17 14:34:53

标签: flutter flutter-platform-channel

我不确定这是否是合适的堆栈交换站点,但我认为它比我能想到的其他站点更适合这里。无论如何,我为一个移动应用程序开发团队工作,我们正在考虑使用Flutter开发我们未来的移动应用程序,因为它减少了同时为iOS和Android开发的工作量(我们只是一个小团队)。 / p>

我通读了有关Flutter的内容,并检查了可用的软件包和Dart / Flutter Pub,还有一些我们尚未在Android和iOS上使用的Flutter软件包。以MSAL(Microsoft身份验证库)为例。阅读完文档后,我了解了平台通道以及如何运行一些KT / Swift等特定代码,并通过Kotlin中的MethodChannel之类返回它,但是Flutter文档中的示例显示了仅返回特定的数据类型或简单值。如果我想使用MSAL对用户进行身份验证怎么办?这将涉及一些Flutter不会发生的UI工作,特别是因为它依赖于浏览器或Web视图(取决于您的MSAL配置)

我在这里的问题可能是两点:

  1. 如果您使用的软件包依赖于iOS或Android的UI,而这些软件包又无法占用应用程序的全部功能,那么如何仍然可以使用Flutter开发其余的您的应用仍在使用特定于平台的软件包的情况下?
  2. 是否有可能拥有多个以上的Activity或ViewController来执行此操作,然后再转到Flutter部分?因为我认为那是对上一个问题的一种可能的解决方案。

注意:

我知道Dart Pub中有用于身份验证的软件包,但我只是以MSAL为例,我们还使用了其他依赖于显示自定义视图来对用户进行身份验证的软件包。

1 个答案:

答案 0 :(得分:1)

我使用平台渠道来完成这项工作。要回答我的具体问题:

  1. 这仍然可以由平台渠道处理。例如,我将MSAL与Webview一起使用,并且在对我的用户进行身份验证后,它仍然返回到原始的FlutterActivity
  2. 对此我不是100%肯定,因为我自己没有创建Activity,但是该软件包能够打开自己的Web视图,因此它应该可以工作

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)
            }
    )
}

我的主页(状态)

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),
      ),
    );
  }
}