前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >从零开始的Flutter之旅: MethodChannel

从零开始的Flutter之旅: MethodChannel

作者头像
Rouse
发布于 2020-07-13 03:11:08
发布于 2020-07-13 03:11:08
1.2K00
代码可运行
举报
文章被收录于专栏:Android补给站Android补给站
运行总次数:0
代码可运行

在flutter_github有这么一个场景:通过authorization认证方式进行登录。而authorization的具体登录形式是,通过跳转一个网页链接进行github授权登录,成功之后会携带对应的code到指定客户端中,然后客户端可以通过这个code来进行oauth授权登录,成功之后客户端可以拿到该账户的token,所以之后的github操作都可以通过该token来进行请求。由于token是有时效性,同时也可以手动解除授权,所以相对于在客户端进行账户密码登录来说更加安全。

那么要实现上面这个场景,Flutter就需要与原生客户端进行通信,拿到返回的code,然后再到Flutter中进行oauth授权登录请求。

通信方式可以使用MethodChannel,这个就是今天的主题。

OAuth App

authorization认证的原理已经知道了,下面直接来看实现方案。

首先我们需要一个OAuth App用来提供用户通过github授权的应用。

这个在github上可以直接注册的

在注册的OAuth App时会有一个Authorization callback URL必填项。这个callback url的作用就是当你通过该链接认证通过后会以App Link的方式使用该url跳转到对应的App应用,同时返回认证成功的code。这里将其定义为REDIRECT_URI

注册成功之后,我们拿到它的Client IDClient SecretAuthorization callback URL,拼接成下面的连接

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const String URL_AUTHORIZATION =
    'https://github.com/login/oauth/authorize?client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&scope=user%20repo%20notifications%20';

有了跳转到外部的认证链接之后,下面就是在应用中实现这个跳转认证流程。

url_launcher

首先需要跳转外部浏览器访问上面的authorization链接。这一步的实现需要借助url_launcher,它能够帮助我们检查链接是否有效,同时启动外部浏览器进行跳转。

在使用之前需要在pubspec.yaml中添加依赖

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dependencies:
  flutter:
    sdk: flutter
  http: 0.12.0+4
  dio: 3.0.7
  shared_preferences: 0.5.6+1
  url_launcher: 5.4.1
  ...

依赖成功之后,使用canLaunch()来检查链接的有效性;launch()来启动跳转

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  authorization() {
    return () async {
      FocusScope.of(context).requestFocus(FocusNode());
      if (await canLaunch(URL_AUTHORIZATION)) {
        // 为设置forceSafariVC,IOS 默认会打开APP内部WebView
        // 而APP内部WebView不支持重定向跳转到APP
        await launch(URL_AUTHORIZATION, forceSafariVC: false);
      } else {
        throw 'Can not launch $URL_AUTHORIZATION)';
      }
    };
  }

Scheme

通过authorization()方法可以成功跳转到外部浏览器进行登录授认证。授权成功之后会返回到之前的app,具体页面路径与链接中配置的REDIRECT_URI有关。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const String REDIRECT_URI = 'github://login';

这里定义了一个Scheme,为了能够成功返回到客户端指定的页面,我们需要为Android与IOS配置对应的Scheme。

Android

找到AndroidManifest文件,在activity便签下添加intent-filter属性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<intent-filter>
    <action android:name="android.intent.action.VIEW" />
 
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
 
    <data
        android:host="login"
        android:scheme="github" />
</intent-filter>

前面的actioncategory配置是固定的,如果需要支持不同的scheme,主要修改的是data中的配置。

schemehost分别对应到REDIRECT_URI中的数值。

IOS

找到info.plist文件,添加URL types便签,在它的item下配置对应的URL identifierURL Schemes

配置完scheme之后,就能够正常返回到对应的客户端页面。

接下来需要考虑的是,如何拿到返回的code值

MethodChannel

这个时候今天的主角就该上场了。

MethodChannel简单的说就是Flutter提供与客户端通信的渠道,使用时互相约定一个渠道name与对应的调用客户端指定方法的method

所以我们先来约定好这两个值

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const String METHOD_CHANNEL_NAME = 'app.channel.shared.data';
const String CALL_LOGIN_CODE = 'getLoginCode';

然后通过MethodChannel来获取对应的渠道

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  callLoginCode(AppLifecycleState state) async {
    if (state == AppLifecycleState.resumed) {
      final platform = const MethodChannel(METHOD_CHANNEL_NAME);
      final code = await platform.invokeMethod(CALL_LOGIN_CODE);
      if (code != null) {
        _getAccessTokenFromCode(code);
      }
    }
  }

使用invokeMethod来调用客户端对应的方法,这里是用来获取授权成功后返回客户端的code。

这是Flutter调用客户端方法的步骤,下面再看客户端的实现

Android

首先我们将约定好的渠道名称与回调方法名定义为常量

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
object Constants {
    const val AUTHORIZATION_CODE = "code"
    const val METHOD_CHANNEL_NAME = "app.channel.shared.data"
    const val CALL_LOGIN_CODE = "getLoginCode"
}

在之前我们已经在AndroidManifest.xml中定义的scheme,所以认证成功后回返回客户端的MainActivity页面,同时回调onNewIntent方法。

所以获取返回code的方式可以在onNewIntent中进行,同时还需要建立对应的MethodChannel与提供回调的方法。具体实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MainActivity : FlutterActivity() {
 
    private var mAuthorizationCode: String? = null
 
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)
        setupMethodChannel()
    }
 
    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        getExtra(intent)
    }
 
    private fun getExtra(intent: Intent?) {
        // from author login
        mAuthorizationCode = intent?.data?.getQueryParameter(Constants.AUTHORIZATION_CODE)
    }
 
    private fun setupMethodChannel() {
        MethodChannel(flutterEngine?.dartExecutor, Constants.METHOD_CHANNEL_NAME).setMethodCallHandler { call, result ->
            if (call.method == Constants.CALL_LOGIN_CODE && !TextUtils.isEmpty(mAuthorizationCode)) {
                result.success(mAuthorizationCode)
                mAuthorizationCode = null
            }
        }
    }
}

MethodChannel建立渠道,setMethodCallHandler来响应Flutter中需要调用的方法。通过判断回调的方法名称,即之前在Flutter中约定的CALL_LOGIN_CODE。来执行对应的逻辑

因为我们需要返回的code值,只需通过resultsuccess方法,将获取到的code传递过去即可。之后Flutter就能够获取到该值。

IOS

AppDelegate.swift中定义一个methodChannel,使用约定好的name。

methodChannel的创建IOS是通过FlutterMethodChannel.init来生成。之后的回调与Android的基本类似

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    var paramsMap: Dictionary<String, String> = [:]
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
     
    let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
    let methodChannel = FlutterMethodChannel.init(name: "app.channel.shared.data", binaryMessenger: controller.binaryMessenger)
     
    methodChannel.setMethodCallHandler { (call, result) in
        if "getLoginCode" == call.method && !self.paramsMap.isEmpty {
            result(self.paramsMap["code"])
            self.paramsMap.removeAll()
        }
    }
     
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
    override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        let absoluteString = url.absoluteURL.absoluteString
        let urlComponents = NSURLComponents(string: absoluteString)
        let queryItems = urlComponents?.queryItems
        for item in queryItems! {
            paramsMap[item.name] = item.value
        }
        return true
    }
}

setMethodCallHandler中判断回调的方法是否与约定的方法名一致,如果一致再通过result方法将code传递给Flutter。

至此Android与IOS都与Flutter建立了通信,它们之间的桥梁就是通过MethodChannel来搭建的。

最后code传回到Flutter之后,我们再将code进行请求获取到对应的token。

到这里整个授权认证就完成了,之后我们就可以通过token来请求用户相关的接口,获取对应的数据。

token的获取与相关接口的调用可以通过查看flutter_github源码获取

flutter_github

flutter_github,这是一个基于Github Open Api开发的Flutter版本的Github客户端。该项目主要是用来练习Flutter,感兴趣的可以加入一起来学习,如果有帮助的话也请不要吝啬你的关注。

当然如果你想了解Android原生,AwesomeGithub是一个不错的选择。它是flutter_github的纯Android版本。

flutter_github: https://github.com/idisfkj/flutter_github

AwesomeGithub: https://github.com/idisfkj/AwesomeGithub

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android补给站 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
[1275]WSL的安装与使用
集成水平:WSL提供更深入的集成与主机操作系统Windows。例如,你可以在Windows的文件管理器中直接访问WSL文件系统,也可以在WSL中直接运行Windows的可执行文件。而虚拟机则创建了一个相对隔离的环境,虽然虚拟机可以访问主机文件系统,但需要特定的设置,并且整体上没有WSL那么直接和方便。
周小董
2024/04/07
5410
[1275]WSL的安装与使用
最详尽教程完整介绍-Windows 的 Linux 子系统-WSL1&WSL2
必须启用“适用于 Linux 的 Windows 子系统”可选功能并重启,然后才能在 Windows 上运行 Linux 发行版。
DevOps在路上
2023/05/16
7.3K0
最详尽教程完整介绍-Windows 的 Linux 子系统-WSL1&WSL2
WSL 2 的安装过程(以及介绍)
WSL全称为Windows Subsystem for Linux,官网译为:适用于 Linux 的 Windows 子系统 (WSL)
没有故事的陈师傅
2022/12/06
3.3K0
WSL 2 的安装过程(以及介绍)
Win 独享 WSL 并搭配 Oh My Zsh
适用于 Linux 的 Windows 子系统随 Windows 操作系统一起提供,但必须先启用它并安装 Linux 发行版,然后才能开始使用它。
acc8226
2022/05/17
3.5K0
WSL2:Windows 亲生的 Linux 子系统
在上一篇文章中,我们主要聊了一下:在 Windows 系统中,安装 WSL 子系统。
IOT物联网小镇
2021/08/13
3.4K1
WSL2:Windows 亲生的 Linux 子系统
重装操作系统经历之谈
重装win10纯净版操作系统 声明:①机器:笔记本联想电脑 ②本文仅是记录自己重装操作系统的经验,如果有错误,请指正! 第一步,准备一个官方渠道购买的优盘,不能少于8G,我自己重装的时候用的是16G的金士顿优盘。 第二步,请备份自己磁盘中的重要文件。切记!切记!切记! 第三步,在msdn官网下载iso文件镜像(这里可以根据自己的需求选择不同的版本,我本人选择的是纯净版的win10 ltsc 企业版2019)注意是下载到优盘 第四步:按照下面推荐的视频操作即可 推荐我在哔哩哔哩观看的一个视频https
WHYBIGDATA
2023/01/31
1.1K0
重装操作系统经历之谈
在Windows11上安装和使用WSL2
https://docs.microsoft.com/zh-cn/windows/wsl/
AiDBA宝典
2023/04/26
6.4K0
在Windows11上安装和使用WSL2
腾讯云服务器如何更换操作系统?
腾讯云服务器,提供了很多公共镜像,当时我们发现之前的操作系统不适合我们业务的时候,我们可以更换系统。我们后来要更换,应该怎么办呢?更换系统镜像就相当于重装系统了,腾讯云服务器更换系统支持这个操作的。
用户6558266
2019/10/26
30.1K0
腾讯云服务器如何更换操作系统?
Windows Server 2019开启WSL并安装子系统
命令执行可能需要几分钟,系统设置完成后会提示是否重启,我们输入“Y”重启系统以完成设置
jwj
2022/05/18
2.3K0
Win11使用WSL2安装Ubuntu22.04并启用GUI应用
Windows Subsystem for Linux (WSL) 允许在几分钟内在 Windows 机器上安装完整的 Ubuntu 终端环境,无需离开 Windows 即可开发跨平台应用程序。
zhangrelay
2022/05/10
42.4K0
Win11使用WSL2安装Ubuntu22.04并启用GUI应用
双系统系列:WSL2-更换Linux安装路径
上次我们说到在Windows下通过WSL2下载安装Linux系统,有一个大家经常会在Windows遇到的问题,那就是C盘容量不足。
小Bob来啦
2022/01/17
5K0
双系统系列:WSL2-更换Linux安装路径
win10使用WSL编译Linux C++项目
我们是做后台开发的,虽然我们的svr都泡在tlinux上,但是大部分同学写代码/看代码还都是在windows下。
breezeliu
2018/11/04
9.8K0
Windows 11安装WSL 2子系统与常见错误处理
最近我安装了Windows 11操作系统。作为一名开发者,Windows提供的WSL可以说是必不可少的工具。然而,安装WSL并没有一帆风顺。本文将记录安装方法以及遇到的一些错误。
七辰
2023/09/11
9.3K0
Windows 11安装WSL 2子系统与常见错误处理
在 Windows 下使用 WSL2 搭建 Kubernetes 集群
本文我们将介绍如何在 Windows10 下使用 WSL2 和 KinD 来搭建一套 Kubernetes 集群。在过去几年,Kubernetes 已经成为了容器编排领域事实上的标准。虽然现在已经有各种各样的 Kubernetes 发行版本和安装程序来部署 Kubernetes 环境了,除了云环境或者裸机环境下面之外,我们仍然需要在本地部署和运行 Kubernetes 集群,特别是对于相关的开发人员。
我是阳明
2020/06/15
15.6K2
在 Windows 下使用 WSL2 搭建 Kubernetes 集群
Win11的WSL2系统更换磁盘和wsl使用简介
版本    Windows 11 家庭中文版 版本    22H2 安装日期    ‎2022/‎7/‎29 操作系统版本    22621.232
zhangrelay
2022/08/10
4K0
Win11的WSL2系统更换磁盘和wsl使用简介
WSL:在 Windows 系统中开发 Linux 程序的又一神器
作为一名嵌入式软件开发工程师,在 Linux 系统下写代码、编译、调试是避免不了的事情。
IOT物联网小镇
2021/08/13
1.9K0
WSL:在 Windows 系统中开发 Linux 程序的又一神器
微软更新Linux子系统,编译WSL 2内核只需3步
今年,微软在Build大会上向开发者放了两个“大招”:Windows Terminal和WSL 2。两个工具都是为了向开发者提供类似于Linux的体验。
量子位
2019/07/17
1.8K0
微软更新Linux子系统,编译WSL 2内核只需3步
一键网络重装系统 – 魔改版(适用于Linux / Windows)
一键网络重装系统 – 魔改版,它可以通过Internet重新安装Linux和Windows以及常见的操作系统。例如:Linux(CentOS,Debian,Ubuntu、etc..),Windows(2019、2016、2012R2、2008R2、7、2003、etc..),以及其他系统(不断支持更多中)。
用户2135432
2023/10/21
1.3K0
Windows 系统中安装 WSL 子系统
在 Windows 命令行窗口,输入指令:wsl --list --verbose(或者输入简化版本:wsl -l -v),得到结果:
时代疯
2021/07/22
3.3K0
搭建自己的本地云平台,QIIME2图形界面玩转16S分析(WSL2+Docker+Galaxy qiime2)
之前分享过一个 qiime2 studio 图形界面的笔记(QIIME2图形界面版(Q2STUDIO)),是 qiime2 团队自己造的轮子,不过最近 qiime2 团队好像转向了利用 galaxy 轮子QIIME 2 2021.4 发布(qiime2 支持 galaxy 啦),还把官方的宣传和安装视频转载到过公众号,不过之前没有加字幕,看起来还是有点困难的,重新加了中英文字幕并校对了下。
用户1075469
2022/11/08
1.2K0
搭建自己的本地云平台,QIIME2图形界面玩转16S分析(WSL2+Docker+Galaxy qiime2)
推荐阅读
相关推荐
[1275]WSL的安装与使用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验