本地环境如下:
Flutter 2.2.0-10.1.pre • channel beta
Dart 2.13.0
之前创建了一个Flutter项目,项目中需要判定手机蓝牙是否打开,这时候就需要调用原生代码,但是在网上查看资料时候发现很多资料过时或不能用,原因应该是电脑上的Flutter版本比较高,搞定之后就记录一下。
项目创建时选择了支持Kotlin及Swift,所有项目整体的结构可能不太一样
Flutter端代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class BeControlPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('被控制端'),
),
body: TestWidget()
);
}
}
class TestWidget extends StatefulWidget {
@override
_TestIosWidgetState createState() => _TestIosWidgetState();
}
class _TestIosWidgetState extends State<TestWidget> {
// 调用原生相关代码
Future runMethod() async{
// 自定义的通道且名字为test,在原生中会使用到,只要对的上通道名称才可调用相关方法
const platform = const MethodChannel('test');
var result;
try{
// Flutter提供三种方法与原生交互
// MethodChannel 用于 Flutter 与 原生平台之间函数的互相调用
// BasicMessageChannel 它传递的是字节数组,使用时自定义编解码器
// EventChannel 用于 Flutter 与 原生平台之间事件的通信
// 这里使用的是MethodChannel方式
result = await platform.invokeMethod('isHavePermission');
return Future.value(result);
} on PlatformException catch (e){
return Future.error(e.toString());
}
}
@override
Widget build(BuildContext context) {
return Center(
child: FlatButton(
onPressed: () async{
// 点击按钮后通过原生方法获取到返回值
var futureValue = await runMethod();
// 拿到返回值后弹出框显示返回值
return showDialog(context: context, builder: (context){
return AlertDialog(
content: Text(
futureValue,
textAlign: TextAlign.center,
),
);
});
},
child:
Text(
'信我,得永生',
style: TextStyle(fontSize: 18.0),
),
color: Colors.red,
textColor: Colors.white,
),
);
}
}
iOS端
- 新建OC文件,命名为FlutterNativePlugin,继承与NSObject
,.h文件如下:
#import <Foundation/Foundation.h>
#import <Flutter/Flutter.h>
NS_ASSUME_NONNULL_BEGIN
@interface FlutterNativePlugin : NSObject<FlutterPlugin>
@end
NS_ASSUME_NONNULL_END
- 在AppDelegate里注册工具类
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
FlutterNativePlugin.register(with: self.registrar(forPlugin: "FlutterNativePlugin") as! FlutterPluginRegistrar)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Android端
Android端多说一点,由于在Flutter1.12后Flutter官方舍弃了io.flutter.app.FlutterActivity,所以网上很多代码就可能无法使用了
新建后的Flutter项目Android目录各种标红
这时候鼠标随便打开Android目录下的某一个文件,点击代码编辑区上方的
使用Android打开会下载一些依赖,并且也无标红了
编写MainActivity代码:
很多文章中写的,如https://www.jianshu.com/p/310c28abc9f3文中的代码:
他导入的是io.flutter.app.FlutterActivity头文件,导入此文件这样写不会有问题,而且相关代码写在onCreate方法中,但是在Flutter1.12后此方法废弃,新建的项目均导入的是io.flutter.embedding.android.FlutterActivity头文件,详情见官方文档,所以,如果你的Flutter版本大于1.12,则正确的代码为:
package com.imowfms.flutter_app
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
private val channel = "test"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger,channel)
.setMethodCallHandler { call, result ->
// 你的代码
if (call.method == "isHavePermission"){
result.success("有了-Android")
}else{
result.notImplemented()
}
}
}
}
此时,三部分的代码都完成了,运行看看效果
Android
iOS