flutter create -t module flutter_module

//将 Flutter 模块作为子项目添加到宿主应用的 settings.gradle 中:
setBinding(new Binding([gradle: this]))
evaluate(new File(settingsDir.parentFile,'flutter_module/.android/include_flutter.groovy'
))//加这里的配置开发起来更方便,直接在一个工程下切换原生项目或Flutter module
include ':flutter_module'
project(':flutter_module').projectDir = new File('../flutter_module')
//应用中引入对 Flutter 模块的依赖:
implementation project(':flutter')
//Caused by: org.gradle.api.internal.plugins.PluginApplicationException: Failed to apply plugin class 'FlutterPlugin'.
//操作1:注释
//dependencyResolutionManagement {
// repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
// repositories {
// google()
// mavenCentral()
// }
//}
//plugins {
// id 'com.android.application' version '8.1.0-alpha06' apply false
// id 'com.android.library' version '8.1.0-alpha06' apply false
// id 'org.jetbrains.kotlin.android' version '1.7.21' apply false
//}plugins {id 'com.android.application' version '7.4.0' apply false //操作3:更改version,对应的gradle可以改为7.5-binid 'com.android.library' version '7.4.0' apply false //操作3:更改versionid 'org.jetbrains.kotlin.android' version '1.7.21' apply false
}
//Caused by: org.gradle.api.internal.plugins.PluginApplicationException: Failed to apply plugin class 'FlutterPlugin'.
//操作2:新增
allprojects {repositories {google()jcenter()}
}
class FlutterAppActivity : FlutterActivity() {private var mInitParams: String? = nullcompanion object {const val INIT_PARAMS = "initParams"private var mtype = 0fun start(context: Context, initParams: String = "", type: Int) {mtype = typeval intent = Intent(context, FlutterAppActivity::class.java)intent.putExtra(INIT_PARAMS, initParams)context.startActivity(intent)}}//优先级高于onCreateoverride fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)mInitParams = intent.getStringExtra(INIT_PARAMS);}//重载该方法来传递初始化参数override fun getInitialRoute(): String? {return if (mInitParams == null) super.getInitialRoute() else mInitParams}
}
class MainActivity : AppCompatActivity() {@SuppressLint("MissingInflatedId")override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)findViewById(R.id.normal).setOnClickListener {FlutterAppActivity.start(this@MainActivity,"打开普通页面的参数信息", type = 1)}findViewById(R.id.btn1).setOnClickListener {FlutterAppActivity.start(this@MainActivity, "BasicMessageChannel", 2)}findViewById(R.id.btn2).setOnClickListener {FlutterAppActivity.start(this@MainActivity, "MethodChannel", 3)}findViewById(R.id.btn3).setOnClickListener {FlutterAppActivity.start(this@MainActivity, "EventChannel", 4)}}
}
import 'package:flutter/material.dart';
import 'dart:ui';
import 'basic_message_channel_page.dart';
import 'event_channel.dart';
import 'method_channel_page.dart';//必须要使用window.defaultRouteName来获取从native层传递过来的参数
void main() => runApp(MyApp(window.defaultRouteName));class MyApp extends StatelessWidget {String initParam;MyApp(this.initParam, {super.key});@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: selectPage(),);}//为了看起来更清晰,分别用了四个page,页面打开后可以通过标题栏进行区分Widget selectPage() {switch (initParam) {case "BasicMessageChannel":return BasicMessageChannelPage();case "MethodChannel":return MethodChannelPage();case "EventChannel":return EventChannelPage();default:return MyHomePage();}}
}class MyHomePage extends StatefulWidget {MyHomePage();@overrideState createState() => _MyHomePageState();
}class _MyHomePageState extends State {//省略...@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("普通的flutter页面"),),//省略...);}
}//BasicMessageChannelPage的标题栏信息:title: Text("native与flutter通信之BasicMessageChannel")
//MethodChannelPage的标题栏信息:title: Text("native与flutter通信之MethodChannelPage")
//EventChannelPage的标题栏信息:title: Text("native与flutter通信之EventChannel")
class BasicMessageChannelManager private constructor(messenger: BinaryMessenger
) : BasicMessageChannel.MessageHandler {private var messageChannel: BasicMessageChannelinit {messageChannel =//参数1:消息信使//参数2:channel的名字,唯一标识//参数3:消息编码器,有多种不同类型的实现,这里通信只选择StringCodecBasicMessageChannel(messenger, "BasicMessageChannelManager", StringCodec.INSTANCE)// 注册处理的Handler,处理来自Flutter的消息messageChannel.setMessageHandler(this)}//重写函数:接收Flutter Module传递过来的消息 并可以回应给Flutter Moduleoverride fun onMessage(s: String?, reply: BasicMessageChannel.Reply) {println("Flutter回复给Android的消息:$s")reply.reply("Android收到了 Flutter--->Android的消息,这次是回复操作") //可以通过reply进行回复}companion object {fun register(messenger: BinaryMessenger,): BasicMessageChannelManager = BasicMessageChannelManager(messenger) //创建BasicMessageChannelManager实例}//native主动向Flutter Module发送消息 方式一 带回调fun send(message: String, callback: BasicMessageChannel.Reply) {messageChannel.send(message, callback)}//native主动向Flutter Module发送消息 方式二 不带回调fun send(message: String) {messageChannel.send(message)}}
class FlutterAppActivity : FlutterActivity() {private var mInitParams: String? = nullprivate var mBasicMessageChannelManager: BasicMessageChannelManager? = nullcompanion object {const val INIT_PARAMS = "initParams"private var mtype = 0fun start(context: Context, initParams: String = "", type: Int) {mtype = typeval intent = Intent(context, FlutterAppActivity::class.java)intent.putExtra(INIT_PARAMS, initParams)context.startActivity(intent)}}//优先级高于onCreateoverride fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)mInitParams = intent.getStringExtra(INIT_PARAMS);if (mtype == 2) {mBasicMessageChannelManager =BasicMessageChannelManager.register(flutterEngine.dartExecutor.binaryMessenger)}}//重载该方法来传递初始化参数override fun getInitialRoute(): String? {return if (mInitParams == null) super.getInitialRoute() else mInitParams}override fun onStart() {super.onStart()sendMessageToFlutter()}private fun sendMessageToFlutter() {if (mtype == 2) {mBasicMessageChannelManager!!.send("通过方式一BasicMessageChannel传递参数") { message: String? ->println("message mtype == 2 $message")}}}
}
class BasicMessageChannelPage extends StatefulWidget {@overrideState createState() {return _MyHomePageState();}
}class _MyHomePageState extends State {// int _counter = 0;_MyHomePageState();void _incrementCounter() {// setState(() {// _counter++;// });// 主动向Android发送消息_basicMessageChannel!.send("Flutter--->Android的消息2,这次是Flutter主动的。");}String _basicMessage = '';BasicMessageChannel? _basicMessageChannel;@overridevoid initState() {super.initState();_basicMessageChannel =BasicMessageChannel('BasicMessageChannelManager', StringCodec());//设置setMessageHandler,目的:为了能够接收来自Android的消息//Future:向Android回传消息 _basicMessageChannel!.setMessageHandler((String? message) => Future(() {setState(() {//Android --> Flutter_basicMessage = 'Android--->Flutter的消息:' + message!;});return "Flutter--->Android的消息1:收到了。";}));}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("native与flutter通信之BasicMessageChannel"),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [const Text('You have pushed the button this many times:',),Text('$_basicMessage',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 MethodChannelManager private constructor(private val messenger: BinaryMessenger
) : MethodChannel.MethodCallHandler {// 3. 用于调用Flutter端方法 方式一 无返回值// method为需调用的方法名fun callMethod(method: String, o: Any) {methodChannel.invokeMethod(method, o)}//用于调用Flutter端方法 方式一 有返回值// method为需调用的方法名、返回值在result内fun callMethod(method: String, o: Any, result: MethodChannel.Result) {methodChannel.invokeMethod(method, o, result)}// 4. 复写onMethodCall():根据Flutter的要求,调用Android方法override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {when (call.method) {"callAndroidMethod" -> {println("Flutter--->Android的消息 ${call.arguments}")//返回结果给Dartresult.success("Android收到了 Flutter--->Android的消息,这次是回复操作")}else -> result.notImplemented()}}private var methodChannel: MethodChannelinit {// 1. 创建MethodChannel实例(传入channel name)methodChannel = MethodChannel(messenger, "MethodChannelManager")// 2. 注册处理的HandlermethodChannel.setMethodCallHandler(this)}companion object {fun register(messenger: BinaryMessenger): MethodChannelManager =MethodChannelManager(messenger)}
}
class FlutterAppActivity : FlutterActivity() {private var mInitParams: String? = nullprivate var mMethodChannelManager: MethodChannelManager? = nullcompanion object {const val INIT_PARAMS = "initParams"private var mtype = 0fun start(context: Context, initParams: String = "", type: Int) {mtype = typeval intent = Intent(context, FlutterAppActivity::class.java)intent.putExtra(INIT_PARAMS, initParams)context.startActivity(intent)}}//优先级高于onCreateoverride fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)mInitParams = intent.getStringExtra(INIT_PARAMS);if (mtype == 3) {mMethodChannelManager =MethodChannelManager.register(flutterEngine.dartExecutor.binaryMessenger)}}//重载该方法来传递初始化参数override fun getInitialRoute(): String? {return if (mInitParams == null) super.getInitialRoute() else mInitParams}override fun onStart() {super.onStart()sendMessageToFlutter()}private fun sendMessageToFlutter() {if (mtype == 3) {// Android调用Flutter的send方法mMethodChannelManager!!.callMethod("AndroidCallFlutterMethod", "Android传递给Flutter的消息")}}
}
class _MyHomePageState extends State {_MyHomePageState();void _incrementCounter() {// setState(() {// _counter++;// });_methodChannel!.invokeMethod("callAndroidMethod", "Flutter--->Android的消息3,这次是Flutter主动的。") // 参数1:告诉Android要调用的方法名,参数2:传递的参数.then((result) { // invokeMethod().then() 来处理正常结束的逻辑(获得返回值)print('Android 回复 ---> Flutter的消息 $result');// 成功:通过result.success 返回值// 异常:通过 result.error 返回异常信息,可通过catchError 处理异常});}MethodChannel? _methodChannel;String _methodMessage = '';@overridevoid initState() {super.initState();// 1.创建MethodChannel_methodChannel = new MethodChannel("MethodChannelManager");// 2. 根据Android的要求,调用对应方法_methodChannel!.setMethodCallHandler((handler) => Future(() {print("Android端要调用的方法和参数是:${handler}");setState(() {_methodMessage = "Android端要调用Flutter的方法名为${handler.method},方法参数是${handler.arguments}";});switch (handler.method) {case "AndroidCallFlutterMethod"://handler.arguments表示native传递的方法参数testFun(handler.method, handler.arguments);break;}return "Flutter--->Android的消息3:收到了。";}));}void testFun(method, params) {print('Android要调用Flutter的方式名为$method,参数是$params');}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("native与flutter通信之MethodChannelPage"),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [const Text('You have pushed the button this many times:',),Text('$_methodMessage',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.);}
}
定义EventChannel管理类,执行逻辑
EventChannelManager类代码
class EventChannelManager private constructor(private val messenger: BinaryMessenger
) : EventChannel.StreamHandler {private var eventSink: EventChannel.EventSink? = null// 4.1.Android端开始发送数据fun send(params: Any) {if (eventSink != null) {eventSink!!.success(params)println("sink success")}}// 4.2.Android端停止发送数据fun cancel() {if (eventSink != null) {eventSink!!.endOfStream()}}// 4.3.Android端发送数据失败fun sendError(str1: String, str2: String, params: Any) {if (eventSink != null) {eventSink!!.error(str1, str2, params)}}// 3.回调时机:Flutter端开始监听该channel时// 说明通道已经建立好,Android可以开始发送数据了// 参数1:Flutter端初始化EventChannel时返回的值,仅此一次// 参数2:传数据的载体override fun onListen(o: Any?, eventSink: EventChannel.EventSink?) {//此处注意时序,必须得该方法回调后,Android端才允许发送数据this.eventSink = eventSinkprintln("onListen():eventSink = $eventSink")}// Flutter端不再接收数据时回调override fun onCancel(o: Any) {println("onCancel()")eventSink = null}init {//1.创建EventChannel 参数2的格式:包名/标识符val channel = EventChannel(messenger, "com.jack.android_simple/EventChannelManager")//2.设置对应Handlerchannel.setStreamHandler(this)}companion object {fun register(messenger: BinaryMessenger): EventChannelManager = EventChannelManager(messenger)}
}
class FlutterAppActivity : FlutterActivity() {private var mInitParams: String? = nullprivate var mEventChannelManager: EventChannelManager? = nullcompanion object {const val INIT_PARAMS = "initParams"private var mtype = 0fun start(context: Context, initParams: String = "", type: Int) {mtype = typeval intent = Intent(context, FlutterAppActivity::class.java)intent.putExtra(INIT_PARAMS, initParams)context.startActivity(intent)}}//优先级高于onCreateoverride fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)mInitParams = intent.getStringExtra(INIT_PARAMS);if (mtype == 4) {mEventChannelManager =EventChannelManager.register(flutterEngine.dartExecutor.binaryMessenger)}}//重载该方法来传递初始化参数override fun getInitialRoute(): String? {return if (mInitParams == null) super.getInitialRoute() else mInitParams}override fun onStart() {super.onStart()sendMessageToFlutter()}private fun sendMessageToFlutter() {if (mtype == 4) {//使用定时器模拟更佳Handler().postDelayed({ mEventChannelManager!!.send("发送流信息") }, 5000)}}
}
class EventChannelPage extends StatefulWidget {@overrideState createState() {return _MyHomePageState();}
}class _MyHomePageState extends State {EventChannel? _eventChannelPlugin;String _eventMessage = '';_MyHomePageState();@overridevoid initState() {super.initState();// 1.创建EventChannel_eventChannelPlugin =EventChannel("com.jack.android_simple/EventChannelManager");// 2.初始化一个广播流从channel中接收数据_eventChannelPlugin!.receiveBroadcastStream() //dynamic arguments: 对应Android端onListen()的第一个参数,可不传// 开启监听.listen((event) {// 注意:listen可以设置 监听数据流其它状态时 的方法 Function? onError, void onDone()?, bool? cancelOnErrorprint("接收Android发送过来的数据 --- $event");setState(() {_eventMessage = event;});});}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("native与flutter通信之EventChannel"),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [const Text('You have pushed the button this many times:',),Text('$_eventMessage',style: Theme.of(context).textTheme.headlineMedium,),],),),// This trailing comma makes auto-formatting nicer for build methods.);}
}