Flutter 调用 Android Native 的方法,是通过MethodChannel的方式来实现的。
Android端:
实现方式一:
- 创建一个Class,实现FlutterPlugin 和 MethodCallHandler 接口
- 重写onAttachedToEngine(),onDetachedFromEngine(),onMethodCall() 这3个方法
- onMethodCall方法中,通过自定义的METHOD_NAME,来响应Flutter中,invokeMethod对Native的通信
- 在io.flutter.plugins包下的GeneratedPluginRegistrant添加代码 flutterEngine.getPlugins().add(SpeechPlugin1.Companion.getINSTANCE());
代码如下:
/**
* todo Flutter 调用 Android Native 的方法 2
* 1、创建一个Class,实现FlutterPlugin和MethodCallHandler接口
* 2、重写onAttachedToEngine(),onDetachedFromEngine(),onMethodCall()
* 3、onMethodCall中,通过自定义的METHOD_NAME,来响应Flutter中,invokeMethod对Native的通信,
* 4、在io.flutter.plugins包下的GeneratedPluginRegistrant添加代码 flutterEngine.getPlugins().add(SpeechPlugin1.Companion.getINSTANCE());
*/
class SpeechPlugin1:MethodChannel.MethodCallHandler,FlutterPlugin {
private var methodChannel: MethodChannel? = null
private var context:Context ?= null
companion object{
private const val CHANNEL_NAME = "speech_plugin"
val INSTANCE : SpeechPlugin1 by lazy (mode = LazyThreadSafetyMode.SYNCHRONIZED){
SpeechPlugin1()
}
}
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
methodChannel = MethodChannel(binding.binaryMessenger,CHANNEL_NAME)
context= binding.applicationContext
methodChannel?.setMethodCallHandler(this)
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
methodChannel?.setMethodCallHandler(null)
methodChannel = null
}
@SuppressLint("SimpleDateFormat")
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when(call.method){
"android_time" -> result.success(SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(System.currentTimeMillis()))
"toast" -> {
if (call.hasArgument("msg") && !TextUtils.isEmpty(call.argument("msg"))) {
Toast.makeText(context, call.argument("msg"), Toast.LENGTH_LONG).show()
} else {
Toast.makeText(context, "msg 不能为空", Toast.LENGTH_SHORT).show()
}
}
else ->result.notImplemented()
}
}
实现方式二:
在继承了FlutterActivity的MainActivity类中重写configureFlutterEngine方法
class MainActivity: FlutterActivity() {
private lateinit var speechPlugin: SpeechPlugin2
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
speechPlugin = SpeechPlugin2(this)
//通过MethodChannel与原生通信
val methodChannel = MethodChannel(flutterEngine.dartExecutor, "speech_plugin")
methodChannel.setMethodCallHandler(speechPlugin)
}
class SpeechPlugin2(private val context: Context) : MethodChannel.MethodCallHandler {
@SuppressLint("SimpleDateFormat")
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when(call.method){
"android_time" -> result.success(SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(System.currentTimeMillis()))
"toast" -> {
if (call.hasArgument("msg") && !TextUtils.isEmpty(call.argument("msg"))) {
Toast.makeText(context, call.argument("msg"), Toast.LENGTH_LONG).show()
} else {
Toast.makeText(context, "msg 不能为空", Toast.LENGTH_SHORT).show()
}
}
else ->result.notImplemented()
}
}
}
Flutter端:
- 根据Native中定义的METHOD_NAME来创建MethodChannel
- 通过MethodChannel.invokeMethod(METHOD_NAME,params),参数METHOD_NAME为Native中定义的METHOD_NAME,params为传递的参数,就可以和Native进行通信了,在Native的onMethodCall方法中,通过call.method == METHOD_NAME来确定,Flutter是否调用的是Native中定义的METHOD_NAME的方法,
class SpeechPlugin {
//一定要和android native端一致
static const String METHOD_NAME = "speech_plugin";
//定义与Native进行交互的MethodChannel,Android与Ios通用
static const MethodChannel _methodChannel = MethodChannel(METHOD_NAME);
//通过安卓获取当前时间
static Future getAndroidTime() async {
//通过MethodChannel对象的invokeMethod()方法调用原生方法
var time = await _methodChannel.invokeMethod("android_time");
return Future.value(time);
}
//显示安卓土司
static showAndroidToast(String message) async {
try{
await _methodChannel.invokeMethod("toast",{"msg":message});
} on PlatformException catch(e){ //使用 catch on 捕获不同类型的错误
// handle PlatformException
print(e.toString());
}
}
}
//获取到android端的系统时间后,再传递给android端。用android端的吐司显示出来
void _showAndridToast(SearchViewModel model) {
SpeechPlugin.getAndroidTime().then((message) {
SpeechPlugin.showAndroidToast(message);
});
}