android,flutter 混合开发,pigeon通信,传参

news/2025/2/21 2:58:43

文章目录

        • app效果
        • native和flutter通信的基础知识
          • 1. 编解码器 一致性和完整性,安全性,性能优化
          • 2. android代码
          • 3. dart代码
        • 1. 创建flutter_module
        • 2.修改 Android 项目的 settings.gradle,添加 Flutter module
        • 3. 在 Android app 的 build.gradle 中添加依赖
        • 4. 原生和flutter_module通信BasePlugin
        • 5. io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister 自动注册插件
        • 6 手动注册
        • 7. 通信关闭flutter页面
        • 8. dartEntrypointArgs传入参数
        • 9. 通信传入参数
          • 9.1 发送参数
          • 9.1 接收参数
        • 10. android代码
        • 11 源码

app效果
在这里插入图片描述
flutter_5">native和flutter通信的基础知识

低级的消息通道,一般不直接使用
ServicesBinding.instance.defaultBinaryMessenger
高级别的消息通道,对defaultBinaryMessenger进行了封装,提供的更简单的api发送和接收消息
BasicMessageChannel MethodChannel EventChannel
MethodChannel EventChannel底层都是基于BasicMessageChannel

1. 编解码器 一致性和完整性,安全性,性能优化

MethodChannel,EventChannel->StandardMethodCodec
BasicMessageChannel->StandardMessageCodec
StandardMessageCodec:支持基本的数据类型(字符串、数字、布尔值、字节数组、列表、映射等)。
StandardMethodCodec:除了支持基本的数据类型外,还支持方法调用的参数和返回结果的编码和解码。
StringCodec:由于只处理字符串,StringCodec 的实现更为简单,性能更高

android_20">2. android代码
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        basicMessageChannel = BasicMessageChannel(flutterEngine.dartExecutor.binaryMessenger, BASIC_CHANNEL, StringCodec.INSTANCE)
        //创建MethodChannel
        methodChannel =
            MethodChannel(flutterEngine.dartExecutor, BASIC_CHANNEL, StandardMethodCodec.INSTANCE)

        //创建EventChannel
        eventChannel = EventChannel(flutterEngine.dartExecutor, BASIC_CHANNEL)


        basicMessageChannel.send("dddd")
        basicMessageChannel.setMessageHandler { message, reply ->
            reply.reply("dddd")
            Log.e("dddd", message.toString())
        }

        methodChannel.invokeMethod("getPlatformVersion", null)
        methodChannel.setMethodCallHandler { call, result ->
            when (call.method) {
                "getPlatformVersion" -> {
                    result.success("Android ${android.os.Build.VERSION.RELEASE}")
                }

                else -> {
                    result.notImplemented()
                }
            }
        }

        eventChannel.setStreamHandler(object : EventChannel.StreamHandler {
            override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
                eventSink = events
                eventSink?.success("Event")
            }

            override fun onCancel(arguments: Any?) {
                eventSink = null
            }
        })

    }
3. dart代码
class _StudyChannelState extends State<StudyChannel> {
  MethodChannel methodChannel = const MethodChannel('base_plugin');
  EventChannel eventChannel = const EventChannel('base_plugin');
  static const basicMessageChannel = BasicMessageChannel<String>('base_plugin', StringCodec());  
  void initState() {
    super.initState();
    //只接收
    eventChannel.receiveBroadcastStream().listen((value){

    });

    //监听
    methodChannel.setMethodCallHandler((call){
      call.method == "getData" ? print("getData") : print("method=$call");
      return Future.value("methodChannel=$call");
    });
    //执行,相当于发送
    methodChannel.invokeListMethod("getData");

    //发送
    basicMessageChannel.send("data");
    //监听
    basicMessageChannel.setMessageHandler((message){
      return Future.value("basicMessageChannel=$message");
    });

  }
  
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}
flutter_module_100">1. 创建flutter_module

File->New->New Flutter Project
name为flutter_module
选择project type为module

2.修改 Android 项目的 settings.gradle,添加 Flutter module
pluginManagement {
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
    repositories {
        google()
        mavenCentral()
        maven(url = "https://storage.googleapis.com/download.flutter.io")
    }
}

rootProject.name = "hunheandroid"
include(":app")
//主要是这一句
apply(from = "../flutter_module/.android/include_flutter.groovy")
3. 在 Android app 的 build.gradle 中添加依赖
dependencies {
    implementation(project(":flutter"))
}
flutter_moduleBasePlugin_149">4. 原生和flutter_module通信BasePlugin

参考文章生成对应的io/flutter/plugins/Messages.g.kt
用pigeon kotlin swift写一个自己的插件
拷贝BasePlugin

package io.flutter.plugins

import android.app.Activity
import android.util.Log
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding


/** BasePlugin */
/** BasePlugin */
class BasePlugin : FlutterPlugin, HostMessageApi, ActivityAware {

    companion object {
        private var flutterMessageApi: FlutterMessageApi? = null
        fun getFlutterMessageApi(): FlutterMessageApi? {
            return flutterMessageApi
        }
    }

    private var activity: Activity? = null
    private var tag = "BasePlugin"
    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        Log.e(tag, "onAttachedToEngine-start")
        HostMessageApi.setUp(flutterPluginBinding.binaryMessenger, this)
        flutterMessageApi = FlutterMessageApi(flutterPluginBinding.binaryMessenger)
        Log.e(tag, "onAttachedToEngine-end")
    }

    override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
        HostMessageApi.setUp(binding.binaryMessenger, null)
    }

    override fun flutter2Native(message: String, type: Long): String {
        print("flutter2Native=message=start=>$message=type=$type")
        return "flutter2Native=message=$message=type=$type"
    }

    override fun flutter2NativeAsync(
        message: String,
        type: Long,
        callback: (Result<String>) -> Unit
    ) {
        print("flutter2NativeAsync=message=$message=type=$type")
        callback(Result.success("flutter2NativeAsync=message=$message=type=$type"))
        if (type == 1L) {
            closeCurrentActivity()
        }
    }

    private fun closeCurrentActivity() {
        activity?.finish()
    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        this.activity = binding.activity
    }

    override fun onDetachedFromActivityForConfigChanges() {

    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {

    }

    override fun onDetachedFromActivity() {
        this.activity = null
    }
}
flutterembeddingenginepluginsutilGeneratedPluginRegister__233">5. io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister 自动注册插件
 public static void registerGeneratedPlugins(@NonNull FlutterEngine flutterEngine) {
    try {
      Class<?> generatedPluginRegistrant =
          Class.forName("io.flutter.plugins.GeneratedPluginRegistrant");
      Method registrationMethod =
          generatedPluginRegistrant.getDeclaredMethod("registerWith", FlutterEngine.class);
      registrationMethod.invoke(null, flutterEngine);
    } catch (Exception e) {
      Log.e(
          TAG,
          "Tried to automatically register plugins with FlutterEngine ("
              + flutterEngine
              + ") but could not find or invoke the GeneratedPluginRegistrant.");
      Log.e(TAG, "Received exception while registering", e);
    }
  }
package io.flutter.plugins;

import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import io.flutter.Log;

import io.flutter.embedding.engine.FlutterEngine;

/**
 * Generated file. Do not edit.
 * This file is generated by the Flutter tool based on the
 * plugins that support the Android platform.
 */
@Keep
public final class GeneratedPluginRegistrant {
  private static final String TAG = "GeneratedPluginRegistrant";
  public static void registerWith(@NonNull FlutterEngine flutterEngine) {
    try {
      Log.e(TAG, "registerWith-start");
      flutterEngine.getPlugins().add(new BasePlugin());
      Log.e(TAG, "registerWith-end");
    } catch (Exception e) {
      Log.e(TAG, "Error registering plugin base_plugin, com.app.base_plugin.BasePlugin", e);
    }
  }
}

6 手动注册

flutterEngine.getPlugins().add(new BasePlugin());

flutter_287">7. 通信关闭flutter页面

使用flutter和原生通信,在收到消息以后,关闭当前页面
BasePlugin实现ActivityAware,获取到activity
在收到flutter传入进来的消息的时候关闭activity

8. dartEntrypointArgs传入参数
//跳转带入参数
val initialRoute = listOf(  
                "aaa",
                "bbbb"
            )
            startActivity(
                withNewEngine()
                    .dartEntrypointArgs(initialRoute)  
                    .build(this)
            )
//args就是传入的参数
void main(List<String> args){
  print("args=$args");
  runApp(const MyApp());
}
9. 通信传入参数
9.1 发送参数
 val initialRoute = listOf(  
                "/page2",
                "bbbb"
            )
            BasePlugin.getFlutterMessageApi()?.native2Flutter(initialRoute.joinToString("#"), 1){
                Log.e(tag, "flutter2NativeAsync: $it")
                FlutterLibrary.startFlutterPage(this)
            }
9.1 接收参数

class RouterPage extends StatefulWidget {
 
  const RouterPage({super.key});

  
  State<RouterPage> createState() => _RouterPageState();
}

class _RouterPageState extends State<RouterPage> implements FlutterMessageApi {
  late String args;

  
  void initState() {
    super.initState();
    FlutterMessageApi.setUp(this);
  }

  
  String native2Flutter(String message, int type) {
    print("native2Flutter=$message $type");
    setState(() {
      args = message;
    });

    return "我是原生调用flutter方法返回的值=》native2Flutter";
  }

  
  Future<String> native2FlutterAsync(String message, int type) {
    args = message;
    print("native2Flutter=$message $type");
    return Future.value("我是原生调用flutter方法返回的值=》native2FlutterAsync");
  }

  
  Widget build(BuildContext context) {
    // final value = widget.args.isNotEmpty ? widget.args[0] : "/";
    if (args.isEmpty||!args.contains("#")) {
      return MyHomePage(title: "首页");
    }
    final value = args.split("#").first;
    switch (value) {
      case '/page2':
        return SecondPage();
    }
    print("_RouterPageState=build");
    return MyHomePage(title: "首页");
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>  {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  
  void initState() {
    super.initState();
  }

  
  Widget build(BuildContext context) {
    print("_MyHomePageState=build");
    return Scaffold(
      appBar: AppBar(title: Text(widget.title), leading: BackButton()),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextButton(
              onPressed: () {
                BasePlugin.flutter2NativeAsync("flutter2NativeAsync", 1).then((
                  value,
                ) {
                  print("flutter2NativeAsync=$value");
                });
              },
              child: Text('flutter2NativeAsync'),
            ),
            TextButton(
              onPressed: () {
                Navigator.of(context).pushNamed("/page2");
              },
              child: Text('flutter2NativeAsync'),
            ),
            const Text('You have pushed the button this many times:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

}

class SecondPage extends StatelessWidget {
  const SecondPage({super.key});

  
  Widget build(BuildContext context) {
    print("SecondPage=build");
    return Scaffold(
      appBar: AppBar(title: Text("SecondPage")),
      body: Center(
        child: TextButton(
          onPressed: () {
            Navigator.of(context).pop();
          },
          child: Text('关闭'),
        ),
      ),
    );
  }
}

android_468">10. android代码
package com.example.hunheandroid

import android.app.Application
import android.content.Context
import android.content.Intent
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.embedding.engine.FlutterEngineGroup
import io.flutter.embedding.engine.dart.DartExecutor
import io.flutter.plugins.BasePlugin

const val ENGINE_ID = "my_engine_id"
object FlutterLibrary {
    fun init(application: Application) {
        FlutterEngineManager.getInstance().init(application)
    }
    fun startFlutterPage(context: Context) {
        val intent = FlutterActivity
            .withCachedEngine(ENGINE_ID)
            .build(context).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(intent)
    }
}

// FlutterEngineManager.kt
class FlutterEngineManager private constructor() {
    private lateinit var engineGroup: FlutterEngineGroup
    private var engine: FlutterEngine? = null

    companion object {
        private var instance: FlutterEngineManager? = null

        fun getInstance(): FlutterEngineManager {
            return instance ?: synchronized(this) {
                instance ?: FlutterEngineManager().also { instance = it }

            }
        }
    }
    fun init(application: Application) {
        engineGroup = FlutterEngineGroup(application)
        engine = engineGroup.createAndRunEngine(
            application,
            DartExecutor.DartEntrypoint.createDefault()
        )
        FlutterEngineCache.getInstance().put(ENGINE_ID, engine)
        engine!!.plugins.add(BasePlugin())

    }

    fun getEngine(): FlutterEngine? {
        return engine
    }

    fun destroyEngine() {
        engine?.destroy()
        engine = null
    }
}

class GoFlutterActivity : FlutterActivity(), HostMessageApi {

    private val tag = "GoFlutterActivity"
    private lateinit var binding: ActivityGoFlutterBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityGoFlutterBinding.inflate(layoutInflater)

        setContentView(binding.root)
        binding.goFlutter.setOnClickListener {
            //跳转到flutter
            val initialRoute = listOf(  // Map 形式的参数
                "/",
                "aaaa"
            )
            BasePlugin.getFlutterMessageApi()?.native2Flutter(initialRoute.joinToString("#"), 1) {
                Log.e(tag, "flutter2NativeAsync: $it")
                FlutterLibrary.startFlutterPage(this)
            }

        }

        binding.goFlutter2.setOnClickListener {
            //跳转到flutter
            val initialRoute = listOf(  // Map 形式的参数
                "/page2",
                "bbbb"
            )
            BasePlugin.getFlutterMessageApi()?.native2Flutter(initialRoute.joinToString("#"), 1) {
                Log.e(tag, "flutter2NativeAsync: $it")
                FlutterLibrary.startFlutterPage(this)
            }

        }
    }

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        Log.e(tag, "configureFlutterEngine")
//        GeneratedPluginRegistrant.registerWith(flutterEngine)
    }

    override fun flutter2Native(message: String, type: Long): String {
        Log.e(tag, "$message$type")
        return "我是flutter调用原生方法的返回值=》flutter2Native"
    }

    override fun flutter2NativeAsync(
        message: String,
        type: Long,
        callback: (Result<String>) -> Unit
    ) {
        Log.e(tag, "$message$type")
        callback(Result.success("我是flutter调用原生方法的返回值=》flutter2NativeAsync"))

    }


}
11 源码

gitee


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

相关文章

常用的 React Hooks 的介绍和示例

目录 1. useState2. useEffect3. useContext4. useReducer5. useCallback6. useMemo7. useRef8. useImperativeHandle9. useLayoutEffect10. useDebugValue 常用的 React Hooks 的介绍和示例&#xff1a; 1. useState useState 是一个用于在函数组件中添加状态的 Hook。 impo…

面试题之手写call,apply,bind

在面试中&#xff0c;手写call&#xff0c;apply&#xff0c;bind是常见的题目&#xff0c;主要考察对JavaScript中函数上下文&#xff08;this&#xff09;和参数传递的理解。对于我这个小菜鸟来说&#xff0c;这无疑也是一道难题呢&#xff0c;嘤嘤嘤 1. 手写 call call 方法…

《DeepSeek-V3:人工智能大语言模型》

《DeepSeek-V3:人工智能大语言模型》 1. 引言 我们介绍了 DeepSeek-V3,这是一个强大的专家混合 (MoE) 语言模型,总共有 671B 个参数,每个令牌激活了 37B。 为了实现高效的推理和具有成本效益的训练,DeepSeek-V3 采用了多头潜在注意力 (MLA) 和 DeepSeekMoE 架构,这些…

Spring Boot中API响应结构的最佳实践

在Spring Boot应用程序中&#xff0c;设计一个清晰、一致的API响应结构是确保代码可维护性和可扩展性的关键。本文将探讨如何在Spring Boot中构建最佳的API响应结构&#xff0c;以便于前端开发人员理解和使用&#xff0c;同时为后端开发人员提供灵活的扩展能力。 1. 标准化的响…

java网络编程02 - HTTP、HTTPS详解

HTTP、HTTPS详解 文章目录 HTTP、HTTPS详解一&#xff1a;HTTP超文本传输协议1&#xff1a;HTTP协议的工作流程2&#xff1a;URI和URL2.1&#xff1a;DNS域名解析 3&#xff1a;HTTP报文的组成结构3.1&#xff1a;请求报文3.2&#xff1a;响应报文3.3&#xff1a;HTTP报文字段3…

高德地图android sdk(备忘)

依赖 // 权限请求框架&#xff1a;https://github.com/getActivity/XXPermissions implementation com.github.getActivity:XXPermissions:20.0 // https://mvnrepository.com/artifact/com.amap.api/navi-3dmap-location-search implementation com.amap.api:navi-3dmap-loca…

当Qt遇见IOCP:用C++打造高并发服务器

一、为什么选择IOCP技术&#xff1f; 在Windows平台开发高并发网络服务时&#xff0c;许多开发者都会遇到这样的困境&#xff1a;当需要同时处理成千上万的客户端连接时&#xff0c;传统的select模型或普通线程池方案会遭遇性能瓶颈。这正是IOCP&#xff08;Input/Output Comp…

从猜想终结到算法革新,弹性哈希开启数据存储新篇章

目录 哈希表的前世今生基本原理从传统到现代&#xff1a;哈希表的演变历程 安德鲁 克拉皮文及其团队的创作历程弹性哈希详解基本原理优点技术细节 漏斗哈希解析基本原理优点技术细节 新算法的实际应用案例电子商务推荐系统金融交易监控系统社交媒体内容过滤物联网设备管理 结论…