在Flutter中调用Android的代码

参考

【Flutter 混合开发】嵌入原生View-Android

默认使用Android studioKotlin

基本配置

创建flutter项目

在终端执行

flutter create batterylevel

添加 Android 平台的实现

打开项目下的android/app/src/main/kotlin 下的 MainActivity.kt 文件。
在这里插入图片描述
我这里编辑器有提示,最好使用其推荐,这样代码会有提示
在这里插入图片描述
使用推荐后会新打开一个窗口,在原窗口里提示的错误也将不会再提示

MainActivity.kt

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngineclass MainActivity : FlutterActivity() {// 在flutter引擎启动时,将自定义的插件添加到flutter 引擎的插件列表中override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)flutterEngine.plugins.add(MyPlugin())}
}

在项目文件下创建MyFlutterView.ktMyFlutterViewFactory.ktMyPlugin.kt 三个文件

  • MyFlutterView.kt编写的是原生安卓代码
  • MyFlutterViewFactory.kt一个自定义的Flutter平台视图工厂,用于创建创建Flutter平台视图并将其返回
  • MyPlugin.kt 创建一个自定义的Flutter插件,将自定义的Flutter平台视图工厂注册到Flutter引擎中,以便在Flutter应用中使用该自定义视图。
    在这里插入图片描述

MyFlutterView.kt

import android.content.Context
import android.view.View
import android.widget.TextView
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.platform.PlatformView// context 上下文对象
// messenger 用于消息传递,BinaryMessenger二进制消息
// viewId View 生成时会分配一个唯一 ID
// args Flutter 传递的初始化参数
class MyFlutterView(context: Context,messenger: BinaryMessenger,viewId: Int,args: Map<String, Any>?
) :PlatformView {// PlatformView代表一个平台视图,它是Flutter和原生平台之间的桥梁。// PlatformView允许在Flutter应用中嵌入原生视图,并提供了与Flutter框架进行交互的方法。// 定义一个文本视图private val textView: TextView = TextView(context)init {// 初始化文本视图textView.text = "我是Android View"}// 获取文本视图override fun getView(): View {return textView}//  销毁override fun dispose() {}
}

MyFlutterViewFactory.kt

import android.content.Context
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory// 用于注册PlatformView
class MyFlutterViewFactory(private val messenger: BinaryMessenger) : PlatformViewFactory(StandardMessageCodec.INSTANCE
) {// 创建PlatformViewoverride fun create(context: Context, viewId: Int, args: Any?): PlatformView {return MyFlutterView(context, messenger, viewId, args as Map<String, Any>?)}}

MyPlugin.kt

"com.example.batterylevel/custom_platform_view" 是自定义平台视图的标识符,需要保证唯一。
标识符通常由小写字母、数字和斜杠(/)组成,并且不包含空格或特殊字符。
具体如何编写没查到,参考文章应该是 按着包名/视图的描述的格式,感觉挺好的

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.PluginRegistryclass MyPlugin : FlutterPlugin {// onAttachedToEngine 在Flutter插件与Flutter引擎绑定时被调用。// 在这个方法中,可以执行一些初始化操作,例如注册平台视图工厂、注册方法调用处理器等override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {// 消息发送器val messenger: BinaryMessenger = binding.binaryMessenger//binding.platformViewRegistry.registerViewFactory("com.example.batterylevel/custom_platform_view", MyFlutterViewFactory(messenger))}// 注册视图companion object {fun registerWith(registrar: PluginRegistry.Registrar) {registrar.platformViewRegistry().registerViewFactory("com.example.batterylevel/custom_platform_view",MyFlutterViewFactory(registrar.messenger()))}}// 用于在插件从 Flutter 引擎中分离时执行清理操作。// 当插件不再需要与 Flutter 引擎通信时,例如应用关闭或插件被移除时,onDetachedFromEngine 方法会被调用。override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {}
}

基本内容编写完成后回到flutter项目的部分,进行运行
main.dart

void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});// This widget is the root of your application.Widget build(BuildContext context) {return MaterialApp(title: '嵌入原生View-Android',theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),useMaterial3: true,),home: const PlatformViewDemo(),);}
}class PlatformViewDemo extends StatelessWidget {const PlatformViewDemo({super.key});Widget build(BuildContext context) {platformView() {// 如果是安卓平台,则返回一个AndroidView对象// AndroidView 是 Flutter 提供的一个小部件,用于在 Flutter 中嵌入原生 Android 视图if (defaultTargetPlatform == TargetPlatform.android) {// 标识符要保持一致return const AndroidView(viewType: 'com.example.batterylevel/custom_platform_view',);}}return Scaffold(appBar: AppBar(),body: Center(child: platformView(),),);}
}

在这里插入图片描述

flutter与原生之间的通信

关于通信可以看一下这篇文章:Flutter与原生如何进行通信

简单的参数传递

flutter中的修改,main.dart

class PlatformViewDemoState extends State<PlatformViewDemo> {Widget build(BuildContext context) {platformView() {// 如果是安卓平台,则返回一个AndroidView对象// AndroidView 是 Flutter 提供的一个小部件,用于在 Flutter 中嵌入原生 Android 视图if (defaultTargetPlatform == TargetPlatform.android) {// 标识符要保持一致return const AndroidView(viewType: 'com.example.batterylevel/custom_platform_view',creationParams: {'text': 'AndroidTextView122'},creationParamsCodec: StandardMessageCodec(),);}}return Scaffold(appBar: AppBar(),body: Center(child: platformView(),),);}
}
  • creationParams :传递的参数,插件可以将此参数传递给 AndroidView 的构造函数。
  • creationParamsCodec :将 creationParams 编码后再发送给平台侧,它应该与传递给构造函数的编解码器匹配。值的范围:
    • StandardMessageCodec,这是 Flutter 默认的编解码器,用于序列化和反序列化标准数据类型,例如字符串、数字、布尔值、列表和映射
    • JSONMessageCodec,使用 JSON 格式进行序列化和反序列化。它可以用于传递复杂的数据结构,例如嵌套的映射和列表。
    • StringCodec,用于将字符串编码为字节流,并在需要时进行解码。它适用于只传递字符串类型的创建参数。
    • BinaryCodec,用于直接传递字节流类型的创建参数,不进行额外的编码或解码

修改 MyFlutterView.kt

class MyFlutterView(context: Context,messenger: BinaryMessenger,viewId: Int,args: Map<String, Any>?
) :PlatformView {// PlatformView代表一个平台视图,它是Flutter和原生平台之间的桥梁。// PlatformView允许在Flutter应用中嵌入原生视图,并提供了与Flutter框架进行交互的方法。// 定义一个文本视图private val textView: TextView = TextView(context)init {// 初始化文本视图// 没学过Kotlin,大体意思是参数存在则赋值args?.also { map ->println(map["text"])println("参数")textView.text = map["text"] as String}}// 获取文本视图override fun getView(): View {return textView}//  销毁override fun dispose() {}
}

在这里插入图片描述

使用MethodChannel 通信

main.dart

class PlatformViewDemoState extends State<PlatformViewDemo> {// 用于通信的通道static const platform = MethodChannel('com.flutter.guide.MyFlutterView');Widget build(BuildContext context) {platformView() {// 如果是安卓平台,则返回一个AndroidView对象// AndroidView 是 Flutter 提供的一个小部件,用于在 Flutter 中嵌入原生 Android 视图if (defaultTargetPlatform == TargetPlatform.android) {// 标识符要保持一致return const AndroidView(viewType: 'com.example.batterylevel/custom_platform_view',creationParams: {'text': '向安卓传参数'},creationParamsCodec: StandardMessageCodec(),);}}return Scaffold(appBar: AppBar(),body: Column(children: [ElevatedButton(onPressed: () {// invokeMethod 的作用是在特定的上下文中调用指定的方法。它接受两个参数:方法名称和一个包含参数的对象platform.invokeMethod('setText', {'name': '张三', 'age': 18});},child: const Text("使用MethodChannel通信")),Expanded(child: platformView()!)],));}
}

修改 MyFlutterView.kt

class MyFlutterView(context: Context,messenger: BinaryMessenger,viewId: Int,args: Map<String, Any>?
) :PlatformView, MethodChannel.MethodCallHandler {// PlatformView代表一个平台视图,它是Flutter和原生平台之间的桥梁。// PlatformView允许在Flutter应用中嵌入原生视图,并提供了与Flutter框架进行交互的方法。// 定义一个文本视图private val textView: TextView = TextView(context)private var methodChannel: MethodChannelinit {// 初始化文本视图// 没学过Kotlin,大体意思是参数存在则赋值args?.also { map ->textView.text = map["text"] as String}// com.flutter.guide.MyFlutterView 标识保证唯一,与flutter中的保持一致methodChannel = MethodChannel(messenger, "com.flutter.guide.MyFlutterView")methodChannel.setMethodCallHandler(this)}// 获取文本视图override fun getView(): View {return textView}//  销毁override fun dispose() {methodChannel.setMethodCallHandler(null)}// 方法调用处理器override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {if (call.method == "setText") {val name = call.argument("name") as String?val age = call.argument("age") as Int?textView.text = "hello,$name,年龄:$age"} else {result.notImplemented()}}
}

注:

methodChannel = MethodChannel(messenger, "com.flutter.guide.MyFlutterView")
methodChannel.setMethodCallHandler(this)

必须放在

 args?.also { map ->textView.text = map["text"] as String}

后面,好像存在执行顺序的问题。如果放在前面, textView.text = map["text"] as String不会执行
在这里插入图片描述

flutter接收来自原生的消息
在flutter中使用invokeMethod调用原生的方法。在原生中处理对应方法时,如果要向flutter中返回消息可以使用

textView.text = "hello,$name,年龄:$age"
result.success("收到了来自flutter的调用")

在flutter中正常接收即可

ElevatedButton(onPressed: () async{// invokeMethod 的作用是在特定的上下文中调用指定的方法。它接受两个参数:方法名称和一个包含参数的对象var res = await  platform.invokeMethod('setText', {'name': '张三', 'age': 18});print(res);},child: const Text("使用MethodChannel通信"))

在这里插入图片描述

解决多个原生View通信冲突问题

这个看原文章就好了,主要是保证每一个通道都是唯一的。

原生 View 生成时,系统会为其生成唯一id:viewId,使用 viewId 构建不同名称的 MethodChannel。

class MyFlutterView(context: Context, messenger: BinaryMessenger, viewId: Int, args: Map<String, Any>?) : PlatformView, MethodChannel.MethodCallHandler {val textView: TextView = TextView(context)private var methodChannel: MethodChannelinit {args?.also {textView.text = it["text"] as String}methodChannel = MethodChannel(messenger, "com.flutter.guide.MyFlutterView_$viewId")methodChannel.setMethodCallHandler(this)}...
}

Flutter 端为每一个原生 View 创建不同的MethodChannel

var platforms = [];AndroidView(viewType: 'plugins.flutter.io/custom_platform_view',onPlatformViewCreated: (viewId) {print('viewId:$viewId');platforms.add(MethodChannel('com.flutter.guide.MyFlutterView_$viewId'));},creationParams: {'text': 'Flutter传给AndroidTextView的参数'},creationParamsCodec: StandardMessageCodec(),
)

给第一个发送消息:

platforms[0].invokeMethod('setText', {'name': 'laomeng', 'age': 18});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/665501.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能深度学习发展历程-纪年录

前言 为了理解模型之间的改进关系、明确深度学习的发展目标、提高自身对模型的深度理解、贯彻爱与和平的理念。总之&#xff0c;我做了如下表格。 时间 重大突破 模型改进 详细信息 1847 SGD 随机梯度下降 1995 SVM 支持向量机 1982 RNN 循环神经网络&#xff0c;…

烽火传递

看似很简单的单调队列优化DP 但是如果状态是表示前\(i\)个烽火台被处理完的最小代价(即不知道最后一个烽火台在哪里)就无法降低复杂度 因为假设你在区间\([i-m1,i]\)中枚举最后一个烽火台(设为\(k\))&#xff0c;你前面的状态并不是\(f[k-1]\)&#xff0c;因为此时\(k\)已经可以…

C++之std::tuple(一) : 使用

相关系列文章 C之std::tuple(一) : 使用 C三剑客之std::variant(一) : 使用 C三剑客之std::variant(二)&#xff1a;深入剖析 目录 1.简介 2.创建元组 2.1.直接初始化方式 2.2.使用花括号初始化列表方式&#xff08;C11及以上版本&#xff09; 2.3.make_tuple方式 2.4.使…

Log4j2-27-log4j2 与 springboot 整合例子

1.去除默认的依赖并导入log4j2、lombok依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><exclusions><!-- 引入log4j日志时需去掉默认的logback --><exclusion>&…

【类和对象】4

日期类的拓展 c语言中的printf函数只能打印内置类型&#xff0c;为了弥补这一不足&#xff0c;c利用运算符重载可以打印自定义类型。 void operator<<(ostream&out);//声明在date.h中void Date::operator<<(ostream& out)//定义在date.cpp中 {out<<…

IBOS靶场搭建流程(超详细)

IBOS 1.下载并安装IBOS 点击然后一直下一步进行安装IBOS 显示出这个时证明安装成功 然后进行数据库的搭建&#xff0c;这里需要说明的是这里运行的服务是nginx和mysql而不是apache和mysql所以说这里的数据库名默认是root且密码也默认是root点击立即安装 安装后出现 这个页面时…

Unity_颜色空间GammaLinear

Unity_颜色空间Gamma&Linear 1: Unity颜色空间的选择对于效果的影响具体有多大? 在ProjectSetting -> Player -> OtherSetting -> Rendering设置下的颜色空间选项卡选择颜色空间进行设置: 太深奥的解释一时半会看不懂,找见一个粗浅的对比,当然本人未做验…

GPGPU面临的工程困境闲聊

作者&#xff1a;蒋志强 本人同意他人对我的文章引用&#xff0c;但请在引用时注明出处&#xff0c;谢谢&#xff0e;作者&#xff1a;蒋志强 0.前言 2007年作为GPGPU的工程界元年至今&#xff0c;已经发展了接近小二十年了。这个领域是如此的重要&#xff0c;几乎影响了工业…

Canal 结合 SpringBoot 源码梳理

1、canal是什么&#xff0c;可以用来作什么 canal是阿里开源的一个用于监听数据库binlog&#xff0c;从而实现数据同步的工具。 2、安装 我使用的是1.1.5版本&#xff0c;太高的版本需要的jdk版本和mysql的驱动版本会更高&#xff0c;可以根据自己的环境选择。 如果是自己玩的话…

如何保证MySQL和Redis中的数据一致性?

文章目录 前言一、缓存案例1.1 缓存常见用法1.2 缓存不一致产生的原因 二、解决方案2.1 先删除缓存&#xff0c;再更新数据库2.2 先更新数据库&#xff0c;删除缓存2.3 只更新缓存&#xff0c;由缓存自己同步更新数据库2.4 只更新缓存&#xff0c;由缓存自己异步更新数据库2.5 …

MySQL-----DDL基础操作

SQL通用语法 1.SQL语句可以单行或多行书写&#xff0c;以分号结尾。 2. SQL语句可以使用空格/缩进来增强语句的可读性。 3. MySQL数据库的SQL语句不区分大小写&#xff0c;关键字建议使用大写。 4&#xff0e;注释: 单行注释:--注释内容或#注释内容(MySQL特有) 多行注释:/*注释…

【Iot】什么是串口?什么是串口通信?串口通信(串口通讯)原理,常见的串口通信方式有哪些?

串口通信原理 1. 串口2. 串口通信4. 波特率与比特率5. 帧格式3. 串口通讯的通讯协议3.1. RS2323.2. RS485 总结 1. 串口 串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是采用串行通信方式的扩展接口。 串口可…

jstack命令解析

前言 如果有一天&#xff0c;你的Java程序长时间停顿&#xff0c;也许是它病了&#xff0c;需要用jstack拍个片子分析分析&#xff0c;才能诊断具体什么病症&#xff0c;是死锁综合征&#xff0c;还是死循环等其他病症&#xff0c;本文我们一起来学习jstack命令~ jstack 的功…

深度学习入门笔记(六)线性回归模型

本节&#xff0c;我们用线性回归为例子&#xff0c;回顾一些基本概念 6.1 相关性 相关性的取值范围是-1 到 1&#xff0c;越接近 1 或者-1 代表越相关&#xff0c;越接近 0 则越不相关。相关系数大于 0 称为正相关&#xff0c;小于 0 称为负相关。 假如 A 与 B 正相关&#…

[UI5 常用控件] 05.FlexBox, VBox,HBox,HorizontalLayout,VerticalLayout

文章目录 前言1. FlexBox布局控件1.1 alignItems 对齐模式1.2 justifyContent 对齐模式1.3 Direction1.4 Sort1.5 Render Type1.6 嵌套使用1.7 组件等高显示 2. HBox,VBox3. HorizontalLayout&#xff0c;VerticalLayout 前言 本章节记录常用控件FlexBox,VBox,HBox,Horizontal…

快速理解复杂系统组成学习内容整合

目录 一、复杂系统组成 二、接入系统 (Access System) 三、应用系统 (Application System) 四、基础平台 (Foundation Platform) 五、中间件 (Abundant External Middleware) 六、支撑系统 (Supporting System) 参考文章 一、复杂系统组成 复杂系统是由多个相互关联、相…

比瓴科技入围软件供应链安全赛道!为关键信息基础设施安全建设注入新动力

1月20日&#xff0c;中关村华安关键信息基础设施安全保护联盟会员大会暨关键信息基础设施安全保护论坛在北京成功举办&#xff0c;比瓴科技作为会员单位受邀出席。 本次论坛发布了《关键信息基础设施安全保护支撑能力白皮书&#xff08;2023&#xff09;》&#xff0c;比瓴科技…

【开源】SpringBoot框架开发大学计算机课程管理平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 实验课程档案模块2.2 实验资源模块2.3 学生实验模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 实验课程档案表3.2.2 实验资源表3.2.3 学生实验表 四、系统展示五、核心代码5.1 一键生成实验5.2 提交实验5.3 批阅实…

获取真实 IP 地址(二):绕过 CDN(附链接)

一、DNS历史解析记录 DNS 历史解析记录指的是一个域名在过去的某个时间点上的DNS解析信息记录。这些记录包含了该域名过去使用的IP地址、MX记录&#xff08;邮件服务器&#xff09;、CNAME记录&#xff08;别名记录&#xff09;等 DNS 信息。DNS 历史记录对于网络管理员、安全研…

怪物联萌小游戏

欢迎来到程序小院 怪物联萌 玩法&#xff1a;将怪物连体&#xff0c;怪物只能直线上下左右移动&#xff0c;躲过障碍物&#xff0c;共16关卡&#xff0c; 不同关卡不同界面&#xff0c;遇到金币记得吃掉金币哦&#xff0c;会获得更高分数&#xff0c;快去闯关吧^^。开始游戏ht…