【Flutter】三个Channel(Android-java / Ios-swift)

news/2024/7/20 20:55:25 标签: ios, flutter, android

Channel

实现与原生通信

【1】MethodChannel

flutter MethodChannel官方文档
通过MethodChannel来传递数据,调用方法

案例

分别调用Android和Ios原生的获取电量的方法

Flutter端

实例一个MethodChannel, 唯一标识name,定义方法名称getBatteryLevel
在这里插入图片描述
methodchannel.invokeMethod(name)来调用方法

  static const platform = MethodChannel('sample.flutter.dev/battery');
  static const method = 'getBatteryLevel';
  String _batteryLevel = 'Unknown battery level';

  Future<void> _getBatteryLevel() async {
    String batteryLevel;
    try {
      final result = await platform.invokeMethod<int>(method);
      batteryLevel = 'Battery level at $result';
    } on PlatformException catch (e) {
      batteryLevel = "Failed to get battery level: '${e.message}";
    }
    setState(() {
      _batteryLevel = batteryLevel;
    });
  }

界面操作

  
  Widget build(BuildContext context) {
    return Material(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          ElevatedButton(
            onPressed: _getBatteryLevel,
            child: const Text('Get Battery Level'),
          ),
          Text(_batteryLevel),
        ],
      ),
    );
  }
Android端

在这里插入图片描述

    private static final String CHANNEL = "sample.flutter.dev/battery";
    private MethodChannel methodChannel;

    private static final String METHOD = "getBatteryLevel";

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        BinaryMessenger binaryMessenger = flutterEngine.getDartExecutor().getBinaryMessenger();
        methodChannel = new MethodChannel(binaryMessenger, CHANNEL);
        methodChannel.setMethodCallHandler((call, result) -> {
            
        });
    }

在这里插入图片描述

if (call.method.equals(METHOD)) {
                int batteryLevel = getBatteryLevel();
                if (batteryLevel != -1) {
                    result.success(batteryLevel);
                } else {
                    result.error("UNAVAILABLE", "Battery level not avaiable", null);
                }
            } else {
                result.notImplemented();
            }
private int getBatteryLevel() {
        int batteryLevel = -1;
        if (VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
            batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
        } else {
            IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
            Intent intent = new ContextWrapper(getApplicationContext()).registerReceiver(null, intentFilter);
            batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /
                    intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
        }
        return batteryLevel;
    }
Ios端

实例FlutterMethodChannel
在这里插入图片描述

override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
      let method : String = "getBatteryLevel"
      let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
      let batteryChannel = FlutterMethodChannel(name: "sample.flutter.dev/battery", binaryMessenger: controller.binaryMessenger)
      batteryChannel.setMethodCallHandler({
          (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
          guard call.method == method else {
              result(FlutterMethodNotImplemented)
              return
          }
          self.receiveBatteryLevel(result: result)
      })
      GeneratedPluginRegistrant.register(with: self)
      return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

定义获取电量的方法

func receiveBatteryLevel(result: FlutterResult) -> Void {
        let device = UIDevice.current
        device.isBatteryMonitoringEnabled = true
        if device.batteryState == UIDevice.BatteryState.unknown {
            result(FlutterError(code: "UNAVAILABLE", message: "Battery level not available.", details: nil))
        } else {
            result(Int(device.batteryLevel * 100))
        }
    }
运行测试

在这里插入图片描述

【2】EventChannel

墙外的参考文章
区别MethodChannel,它是continuously
采用event streams

案例

在原生端(Android&Ios)会有个计时器,不停的传时间给Flutter端,Flutter端显示出来

Flutter端

实例一个EventChannel,唯一标识name
在这里插入图片描述

  late EventChannel eventChannel;

  
  void initState() {
    eventChannel = const EventChannel('timeHandlerEvent');
    super.initState();
  }

在Flutter注册监听
在这里插入图片描述

Stream<String> get streamTimeFromNative =>
      eventChannel.receiveBroadcastStream().map((event) => event.toString());

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: StreamBuilder<String>(
          stream: streamTimeFromNative,
          builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
            if (snapshot.hasData) {
              return Text(
                '${snapshot.data}',
                style: Theme.of(context).textTheme.headlineMedium,
              );
            } else {
              return const CircularProgressIndicator();
            }
          },
        ),
      ),
    );
  }
Ios端

实例一个FlutterEventChannel,加上唯一标识timeHandlerEvent
在这里插入图片描述

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
      let eventChannel = FlutterEventChannel(name: "timeHandlerEvent", binaryMessenger: controller.binaryMessenger)

定义FlutterStreamHandler

class TimeHandler: NSObject, FlutterStreamHandler {
        func onCancel(withArguments arguments: Any?) -> FlutterError? {
            return nil
        }
        
        func onListen(withArguments arguments: Any?, eventSink: @escaping FlutterEventSink) -> FlutterError? {
            return nil
        }
    }

每间隔1秒发送一次当前时间

    class TimeHandler: NSObject, FlutterStreamHandler {
        var timer = Timer()
        private var eventSink: FlutterEventSink?
        
        func onCancel(withArguments arguments: Any?) -> FlutterError? {
            eventSink = nil
            return nil
        }
        
        func onListen(withArguments arguments: Any?, eventSink: @escaping FlutterEventSink) -> FlutterError? {
            self.eventSink = eventSink
            self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: {_ in 
                let dateFormat = DateFormatter()
                dateFormat.dateFormat = "HH:mm:ss"
                let time = dateFormat.string(from: Date())
                eventSink(time)
            })
            return nil
        }
    }

注册监听

eventChannel.setStreamHandler(TimeHandler())

在这里插入图片描述

Android端

new 一个EventChannel对象
在这里插入图片描述
在channel注册一个stream Handler
在这里插入图片描述
在这里插入图片描述

        EventChannel.StreamHandler streamHandler = new EventChannel.StreamHandler() {
            @Override
            public void onListen(Object arguments, EventChannel.EventSink events) {
            }

            @Override
            public void onCancel(Object arguments) {
            }
        };
        eventChannel.setStreamHandler(streamHandler);

不断将当前时间返回
在这里插入图片描述

EventChannel.StreamHandler streamHandler = new EventChannel.StreamHandler() {
            private final Handler handler = new Handler(Looper.getMainLooper());

            private EventChannel.EventSink eventSink = null;

            @Override
            public void onListen(Object arguments, EventChannel.EventSink events) {
                eventSink = events;
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        Locale locale = new Locale("zh", "CN");
                        SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss", locale);
                        String time = dateFormat.format(new Date());
                        events.success(time);
                        handler.postDelayed(this, 1000);
                    }
                };
                handler.postDelayed(runnable, 1000);
            }

            @Override
            public void onCancel(Object arguments) {
                eventSink = null;
            }
        };
        eventChannel.setStreamHandler(streamHandler);
运行测试

在建立好EventChannel之后,运行项目。
在这里插入图片描述
获取到当前的时间,并且不停的

【3】BasicMessageChannel

参考文章
约定一种数据格式,来互相传递数据

案例

传递Map数据到Android/Ios端,再解析并返回数据到Flutter端

Flutter端

构建BasicMessageChannel, 唯一标识name,约定数据格式StandardMessageCodec

static const messageChannel =
      BasicMessageChannel('basic_message_channel', StandardMessageCodec());

发送数据

Map<String, dynamic> message = {
                  "name": "apple",
                  "time": "2024-04-09 12:30:00"
                };
messageChannel.send(arguments)

接收数据

Map reply = await messageChannel.send(arguments) as Map;

在这里插入图片描述

Android 端

接收数据

messageChannel.setMessageHandler((message, reply) -> {});

发送数据

reply.reply(resultMap);

在这里插入图片描述

package com.example.basic_message_channel_example;

import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.StandardMessageCodec;

public class MainActivity extends FlutterActivity {

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        BinaryMessenger binaryMessenger = Objects.requireNonNull(getFlutterEngine()).getDartExecutor().getBinaryMessenger();
        BasicMessageChannel<Object> messageChannel = new BasicMessageChannel<Object>(binaryMessenger, "basic_message_channel", StandardMessageCodec.INSTANCE);
        messageChannel.setMessageHandler((message, reply) -> {
            Map<Object, Object> arguments = (Map<Object, Object>) message;
            assert message != null;
            String name = (String) arguments.get("name");
            assert name != null;
            if (name.equals("apple")) {
                Map<String, Object> resultMap = new HashMap<>();
                String timeStr = (String) arguments.get("time");
                Timestamp timestamp = Timestamp.valueOf(timeStr);
                resultMap.put("message", "i eat the " + name + " at " + timestamp.toString());
                resultMap.put("code", 200);
                reply.reply(resultMap);
            } else {
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("message", "i dislike " + name);
                resultMap.put("code", 500);
                reply.reply(resultMap);
            }
        });
    }
}

Ios 端

构建通道

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let basicMessageChannel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: controller.binaryMessenger)

接收数据

      basicMessageChannel.setMessageHandler { message, reply in
          
      }

返回数据

reply(result)

在这里插入图片描述

import UIKit
import Flutter

@available(iOS 15.0, *)
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
      let channelName : String = "basic_message_channel"
      let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
      let basicMessageChannel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: controller.binaryMessenger)
      basicMessageChannel.setMessageHandler { message, reply in
          if let data = message as? Dictionary<String, Any> {
              let name: String = data["name"] as? String ?? ""
              if name == "apple" {
                  let timeStr: String = data["time"] as? String ?? ""
                  var message: String = "I eat the "
                  message.append(name)
                  message.append(" at ")
                  message.append(timeStr)
                  let result = ["code": 200, "message": message]
                  reply(result)
              } else {
                  var message = "I dislike "
                  message.append(name)
                  let result = ["code": 500, "message": message]
                  reply(result)
              }
          }
      }
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}
运行测试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

MethodChannel 定义方法名调用
EventChannel 持续监听数据传递
BasicMessageChannel 约定一种数据格式,传递数据


http://www.niftyadmin.cn/n/5478797.html

相关文章

abrt生成的文件很大处理方法

服务介绍 abrt 是 Automatic Bug Reporting Tool (ABRT) 的一个组成部分&#xff0c;用于捕获核心转储&#xff08;core dumps&#xff09;并帮助分析和报告程序崩溃的问题。 处理方法 如果 abrt-ccpp生成了非常大的文件&#xff0c;这通常意味着有程序崩溃了&#xff0c;并…

Django交易商场

Hello&#xff0c;我是小恒不会java 最近学习django&#xff0c;写了一个demo,学到了不少东西。 我在GitHub上开源了&#xff0c;提示‘自行查看代码&#xff0c;维护&#xff0c;运行’。 最近有事&#xff0c;先发布代码了&#xff0c;我就随缘维护更新吧 介绍&#xff1a; 定…

ChatGPT革新学术写作:论文撰写的新思路

ChatGPT无限次数:点击直达 ChatGPT革新学术写作&#xff1a;论文撰写的新思路 随着人工智能技术的不断发展&#xff0c;ChatGPT作为一种文本生成模型&#xff0c;为学术写作提供了全新的思路和方式。本文将探讨ChatGPT在论文撰写中的应用&#xff0c;展示其革新之处。 ChatGP…

Overlay网络与Underlay网络:深入探索与全面对比

在当今云原生的世界中&#x1f30d;☁️&#xff0c;网络是构建和维护任何分布式系统的基石&#x1f48e;。了解Overlay网络和Underlay网络及其之间的区别&#x1f50d;&#xff0c;对于设计高效、可扩展的云原生应用至关重要&#x1f680;。本文旨在全面解析Overlay和Underlay…

vue+springboot实现JWT登录验证

目录 前言概念实际演示路由信息初始访问登录界面登录验证验证过期 vue实现依赖引入main.js获取和设置token工具类登录方法实体登录方法axios请求 router配置 springboot实现依赖引入JWT工具类忽视jwt验证注解拦截器逻辑跨域&调用拦截器配置登录接口&验证token接口 结语…

sh与bash:Shell脚本中的微妙差异

在Unix和Linux的世界中&#xff0c;Shell是用户与操作系统交互的主要界面。Shell提供了命令行界面&#xff0c;使得用户能够执行各种命令和操作。在众多的Shell中&#xff0c;sh和bash是最常见且使用最广泛的两种。尽管它们在很多方面相似&#xff0c;但在功能、特性和语法上&a…

CodeMirror使用: 编写一个在线编辑HTML、JS、CSS文件,网页的模板页面-初实现

前言&#xff1a;前几天编写一个UI模板控制的功能&#xff0c;根据上传的前端模板更换跳转入口主题页面&#xff1b;在编写的时候&#xff0c;突发奇想能不能在列表页面进行在线编辑刚刚上传的模板zip压缩包里的页面...于是经过学习研究有了这篇文章&#xff1b;当日记本一样记…

计算机网络----第五天

广域网基本原理 局域网问题&#xff1a; 问题&#xff1a;以太网等局域网技术无法支持远程传输 广域网目的&#xff1a; 目的&#xff1a;基于电信运营商的通信网络设施建立远程连接 在相聚遥远的局域网之间建设连接性 广域网连接方式&#xff1a; 方式&#xff1a;电路交…