flutter插件开发基础教程

前言

虽然现在已经有很多插件了,但是有时候还是需要自己开发一个插件。因此打算学习一下如何开发一个插件。这里只考虑安卓,安卓使用kotlinkotlin不会也没事,我也不会。

参考项目: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

dart 复制代码
 // 获取电池电量
 Future<int?> getBatteryLevel() {
   throw UnimplementedError('getBatteryLevel() has not been implemented.');
 }

batterylevel_method_channel.dart

dart 复制代码
/// 获取电池电量
@override
Future<int?> getBatteryLevel() async {
  final level = await methodChannel.invokeMethod<int>('getBatteryLevel');
  return level;
}

BatterylevelPlugin.kt

编写原生代码时,创建一个新的窗口打开安卓部分,这样会有提示,也不会出现报错。

选中项目,鼠标右键

打开后,两边对照一下,别打开错了。

dart 复制代码
/** 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

dart 复制代码
// 获取电池电量
Future<int?> getBatteryLevel() {
  return BatterylevelPlatform.instance.getBatteryLevel();
}

测试

在插件的example里测试

example下的main.dart

dart 复制代码
class _MyAppState extends State<MyApp> {
  String _platformVersion = 'Unknown';
  final _batterylevelPlugin = Batterylevel();

  // 电量
  String batteryLevel = '';

  @override
  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(() {});
  }

  @override
  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、就跟其他依赖一样,正常使用即可

dart 复制代码
class _MyHomePageState extends State<MyHomePage> {
  // 获取电池电量的本地插件
  final Batterylevel batteryLevel = Batterylevel();
  // 当前电量
  int batteryLevelValue = 0;

  @override
  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;
                  });
                })
          ],
        ),
      ),
    );
  }
}
相关推荐
孤鸿玉5 小时前
Fluter InteractiveViewer 与ScrollView滑动冲突问题解决
flutter
叽哥12 小时前
Flutter Riverpod上手指南
android·flutter·ios
BG1 天前
Flutter 简仿Excel表格组件介绍
flutter
zhangmeng1 天前
FlutterBoost在iOS26真机运行崩溃问题
flutter·app·swift
恋猫de小郭1 天前
对于普通程序员来说 AI 是什么?AI 究竟用的是什么?
前端·flutter·ai编程
卡尔特斯1 天前
Flutter A GlobalKey was used multipletimes inside one widget'schild list.The ...
flutter
w_y_fan1 天前
Flutter 滚动组件总结
前端·flutter
醉过才知酒浓1 天前
Flutter Getx 的页面传参
flutter
火柴就是我2 天前
flutter 之真手势冲突处理
android·flutter
Speed1232 天前
`mockito` 的核心“打桩”规则
flutter·dart