美文网首页
Flutter开发插件(swift、kotlin)

Flutter开发插件(swift、kotlin)

作者: 云醉倚清风 | 来源:发表于2023-03-23 11:02 被阅读0次

开发环境

flutter doctor                   
[✓] Flutter (Channel stable, 3.7.7,on macOS 13.1 22C65 darwin-x64, locale
    zh-Hans-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.1)
[✓] IntelliJ IDEA Ultimate Edition (version 2021.3)
[✓] VS Code (version 1.76.2)

一:新建插件工程

若已打开Android Studio:File->New->New Flutter Project->Next

  1. Project name:工程名 注意非驼峰命名,采用下划线连接(xx_xx_xx,lower_case_with_underscores)

  2. Project location:保存路径,文件夹名注意与Project name一致,若不改则使用Project name名称

  3. Description:工程介绍

  4. Project type:工程选择,这里选择plugin

  5. Organization:包名

二:iOS功能开发

1:开发目录确定

在项目根目录 example的iOS目录下执行pod install

cd example/ios

pod install

右键iOS,最底部Flutter -> Open iOS module in Xcode或者在文件夹example/ios中找到Runner.xcworkspace双击打开,这个时候就能看到Runner和Pod两个target。

  • Runner:example 可运行的主工程,用来测试插件的,用来Flutter启动iOS的

  • Pod:将插件生成本地pod库,用来调试

    点击展开Pod->Development Pods->...->Classes,一直到Classes就是我们插件代码放置的位置,可以看到已经生成的xxxPlugin.swift

2:定义方法

根目录的lib文件夹中自动生成的三个文件

  • xx_dart:项目调用插件的唯一途径

  • xx_method_channel:平台通道,将API暴露给Flutter应用程序,<u>若不需要跨端就直接在此处处理逻辑了</u>

  • xx_platform_interface:平台接口,定义了插件的API。

也是是我们的开发顺序是:xx_dart->xx_platform_interface->xx_method_channel

  1. xx_dart:定义我们此插件需要为别的项目提供哪些能力,也就是插件的api。

  2. xx_platform_interface:定义平台也就是原生端需要提供给插件的响应api,接口声明

  3. xx_method_channel:通过通道调用原生方法

原生去响应通道的方法:

  public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
    result("iOS " + UIDevice.current.systemVersion)
  }

已自动生成的方法,需要根据call.method判断Dart那边调用原生的方法。

学习方法使用,无非就是相互调用,参数互传。

思路:我需要插件帮我计算下a+b=?,插件需要2秒后给我个"hellow world"

xx.dart中定义方法

class xxPlayer {
  Future<String?> getPlatformVersion() {
    return xxPlayerPlatform.instance.getPlatformVersion();
  }
  // 原生去计算A+B
  Future<int?> sumAB(){
    return xxPlayerPlatform.instance.sumAB(a,b);
  }

  // 监听原生调用
  void listenNative(NativeCallBack nativeCallBack) {
    return EchoPlayerPlatform.instance.listenNative(nativeCallBack);
  }
}

xx_platform_interface.dart声明接口

Future<int?> sumAB(int a, int b) {
    throw UnimplementedError('sumAB() has not been implemented.');
  }

 void listenNative(NativeCallBack nativeCallBack) {
   throw UnimplementedError('startCount() has not been implemented.');
 }

xx_method_channel.dart重写实现接口,通道调用原生

 typedef NativeCallBack= void Function(dynamic result);

   @override
  Future<int?> sumAB(int a,int b) async {
    final result = await methodChannel
        .invokeMethod<int>('sumAB', {"a": a, "b": b});
    return result;
  }

 // 和fullter调用原生一样,都是通过通道通信的
  @override
  void listenNative(NativeCallBack nativeCallBack) {
    methodChannel.setMethodCallHandler((call) {
      if (call.method == 'countUp') {
        nativeCallBack(call.arguments);
      }
      return Future(() => null);
    });
  }

xxPlugin.swift中实现方法

 public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        if call.method == "sumAB" {
            // 取参数  插件接口已定义必填,可强制拆包
            let args = call.arguments as! [String: Int]
            let a = args["a"]!
            let b = args["b"]!
            result(sumAB(a: a, b: b))
            // 执行方法并回调
            result(sumAB(a: a, b: b))
        } else if call.method == "startCount" {
           // 定时器模拟重复调用的场景,延迟或者其他情况直接使用channel.invokeMethod即可
            countTime()
        }
        result("iOS " + UIDevice.current.systemVersion)
 }
 public func sumAB(a: Int, b: Int) -> Int {
    return a + b
 }
 var count = 0
 public func countTime() {
   Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(sendToFlutter), userInfo: nil, repeats: true)
 }

 @objc func sendToFlutter() {
    count += 1
    channel!.invokeMethod("countUp", arguments: ["count": count])
  }

exmaple/main.dart 调用测试

TextButton(
     onPressed: () {
       _xxPlugin
        .sumAB(3, 4)
        .then((value) => {debugPrint(value.toString())});
       },
      child: const Text("SumAB"))

 TextButton(
        onPressed: () {
          //开启定时计数
          _echoPlayerPlugin.startCount();
         //监听计数回调
          _echoPlayerPlugin.listenNative((result) {
             print(result);
            });
           },
       child: const Text("countUp"))

三:Android功能开发

在工程example/android 上右键open Android module in Android studio,依赖加载有些久,打开后就可以看到我们其实要开发的就是个Android的module。

Android这边要好些的是channel已经是是变量,可以直接主动像flutter发送消息

class XXPlugin: FlutterPlugin, MethodCallHandler {
  /// The MethodChannel that will the communication between Flutter and native Android
  ///
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private lateinit var channel : MethodChannel

  //注册通道
  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "echo_player")
    channel.setMethodCallHandler(this)
  }

  override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
    if (call.method == "getPlatformVersion") {
      result.success("Android ${android.os.Build.VERSION.RELEASE}")
    }
    else {
      result.notImplemented()
    }
  }

//注销通道
  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    channel.setMethodCallHandler(null)
  }
}

sumABstartCount的实现


    override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
        if (call.method == "getPlatformVersion") {
            result.success("Android ${android.os.Build.VERSION.RELEASE}")
        } else if (call.method == "sumAB") {
            // 获取传递的参数
            val args = call.arguments as? Map<String, Int>
            val a = args?.get("a")
            val b = args?.get("b")
            if (a != null && b != null) {
                result.success(a + b)
            }
        } else if (call.method == "startCount") {
            // 定时器模拟重复调用的场景,延迟或者其他情况直接使用channel.invokeMethod即可
            countTime()
        } else {
            result.notImplemented()
        }
    }

    fun countTime() {
        val timer = Timer()
        val delay = 0L // 0 second delay
        val period = 1000L // 1 second interval

        // 回去主线程 否则会崩溃
        val handler = android.os.Handler(Looper.getMainLooper())

        val task = object : TimerTask() {
            override fun run() {
                handler.post{
                    count++
                    channel.invokeMethod("countUp", mapOf("count" to count))
                }

            }
        }
        timer.scheduleAtFixedRate(task, delay, period)
    }

相关文章

网友评论

      本文标题:Flutter开发插件(swift、kotlin)

      本文链接:https://www.haomeiwen.com/subject/iurirdtx.html