Mobile Development 11 min read

Using Pigeon for Flutter Development on HarmonyOS

The article shows how to integrate Flutter's Pigeon tool into HarmonyOS to automatically generate ETS channel code, enabling Flutter developers to avoid writing native HarmonyOS code by adding the pigeon package, defining an API, running the generation command, and using the generated setup in the HarmonyOS side.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Using Pigeon for Flutter Development on HarmonyOS

在鸿蒙中开发Flutter项目,一个最大的问题,就是“不太会写鸿蒙代码”,这对于一个Flutter开发者来说,虽然不是一件很麻烦的事,但由于现在鸿蒙的版本和文档还略有一些混乱,所以要写好还是有一些麻烦的,所以,秉着能用工具解决的问题就不要自己写的原则,我们参考Native的Flutter Channel的实现,也就是pigeon的方式,不熟悉的同学可以参考我之前的文章。

Flutter混编工程之高速公路Pigeon

这套东西在鸿蒙中也有的适配,可以一键生成ets代码,方便我们进行多端复用,项目地址如下。

https://gitee.com/openharmony-sig/flutter_packages/tree/master/packages/pigeon

在鸿蒙中使用也非常简单,指定引用即可,代码如下所示。

yaml
pigeon:
git:
url: "https://gitee.com/openharmony-sig/flutter_packages.git"
path: "packages/pigeon"

pub get之后,参考我们之前的实现,创建一个接口协议文件,这里就用之前的来示例。

dart
import 'package:pigeon/pigeon.dart';
@HostApi()
abstract class NativeNetApi {
@async
String
getNativeNetBridge(
String
path,
Map
<
String
,
Object
> params);
@async
String
postNativeNetBridge(
String
path,
Map
<
String
,
Object
> params);
void
doActionUrlCall(
String
actionUrl);
}

接下来执行命令:

shell
flutter pub run pigeon --input lib/native_api.dart --arkts_out lib/native_channel.ets --dart_out lib/native_channel.dart

执行完成后,就会在指定目录下生成我们需要的Channel文件,dart代码我就不贴了,和之前文章中的一样,我们来看下鸿蒙的代码。

arkts
import StandardMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec';
import BasicMessageChannel, { Reply } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BasicMessageChannel';
import { BinaryMessenger,TaskQueue } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger';
import MessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/MessageCodec';
import { ByteBuffer } from '@ohos/flutter_ohos/src/main/ets/util/ByteBuffer';
/** Error class for passing custom error details to Flutter via a thrown PlatformException. */
export class FlutterError implements Error {
/** The error code. */
public code: string;
/** The error name. */
public name: string;
/** The error message. */
public message: string;
/** The error stack. */
public stack?: string;
constructor(code: string, name: string,  message: string, stack: string)
{
this.code = code;
this.name = name;
this.message = message;
this.stack = stack;
}
}
function wrapError(error: Error): Array<Object> {
let errorList: Array<Object> = new Array<Object>(3);
if (error instanceof FlutterError) {
let err: FlutterError = error as FlutterError;
errorList[0] = err.code;
errorList[1] = err.name;
errorList[2] = err.message;
} else {
errorList[0] = error.toString();
errorList[1] = error.name;
errorList[2] = "Cause: " + error.message + ", Stacktrace: " + error.stack;
}
return errorList;
}
export interface Result<T> {
success( result: T ): void;
error( error: Error): void;
}
/* Generated abstract class from Pigeon that represents a handler of messages from Flutter.*/
export abstract class NativeNetApi {
abstract getNativeNetBridge(path: string , params: Map<string, Object> , result: Result<string>): void;
abstract postNativeNetBridge(path: string , params: Map<string, Object> , result: Result<string>): void;
abstract doActionUrlCall(actionUrl: string ): void;
/** The codec used by NativeNetApi. */
static getCodec(): MessageCodec<Object>{
return new StandardMessageCodec();
}
/*Sets up an instance of `NativeNetApi` to handle messages through the `binaryMessenger`.*/
static setup(binaryMessenger: BinaryMessenger, api: NativeNetApi | null): void {
{
let channel: BasicMessageChannel<Object> =
new BasicMessageChannel(
binaryMessenger, "dev.flutter.pigeon.test1.NativeNetApi.getNativeNetBridge", NativeNetApi.getCodec());
if (api != null) {
channel.setMessageHandler({
onMessage(message: Object ,reply: Reply<Object> ) {
let args: Array<Object> = message as Array<Object>;
class ResultImp implements Result<string>{
success(result: string): void {
let res: Array<Object> = [];
res.push(result);
reply.reply(res);
}
error(error: Error): void {
let wrappedError: Array<Object> = wrapError(error);
reply.reply(wrappedError);
}
}
let resultCallback: Result<string> = new ResultImp();
api!.getNativeNetBridge(args[0] as string, args[1] as Map<string, Object>, resultCallback);
} });
} else {
channel.setMessageHandler(null);
}
}
{
let channel: BasicMessageChannel<Object> =
new BasicMessageChannel(
binaryMessenger, "dev.flutter.pigeon.test1.NativeNetApi.postNativeNetBridge", NativeNetApi.getCodec());
if (api != null) {
channel.setMessageHandler({
onMessage(message: Object ,reply: Reply<Object> ) {
let args: Array<Object> = message as Array<Object>;
class ResultImp implements Result<string>{
success(result: string): void {
let res: Array<Object> = [];
res.push(result);
reply.reply(res);
}
error(error: Error): void {
let wrappedError: Array<Object> = wrapError(error);
reply.reply(wrappedError);
}
}
let resultCallback: Result<string> = new ResultImp();
api!.postNativeNetBridge(args[0] as string, args[1] as Map<string, Object>, resultCallback);
} });
} else {
channel.setMessageHandler(null);
}
}
{
let channel: BasicMessageChannel<Object> =
new BasicMessageChannel(
binaryMessenger, "dev.flutter.pigeon.test1.NativeNetApi.doActionUrlCall", NativeNetApi.getCodec());
if (api != null) {
channel.setMessageHandler({
onMessage(message: Object ,reply: Reply<Object> ) {
let args: Array<Object> = message as Array<Object>;
let res: Array<Object> = [];
try {
api!.doActionUrlCall(args[0] as string);
res.push(null);
}
catch (error) {
let wrappedError: Array<Object> = wrapError(error);
res = wrappedError;
}
reply.reply(res);
} });
} else {
channel.setMessageHandler(null);
}
}
}
}
}

整体代码和Java的代码很类似,阅读基本没什么障碍,使用方式也和Native保持一致,通过调用setup方法,传入接口的实现即可,这里就不赘述了。

< END >

Fluttermobile developmentcross‑platformHarmonyOSNative IntegrationPigeon
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.