写点什么

Flutter- 插件开发:以微信 SDK 为例,android 音频面试题

作者:嘟嘟侠客
  • 2021 年 11 月 27 日
  • 本文字数:4783 字

    阅读完需:约 16 分钟

super.initState();initPlatformState();}


// Platform messages are asynchronous, so we initialize in an async method.Future<void> initPlatformState() async {String platformVersion;// Platform messages may fail, so we use a try/catch PlatformException.try {platformVersion = await Wechat.platformVersion;} on PlatformException {platformVersion = 'Failed to get platform version.';}


// If the widget was removed from the tree while the asynchronous platform// message was in flight, we want to discard the reply rather than calling// setState to update our non-existent appearance.if (!mounted) return;


setState(() {_platformVersion = platformVersion;});}


@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: const Text('Plugin example app'),),body: Center(child: Text('Running on: $_platformVersion\n'),),),);}}


这里需要特别注意的就是?initPlatformState()?方法中对?Wechat.platformVersion?的调用,这里面的?Wechat?就是我们的插件,platformVersion?就是插件提供的?get?方法,跟着这个文件,找到?lib/wechat.dart?文件,代码如下:


import 'dart:async';


import 'package:flutter/services.dart';


class Wechat {static const MethodChannel _channel =const MethodChannel('wechat');


static Future<String> get platformVersion async {final String version = await _channel.invokeMethod('getPlatformVersion');return version;}}


在该文件中,可以看到 class Wechat 定义了一个 get 方法 platformVersion,它的函数体有点特别:


final String version = await _channel.invokeMethod('getPlatformVersion');return version;


我们的?version?是通过?_channel.invokeMethod('getPlatformVersion')?方法的调用得到的,这个?_channel?就是我们 Dart 代码与 原生代码进行通信的桥了,也是 Flutter 原生插件的核心(当然,如果你编写的插件并不需要原生代码相关的功能,那么,_channel?就是可有可无的了,比如我们可以写一个下面这样的方法,返回 两个数字?a?与?b?的和:


class Wechat {...static int calculate (int a, int b) {return a + b;}}


之后,修改 example/lib/main.dart 代码:


class _MyAppState extends State<MyApp> {String _platformVersion = 'Unknown';// 定义一个 int 型变量,用于保存计算结果 int _calculateResult;


@overridevoid initState() {super.initState();initPlatformState();}


Future<void> initPlatformState() async {String platformVersion;try {platformVersion = await Wechat.platformVersion;} on PlatformException {platformVersion = 'Failed to get platform version.';}


if (!mounted) return;// init 的时候,计算一下 10 + 10 的结果_calculateResult = Wechat.calculate(10, 10);


setState(() {_platformVersion = platformVersion;});}


@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: const Text('Plugin example app'),),body: Container(padding: EdgeInsets.all(16.0),child: SingleChildScrollView(child: Column(children: <Widget>[Text('Running on: _calculateResult\n'),],),),),),);}}

支持原生编码提供的方法

很多时候,写插件,更多的是因为我们需要让应用能够调用原生代码提供的方法,怎么做呢?

Android 系统

打开?android/src/main/java/com/example/wechat/WechatPlugin.java?文件,看如下代码:


package com.example.wechat;


import io.flutter.plugin.common.MethodCall;import io.flutter.plugin.common.MethodChannel;import io.flutter.plugin.common.MethodChannel.MethodCallHandler;import io.flutter.plugin.common.MethodChannel.Result;import io.flutter.plugin.common.PluginRegistry.Registrar;


/** WechatPlugin /public class WechatPlugin implements MethodCallHandler {/* Plugin registration. */public static void registerWith(Registrar registrar) {final MethodChannel channel = new MethodChannel(registrar.messenger(), "wechat");channel.setMethodCallHandler(new WechatPlugin());}


@Overridepublic void onMethodCall(MethodCall call, Result result) {if (call.method.equals("getPlatformVersion")) {result.success("Android " + android.os.Build.VERSION.RELEASE);} else {result.notImplemented();}}}


还记得上面提到的?getPlatformVersion?吗?还记得?_channel?那么,是不是在这里面也看到的对应的存在?没错,?dart?中的?getPlatformVersion?通过?_channel.invokeMethod?发起一次请求,然后,Java?代码中的?onMethodCall?方法回被调用,该方法有两个参数:


MethodCall call:请求本身 Result result:结果处理方法然后通过?call.method?可以知到?_channel.invokeMethod?中的方法名,然后通过?result.success?回调返回成功结果响应。


registerWith


在上面还有一小段代码 registerWith,可以看到里面有一个调用:


final MethodChannel channel = new MethodChannel(registrar.messenger(), "wechat");channel.setMethodCallHandler(new WechatPlugin());


这里就是在注册我们的插件,将 wechat 注册成为我们的 channel 名,这样,才不会调用 alipay 插件的调用最后到了 wechat 插件这里。###iOS 系统同样的,这次我们打开 ios/Classes/WechatPlugin.m 文件:


#import "WechatPlugin.h"


@implementation WechatPlugin


  • (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>)registrar {FlutterMethodChannel channel = [FlutterMethodChannelmethodChannelWithName:@"wechat"binaryMessenger:[registrar messenger]];WechatPlugin* instance = [[WechatPlugin alloc] init];[registrar addMethodCallDelegate:instance channel:channel];}


  • (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {if ([@"getPlatformVersion" isEqualToString:call.method]) {result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);} else {result(FlutterMethodNotImplemented);}}


@end


虽然语法有所不同,但是,可以看到,跟?android?的 Java 代码结构上几乎是一模一样的,首先?register?一个名为?wechat?的?channel,然后去?handleMethodCall,同样的通过?call.method 拿到方法名,通过?result?做出响应。


###小试牛刀接下来,我们将前面的?caculate?方法,移到原生代码中来提供(虽然这很没必要,但毕竟,只是为了演示嘛)。


###Android 在前面打开的?android/src/main/java/com/example/wechat/WechatPlugin.java?文件中,修改?onMethodCall?方法:


@Overridepublic void onMethodCall(MethodCall call, Result result) {if (call.method.equals("getPlatformVersion")) {result.success("Android " + android.os.Build.VERSION.RELEASE);} else if (call.method.equals("calculate")) {int a = call.argument("a");int b = call.argument("b");int r = a + b;result.success("" + r);} else {result.notImplemented();}}


添加了?call.method.equals("calculate")?判断,这里面具体的过程是:


调用?call.argument()?方法,可以取得由?wechat.dart?传递过来的参数计算结果调用?result.success()?响应结果然后,我们需要在?lib/wechat.dart?中修改?calculate?方法的实现,代码如下:


static Future<int> calculate (int a, int b) async {final String result = await _channel.invokeMethod('calculate', {'a': a,'b': b});return int.parse(result);}


由于?_channel.invokeMethod?是一个异步操作,所以,我们需要将?calculate?的返回类型修改为?Future,同时加上?async,此时我们就可以直接使用?await?关键字了,跟?JavaScript?中的?await?一样,让我们用同步的方式编写异步代码,在新版的?calculate?代码中,我们并没有直接计算?a+b?的结果,而是调用?_channel.invokeMethod?方法,将?a?与?b?传递给了?Java?端的?onMethodCall?方法,然后返回该方法返回的结果。_channel.invokeMethod


该方法接受两个参数,第一个定义一个方法名,它是一个标识,简单来说,它告诉原生端的代码,我们这次是要干什么,第二个参数是一个?Map<String, dynamic>?型数据,是参数列表,我们可以在原生代码中获取到。


接着,我们需要更新一下对该方法的调用了,回到?example/lib/main.dart?中,修改成如下调用:


_calculateResult = await Wechat.calculate(10, 10);


因为我们现在的?calculate?方法已经是一个异步方法了。

iOS

如果我们的插件需要支持?Android?与?IOS?两端,那么需要同步的在?ios?中实现上面的方法,打开?ios/Classes/WechatPlugin.m?文件,作如下修改:


  • (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {NSDictionary *arguments = [call arguments];if ([@"getPlatformVersion" isEqualToString:call.method]) {result(


《Android 学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享


[@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);} else if ([@"calculate" isEqualToString:call.method]) {NSInteger a = [arguments[@"a"] intValue];NSInteger b = [arguments[@"b"] intValue];result([NSString stringWithFormat:@"%d", a + b]);} else {result(FlutterMethodNotImplemented);}}


实现过程与?java?端保持一致即可。

添加第三方 SDK

我们的插件是可以提供微信的分享相关功能的,所以,肯定需要用到第三方 SDK,还是从 Android 开始。

Android 端 WechatSDK

按?官方接入指南?所述,我们需要添加依赖:


dependencies {compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'}



dependencies {compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'}


前者带有统计功能,这很简单,打开 android/build.gradle 文件 ,在最下方粘贴以上片段即可:


...android {compileSdkVersion 27


defaultConfig {minSdkVersion 16testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"}lintOptions {disable 'InvalidPackage'}}


dependencies {compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'}


然后,回到 WechatPlugin.java 文件,先添加一个 register 方法,它将我们的 Appid 注册给微信,还是接着前面的 onMethodCall 中的 if 判断:


...import com.tencent.mm.opensdk.openapi.WXAPIFactory;...else if (call.method.equals("register")) {appid = call.argument("appid");api = WXAPIFactory.createWXAPI(context, appid, true);result.success(api.registerApp(appid));

最后

现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务 Curd 而已!现如今市场上初级程序员泛滥,这套教程针对 Android 开发工程师 1-6 年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶 Android 中高级、架构师对你更是如鱼得水!


为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!


Android 架构师之路很漫长,一起共勉吧!


本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

用户头像

嘟嘟侠客

关注

还未添加个人签名 2021.03.19 加入

还未添加个人简介

评论

发布
暂无评论
Flutter-插件开发:以微信SDK为例,android音频面试题