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

 // 获取电池电量
 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;
                  });
                })
          ],
        ),
      ),
    );
  }
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/406295.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nrm 镜像源管理工具

1、什么是nrm nrm(npm registry manager )是npm的镜像源管理工具。它可以快速在让你在本地源之间切换。 2、安装 npm install -g nrm 3、查看本地源&#xff08;nrm ls&#xff09; 4、切换 &#xff08;nrm use ***&#xff09; 5 、测试速度&#xff08;nrm test ***&…

spring注解驱动系列--Bean生命周期一

一、Bean生命周期 bean创建--- BeanPostProcessor.postProcessorsBeforeInitialization---初始化----BeanPostProcessor.postProcessAfterInitialization ----销毁的过程 二、管理Bean生命周期 在Bean的生命周期中&#xff0c;我们可以认为的进行干预Bean的创建到销毁的过程&…

石头剪刀布游戏(C语言)

题目描述 石头剪刀布游戏有 3 种出拳形状&#xff1a;石头、剪刀、布。分别用字母 A , B , C 表示。 游戏规则: 出拳形状之间的胜负规则如下&#xff1a; A > B&#xff1b;B > C&#xff1b;C > A&#xff1b;">"左边一个字母&#xff0c;表示相对优…

ElasticSearch之聚合aggs

写在前面 本文看下es的聚合相关内容。 1&#xff1a;什么是聚合 即&#xff0c;数据的统计分析。如sum&#xff0c;count&#xff0c;avg&#xff0c;min&#xff0c;max&#xff0c;分组等。 2&#xff1a;支持哪些聚合类型 2.1&#xff1a;bucket aggregation 对满足特…

抖音数据挖掘软件|视频内容提取

针对用户获取抖音视频的需求&#xff0c;我们开发了一款功能强大的工具&#xff0c;旨在解决用户在获取抖音视频时需要逐个复制链接、下载的繁琐问题。我们希望用户能够通过简单的关键词搜索&#xff0c;实现自动批量抓取视频&#xff0c;并根据需要进行选择性批量下载。因此&a…

Echarts与后台(mongoose)交互

Echarts引入地址可参考 echarts组件引入 <template><div><div id"main" style"width: 600px;height:400px;"></div></div> </template><script setup> import { onMounted, ref } from vue; import * as echa…

挑战杯 基于卷积神经网络的乳腺癌分类 深度学习 医学图像

文章目录 1 前言2 前言3 数据集3.1 良性样本3.2 病变样本 4 开发环境5 代码实现5.1 实现流程5.2 部分代码实现5.2.1 导入库5.2.2 图像加载5.2.3 标记5.2.4 分组5.2.5 构建模型训练 6 分析指标6.1 精度&#xff0c;召回率和F1度量6.2 混淆矩阵 7 结果和结论8 最后 1 前言 &…

数字滚动实现

介绍 vue-countup-v3 插件是一个基于 Vue3 的数字动画插件&#xff0c;用于在网站或应用程序中创建带有数字动画效果的计数器。通过该插件&#xff0c;我们可以轻松地实现数字的递增或递减动画&#xff0c;并自定义其样式和动画效果。该插件可以用于许多场景&#xff0c;例如展…

nginx 配置文件详细介绍

一&#xff0c; nginx 配置文件架构 上一篇 已对 main 全局配置做了详细介绍 本章对剩下的配置文件部分做介绍 二&#xff0c;event 设置 &#xff08;一&#xff09;event 相关的配置文件为 配置工作模式以及连接数 &#xff08;二&#xff09;具体表现 1&#xff…

抖音数据抓取工具|视频内容提取软件

引言部分&#xff1a; 介绍针对抖音视频下载需求开发的强大工具突出解决用户获取抖音视频繁琐问题的初衷 工具功能介绍&#xff1a; 详细描述工具功能&#xff0c;包括关键词搜索、自动批量抓取、选择性批量下载等提及基于C#开发的优势以及支持通过分享链接进行单个视频抓取…

k8s的svc流量通过iptables和ipvs转发到pod的流程解析

文章目录 1. k8s的svc流量转发1.1 service 说明1.2 endpoints说明1.3 pod 说明1.4 svc流量转发的主要工作 2. iptables规则解析2.1 svc涉及的iptables链流程说明2.2 svc涉及的iptables规则实例2.2.1 KUBE-SERVICES规则链2.2.2 KUBE-SVC-EFPSQH5654KMWHJ5规则链2.2.3 KUBE-SEP-L…

axios是如何实现的(源码解析)

1 axios的实例与请求流程 在阅读源码之前&#xff0c;先大概了解一下axios实例的属性和请求整体流程&#xff0c;带着这些概念&#xff0c;阅读源码可以轻松不少&#xff01; 下图是axios实例属性的简图。 可以看到axios的实例上&#xff0c;其实主要就这三个东西&#xff1a…

自定义悬浮气泡组件

一.常用悬浮气泡展示 在一个项目中&#xff0c;常常会使用点悬浮展示&#xff0c;而市面上悬浮tooltip的组件非常多 例如常用的antd提供的Tooltip 用法如下&#xff08;来自于官方文档示例&#xff09;&#xff1a; import React from react; import { Button, Tooltip, Con…

129 Linux 系统编程7 ,make 的编写和解析

前文中&#xff0c;我们有多少个.c文件&#xff0c;就需要build 出来多少个.o文件 假设我们的项目很大&#xff0c;怎么管理这些 .c文件呢&#xff1f; 这里就要学习一个make文件的编写了。 makefile 本质上是一个脚本语言 脚本语言实际上就是将一系列命令放在一起执行 mak…

服务器被黑该如何查找入侵痕迹以及如何防御攻击

当公司的网站服务器被黑&#xff0c;被入侵导致整个网站&#xff0c;以及业务系统瘫痪&#xff0c;给企业带来的损失无法估量&#xff0c;但是当发生服务器被攻击的情况&#xff0c;作为服务器的维护人员应当在第一时间做好安全响应&#xff0c;对服务器以及网站应以最快的时间…

程序环境和预处理(1)

文章目录 目录1. 程序的翻译环境和执行环境2. 详解编译链接2.1 翻译环境2.2 编译本身也分为几个阶段2.3 运行环境 3. 预处理详解3.1 预定义符号3.2 #define3.2.1 #define 定义标识符3.2.2 #define 定义宏3.2.3 #define 替换规则3.2.4 #和##3.2.5 带副作用的宏参数3.2.6 宏和函数…

HAT论文详解:Activating More Pixels in Image Super-Resolution Transformer

code&#xff1a;https://github.com/XPixelGroup/HAT paper: https://arxiv.org/abs/2309.05239 1. 概述 本文是对Swinir的改进&#xff0c;目前很多图像超分Benchmark的SOTA。相对于SwinIR的改进主要有三个地方&#xff1a;1. 引入Channel Attention,以获得更好的全局能力&…

【Linux】 login命令使用

login命令 在 Linux 中用于创建一个新的会话&#xff0c;并在新会话中登录用户。这个命令通常在终端中自动执行&#xff0c;当你打开一个新的终端会话或者通过 SSH 远程连接到 Linux 服务器时。 在命令后面附加欲登入的用户名称&#xff0c;它会直接询问密码&#xff0c;等待…

探索水下低光照图像检测性能,基于YOLOv3全系列【yolov3tiny/yolov3/yolov3spp】参数模型开发构建海底生物检测识别分析系统

海底这类特殊数据场景下的检测模型开发相对来说比较少&#xff0c;在前面的博文中也有一些涉及&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《尝试探索水下目标检测&#xff0c;基于yolov5轻量级系列模型n/s/m开发构建海底生物检测系统》 《基于YOLOv5C3CBAMCBA…

Element table 实现表格行、列拖拽功能

安装包 npm install sortablejs --save <template><div class"draggable" style"padding: 20px"><el-table row-key"id" :data"tableData" style"width: 100%" border><el-table-columnv-for"(it…