flutter 鸿蒙化插件开发横空出世

1,913 阅读3分钟

前言导读

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

效果图

image.png

image.png

具体实现

  • 创建插件工程
flutter create -t plugin --platforms ohos,android,ios <plugin_name>

image.png

image.png

导入我们的插件工程

image.png

  • 1 我们的lib目录下面编写我们的插件和原生交互的dart代码

  • 2 example 下面是我们调试插件的代码

  • 3 ohos 是我们的插件原生部分代码

  • 我们选直接运行下我们的项目 让devceo studio 拉一下我们的gradle

  • 我们打开example 项目下面的ohos工程 (谨记不是根目录下面的ohos工程)

image.png

  • 然后让devceo studio 构建

image.png

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

image.png

这个demo我们一共编写了 获取鸿蒙系统版本号和toast的案例

  • 获取鸿蒙系统版本号

if (call.method == "getPlatformVersion") {
  result.success("OpenHarmony "+deviceInfo.distributionOSVersion)
}
  • toast

 if(call.method=='toast') {
  let str:string=call.argument('param') as string;
  console.log("str-- > "+str);

  prompt.showToast({
    message:str
  })

}

这里需要注意我们flutter 端 是通过map传递参数给我们鸿蒙next端的

@override
 toast(String str) async {
  Map<String,dynamic>user={
    'param':str
  };
   await methodChannel.invokeMethod<String>('toast',user);
}
  • 完整插件原始鸿蒙next代码

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端插件代码实现

我们先再插件父类抽象类里面 定义我们跟原生端交互的方法

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 类里面实现这些方法

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 端

@visibleForTesting
final methodChannel = const MethodChannel('demoplugin');
  • 鸿蒙原生端

onAttachedToEngine(binding: FlutterPluginBinding): void {
  this.channel = new MethodChannel(binding.getBinaryMessenger(), "demoplugin");
  this.channel.setMethodCallHandler(this)
}
  • 然后我们定义 Demoplugin 定义对应的对外方法 给我们的 example 调试工程调用

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系统版本号调用
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调用
@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站教程谢谢

如果想看Flutter插件开发化android交互在这里

flutter 插件开发化android 交互