flutter插件开发基础教程

前言

虽然现在已经有很多插件了,但是有时候还是需要自己开发一个插件。因此打算学习一下如何开发一个插件。这里只考虑安卓,安卓使用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

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;
                  });
                })
          ],
        ),
      ),
    );
  }
}
相关推荐
梦想的颜色4 小时前
【编程实战】AI 时代 APP 开发全栈硬核指南:技术选型 + AI 架构 + 模型落地全维度决策
python·flutter·react native·react.js·ai·桌面应用·milvus
yuanlaile1 天前
2026年全新Flutter 跨平台开发全栈学习资料整理
flutter·getx·鸿蒙 next·flutter开发鸿蒙·flutter入门实战·flutter全栈
恋猫de小郭1 天前
Genkit Dart 1.0 发布,Flutter 原生的 AI Agent 终于完整了
android·前端·flutter
第10086个小白1 天前
flutter桌面端打包方式(Inno Setup Compiler)版本
前端·flutter
陆断枫2 天前
Flutter 3.47 动画引擎盘点:Impeller 全平台,和那些"新特性"
flutter
程序员老刘2 天前
Flet 1.0 思路很好,可惜来晚了
flutter·ai编程·客户端
m0_738185822 天前
Flutter 鸿蒙化实战:qr_code_scanner_plus 适配 OpenHarmony,二维码扫描
flutter·华为·harmonyos·鸿蒙
恋猫de小郭2 天前
Flutter + EmbeddingGemma 2,谷歌发布完全端侧的 AI Edge Foresight
android·前端·flutter
君赏3 天前
基于 FlutterPatch 快速接入 Flutter 热更新
flutter
律宏阔3 天前
Dart FFI 内存管理:用 using + Arena 替代嵌套 try-finally
前端·flutter