美文网首页
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