前言导读
最近呢有同学让我更新flutter 鸿蒙化插件的开发,趁着有时间我就分享一下。内容包括插件工程的创建还有如何开发等等,那么废话不多说我们正式开始。
效果图


具体实现
创建插件工程
dart
flutter create -t plugin --platforms ohos,android,ios <plugin_name>


导入我们的插件工程

-
1 我们的lib目录下面编写我们的插件和原生交互的dart代码
-
2 example 下面是我们调试插件的代码
-
3 ohos 是我们的插件原生部分代码
我们选直接运行下我们的项目 让devceo studio 拉一下我们的gradle
我们打开example 项目下面的ohos工程 (谨记不是根目录下面的ohos工程)

然后让devceo studio 构建

DemopluginPlugin就是我们插件原生代码 在这里编写和我们的flutter交互的代码

这个demo我们一共编写了 获取鸿蒙系统版本号和toast的案例
获取鸿蒙系统版本号
arkts
if (call.method == "getPlatformVersion") {
result.success("OpenHarmony "+deviceInfo.distributionOSVersion)
}
toast
arkts
if(call.method=='toast') {
let str:string=call.argument('param') as string;
console.log("str-- > "+str);
prompt.showToast({
message:str
})
}
这里需要注意我们flutter 端 是通过map传递参数给我们鸿蒙next端的
dart
@override
toast(String str) async {
Map<String,dynamic>user={
'param':str
};
await methodChannel.invokeMethod<String>('toast',user);
}
完整插件原始鸿蒙next代码
arkts
import {
FlutterPlugin,
FlutterPluginBinding,
MethodCall,
MethodCallHandler,
MethodChannel,
MethodResult,
} from '@ohos/flutter_ohos';
import deviceInfo from '@ohos.deviceInfo';
import { prompt } from '@kit.ArkUI';
/** DemopluginPlugin **/
export default class DemopluginPlugin implements FlutterPlugin, MethodCallHandler {
private channel: MethodChannel | null = null;
constructor() {
}
getUniqueClassName(): string {
return "DemopluginPlugin"
}
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(binding.getBinaryMessenger(), "demoplugin");
this.channel.setMethodCallHandler(this)
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {
if (this.channel != null) {
this.channel.setMethodCallHandler(null)
}
}
onMethodCall(call: MethodCall, result: MethodResult): void {
if (call.method == "getPlatformVersion") {
result.success("OpenHarmony "+deviceInfo.distributionOSVersion)
} else if(call.method=='toast') {
let str:string=call.argument('param') as string;
console.log("str-- > "+str);
prompt.showToast({
message:str
})
}else {
result.notImplemented()
}
}
}
flutter端插件代码实现
我们先再插件父类抽象类里面 定义我们跟原生端交互的方法
dart
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'demoplugin_method_channel.dart';
abstract class DemopluginPlatform extends PlatformInterface {
/// Constructs a DemopluginPlatform.
DemopluginPlatform() : super(token: _token);
static final Object _token = Object();
static DemopluginPlatform _instance = MethodChannelDemoplugin();
/// The default instance of [DemopluginPlatform] to use.
///
/// Defaults to [MethodChannelDemoplugin].
static DemopluginPlatform get instance => _instance;
/// Platform-specific implementations should set this with their own
/// platform-specific class that extends [DemopluginPlatform] when
/// they register themselves.
static set instance(DemopluginPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
_instance = instance;
}
Future<String?> getPlatformVersion() {
throw UnimplementedError('platformVersion() has not been implemented.');
}
@override
toast(String str) async {
throw UnimplementedError('platformVersion() has not been implemented.');
}
}
然后再我们的 MethodChannelComeplugin 类里面实现这些方法
dart
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'demoplugin_platform_interface.dart';
/// An implementation of [DemopluginPlatform] that uses method channels.
class MethodChannelDemoplugin extends DemopluginPlatform {
/// The method channel used to interact with the native platform.
@visibleForTesting
final methodChannel = const MethodChannel('demoplugin');
@override
Future<String?> getPlatformVersion() async {
final version = await methodChannel.invokeMethod<String>('getPlatformVersion');
return version;
}
@override
toast(String str) async {
Map<String,dynamic>user={
'param':str
};
await methodChannel.invokeMethod<String>('toast',user);
}
}
我们通过 MethodChannel 来注册我们的交互的通信的协议demoplugin 这个要跟我的原生端保持一致
flutter 端
dart
@visibleForTesting
final methodChannel = const MethodChannel('demoplugin');
鸿蒙原生端
arkts
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(binding.getBinaryMessenger(), "demoplugin");
this.channel.setMethodCallHandler(this)
}
然后我们定义 Demoplugin 定义对应的对外方法 给我们的 example 调试工程调用
dart
import 'demoplugin_platform_interface.dart';
class Demoplugin {
Future<String?> getPlatformVersion() {
return DemopluginPlatform.instance.getPlatformVersion();
}
@override
toast(String str) async {
return DemopluginPlatform.instance.toast(str);
}
}
我们在Demoplugin 里面里面返回我们的 DemopluginPlatform 里面的结果
然后我们在 example里面去调用
获取鸿蒙next系统版本号调用
dart
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 _demopluginPlugin.getPlatformVersion() ?? 'Unknown platform version';
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
});
}
toast调用
dart
@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'),
ElevatedButton(onPressed: ()=>{
_demopluginPlugin.toast("测试数据")
}, child: Text("点击toast"))
],
)
),
),
);
}
最后总结
到此我们的flutter鸿蒙化 插件开发我们就讲完了,那么如何打包插件发布还有和其他端交互例如 ios还有鸿蒙,我们在后面我们补上去,因为篇幅有限我这边就不展开讲,原理都差不多 也是使用Methodchannel 交互的,如果同学有兴趣可以自己研究 也可以继续等待老师后续的更新,今天的文章就讲到这里,, 今天的文章就讲到这里有兴趣的 关注我B站教程 了解更多鸿蒙开发的知识 可以关注坚果派公众号 。 谢谢