前言
虽然现在已经有很多插件了,但是有时候还是需要自己开发一个插件。因此打算学习一下如何开发一个插件。这里只考虑安卓,安卓使用kotlin
,kotlin
不会也没事,我也不会。
参考项目:https://github.com/TBoyLi/flutter_plugin_learning
参考教程:https://www.jianshu.com/p/9fc6747fc7c4
创建插件项目
1、文件、新建、新建flutter项目
2、选择flutter、下一步
3、维护好基础信息,项目类型选择插件
开发
项目目录如下,后续需要编写的文件是
BatterylevelPlugin.kt
编写原生代码batterylevel.dart
编写dart代码,flutter项目中会使用该文件batterylevel_method_channel.dart
用于编写与原生通信的逻辑batterylevel_platform_interface.dart
定义了需要实现哪些方法
在batterylevel_platform_interface.dart
定义了一个获取平台接口的方法。
在batterylevel_method_channel.dart
中重新了该方法,并与原生通信
在BatterylevelPlugin.kt
实现了原生逻辑
安装上面的方式,我们定义一个获取当前电量的方法。
batterylevel_platform_interface.dart
// 获取电池电量
Future<int?> getBatteryLevel() {
throw UnimplementedError('getBatteryLevel() has not been implemented.');
}
batterylevel_method_channel.dart
/// 获取电池电量
Future<int?> getBatteryLevel() async {
final level = await methodChannel.invokeMethod<int>('getBatteryLevel');
return level;
}
BatterylevelPlugin.kt
编写原生代码时,创建一个新的窗口打开安卓部分,这样会有提示,也不会出现报错。
选中项目,鼠标右键
打开后,两边对照一下,别打开错了。
/** BatterylevelPlugin */
class BatterylevelPlugin: FlutterPlugin, MethodCallHandler {
private lateinit var channel : MethodChannel
// 获取上下文对象
private var applicationContext: Context? = null
// 注册插件到flutter引擎
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
// 上下文对象
applicationContext = flutterPluginBinding.applicationContext
// 创建通道
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "batterylevel")
channel.setMethodCallHandler(this)
}
override fun onMethodCall(call: MethodCall, result: Result) {
// 判断通信方法的名称,实现获取平台版本
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else if(call.method=="getBatteryLevel"){
// 返回电量
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "Battery level not available.", null)
}
}
else {
result.notImplemented()
}
}
// 获取电池电量
private fun getBatteryLevel(): Int {
var batteryLevel = -1
batteryLevel = if (VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val batteryManager = applicationContext?.let { getSystemService(it, BatteryManager::class.java) }
batteryManager!!.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
} else {
val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
(intent?.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) ?: -1) * 100 / (intent?.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
?: -1)
}
return batteryLevel
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}
batterylevel.dart
// 获取电池电量
Future<int?> getBatteryLevel() {
return BatterylevelPlatform.instance.getBatteryLevel();
}
测试
在插件的example里测试
example
下的main.dart
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
final _batterylevelPlugin = Batterylevel();
// 电量
String batteryLevel = '';
void initState() {
super.initState();
initPlatformState();
}
///获取版本号
Future<void> initPlatformState() async {
String platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
// We also handle the message potentially returning null.
try {
platformVersion = await _batterylevelPlugin.getPlatformVersion() ??
'Unknown platform version';
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
});
}
// 获取电量
Future<void> getBatteryLevel() async {
try {
int res = await _batterylevelPlugin.getBatteryLevel() ?? 0;
batteryLevel = res.toString();
} on PlatformException {
batteryLevel = 'Failed to get battery level.';
}
// 更新
setState(() {});
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Column(
children: [
Text('Running on: $_platformVersion\n'),
Text('电量:$batteryLevel\n'),
ElevatedButton(onPressed: (){
getBatteryLevel();
}, child: const Text("获取电量"))
],
),
),
),
);
}
}
在flutter项目里加载本地的这个插件
最开始是打算直接在项目里引入插件的,奈何引入后一直提示路径不对。因此改成通过git
引入
1、将你的插件提交到git仓库
2、在flutter项目的pubspec.yaml
引入插件
3、运行 flutter pub get
获取依赖
下载的依赖一般都在用户目录下,如下图
4、就跟其他依赖一样,正常使用即可
class _MyHomePageState extends State<MyHomePage> {
// 获取电池电量的本地插件
final Batterylevel batteryLevel = Batterylevel();
// 当前电量
int batteryLevelValue = 0;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("当前电量是:$batteryLevelValue"),
ElevatedButton(
child: const Text("获取电量"),
onPressed: () async {
int res = await batteryLevel.getBatteryLevel() ?? 0;
setState(() {
batteryLevelValue = res;
});
})
],
),
),
);
}
}