前言导读
之前有同学问我flutter插件如何开发, 今天就分享一起flutter插件的开发。带着大家从零开始开发属于自己的插件
效果图
具体实现
-
1 创建插件工程
选择flutter工程然后选定自己的sdk
我们这个project type 选择plugin
插件工程
-
1 我们的lib目录下面编写我们的插件和原生交互的dart代码
-
2 example 下面是我们调试插件的代码
-
3 android 是我们的插件原生部分代码
-
我们选直接运行下我们的项目 让android studio 拉一下我们的gradle
-
我们打开example 项目下面的Android工程 (谨记不是根目录下面的Android工程)
-
然后让android studio 构建
ComepluginPlugin 就是我们插件原生代码 在这里编写和我们的flutter交互的代码
我们一共编写获取Android版本号 获取versionname 获取versioncode toast 弹出等等
-
获取Android版本号
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
}
-
获取versionname
if (call.method.equals("getVersionName")) {
result.success(versionName(this.flutterPluginBinding.getApplicationContext()));
}
-
获取versioncode
if(call.method.equals("getVersionCode")) {
result.success((versionCode(this.flutterPluginBinding.getApplicationContext())));
-
toast
这里需要注意我们flutter 端 是通过json传递参数给我们Android端的
if(call.method.equals("toast")) {
String param = call.argument("param"); // 获取参数
Toast.makeText(this.flutterPluginBinding.getApplicationContext(),param,Toast.LENGTH_LONG).show();
完整插件原生Android代码
package com.example.comeplugin;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.widget.Toast;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
/** ComepluginPlugin */
public class ComepluginPlugin implements FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private MethodChannel channel;
FlutterPluginBinding flutterPluginBinding;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "comeplugin");
channel.setMethodCallHandler(this);
this.flutterPluginBinding=flutterPluginBinding;
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else if (call.method.equals("getVersionName")) {
result.success(versionName(this.flutterPluginBinding.getApplicationContext()));
} else if(call.method.equals("getVersionCode")) {
result.success((versionCode(this.flutterPluginBinding.getApplicationContext())));
}else if(call.method.equals("toast")) {
String param = call.argument("param"); // 获取参数
Toast.makeText(this.flutterPluginBinding.getApplicationContext(),param,Toast.LENGTH_LONG).show();
}else {
result.notImplemented();
}
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
/***
*
* 获取versioncode
* @param context
* @return
*/
public String versionCode(Context context) {
PackageManager manager = context.getPackageManager();
int code = 0;
try {
PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
code = info.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return String.valueOf(code);
}
/***
*
*
* versioncode
* @param context
* @return
*/
public String versionName(Context context) {
PackageManager manager = context.getPackageManager();
String name = null;
try {
PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
name = info.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return name;
}
}
-
flutter端插件代码实现
我们先再插件父类抽象类里面 定义我们跟原生端交互的方法
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'comeplugin_method_channel.dart';
abstract class ComepluginPlatform extends PlatformInterface {
/// Constructs a ComepluginPlatform.
ComepluginPlatform() : super(token: _token);
static final Object _token = Object();
static ComepluginPlatform _instance = MethodChannelComeplugin();
/// The default instance of [ComepluginPlatform] to use.
///
/// Defaults to [MethodChannelComeplugin].
static ComepluginPlatform get instance => _instance;
/// Platform-specific implementations should set this with their own
/// platform-specific class that extends [ComepluginPlatform] when
/// they register themselves.
static set instance(ComepluginPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
_instance = instance;
}
Future<String?> getPlatformVersion() {
throw UnimplementedError('platformVersion() has not been implemented.');
}
Future<String?> getVersionName() {
throw UnimplementedError('platformVersion() has not been implemented.');
}
Future<String?> getVersionCode() {
throw UnimplementedError('platformVersion() has not been implemented.');
}
toast(String str){
throw UnimplementedError('platformVersion() has not been implemented.');
}
}
-
然后再我们的 MethodChannelComeplugin 类里面实现这些方法
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'comeplugin_platform_interface.dart';
/// An implementation of [ComepluginPlatform] that uses method channels.
class MethodChannelComeplugin extends ComepluginPlatform {
/// The method channel used to interact with the native platform.
@visibleForTesting
final methodChannel = const MethodChannel('comeplugin');
@override
Future<String?> getPlatformVersion() async {
final version = await methodChannel.invokeMethod<String>('getPlatformVersion');
return version;
}
@override
Future<String?> getVersionName() async {
final versionname = await methodChannel.invokeMethod<String>('getVersionName');
return versionname;
}
@override
Future<String?> getVersionCode() async {
final versioncode = await methodChannel.invokeMethod<String>('getVersionCode');
return versioncode;
}
@override
toast(String str) async {
await methodChannel.invokeMethod('toast', {'param': str});
}
}
-
我们通过 MethodChannel 来注册我们的交互的通信的协议 comeplugin 这个要跟我的原生端保持一致
flutter 端
final methodChannel = const MethodChannel('comeplugin');
原生端
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "comeplugin");
channel.setMethodCallHandler(this);
this.flutterPluginBinding=flutterPluginBinding;
}
-
然后我们定义 Comeplugin 定义对应的对外方法 给我们的 example 调试工程调用
import 'comeplugin_platform_interface.dart';
class Comeplugin {
Future<String?> getPlatformVersion() {
return ComepluginPlatform.instance.getPlatformVersion();
}
Future<String?> getVersionName() {
return ComepluginPlatform.instance.getVersionName();
}
Future<String?> getVersionCode() {
return ComepluginPlatform.instance.getVersionCode();
}
toast(String str) async {
return ComepluginPlatform.instance.toast(str);
}
}
我们在Comeplugin 里面里面返回我们的 ComepluginPlatform 里面的结果
然后我们在 example里面去调用
-
获取Android版本号 获取versionname 获取versioncode 调用
Future<void> initPlatformState() async {
String platformVersion;
String? versionname;
String? versioncode;
try {
platformVersion =
await _comepluginPlugin.getPlatformVersion() ?? 'Unknown platform version';
print("platformVersion -- >"+platformVersion);
versionname =
await _comepluginPlugin.getVersionName() ?? 'Unknown versionname';
print("versionname -- >"+versionname);
versioncode =
await _comepluginPlugin.getVersionCode() ?? 'Unknown versioncode version';
print("versioncode -- >"+versioncode);
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
_veriosnName= versionname.toString();
_versionCode= versioncode.toString();
});
}
-
toast调用
@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('Versionname: $_veriosnName\n'),
Text('VersionCode: $_versionCode\n'),
ElevatedButton(
onPressed: () =>{
_comepluginPlugin.toast("测试哈哈哈")
},
child: const Text("点击toast"),
),
],
)
),
),
);
}
最后总结
到此我们的flutter插件开发我们就讲完了,那么如何打包插件发布还有和其他端交互例如 ios还有鸿蒙,我们在后面我们补上去,因为篇幅有限我这边就不展开讲,原理都差不多 也是使用Methodchannel 交互的,如果同学有兴趣可以自己研究 也可以继续等待老师后续的更新,今天的文章就讲到这里,, 今天的文章就讲到这里有兴趣的 关注我B站教程 了解更多鸿蒙开发的知识 可以关注坚果派公众号 。 谢谢
课程地址
项目内容:
-
1 Flutter 鸿蒙化开发环境搭建和项目运行介绍和实战使用
-
2 Flutter 鸿蒙化flutter页面添加到现有的鸿蒙项目中
-
3 Flutter鸿蒙化之flutter代码和鸿蒙next原生代码通信 MethodChannel 方式通信
-
4 Flutter鸿蒙化之flutter代码和鸿蒙next原生代码通信 EventChannel 方式通信
-
5 Flutter鸿蒙化之flutter代码和鸿蒙next原生代码通信 BasicMessageChannel 方式通信 实现透传
-
6 Flutter 鸿蒙化PlatformView实现混合渲染