Flutter OHOS 如何导入自渲染内容到 Flutter

5 阅读3分钟

背景介绍

支持将外部自渲染内容(无论是通过 NativeDrawing 等OHOS CAPI 绘制,还是通过 OpenGL 相关接口绘制)通过外接纹理的方式导入 Flutter 的 Texture 组件进行展示。以下是具体实现方法。

使用前提

Flutter版本需要3.22及以上


实现步骤

1. Dart 侧操作

1.1 创建Texture组件

  • 创建Texture组件,绑定textureId

1.2 注册纹理

  • 创建 MethodChannel:

    final MethodChannel _channel = const MethodChannel('PictureChannel1');

  • 在 initState 函数中注册纹理:

    _textureId = await _channel.invokeMethod("registerStarTexture");

1.3 注销纹理

  • 在 dispose 函数中注销纹理:

    _channel.invokeMethod('unregisterTexture', {'textureId': _textureId});


2. OHOS侧操作

2.1 引入工具类

需要引入以下工具类:

import { TextureRegistry, SurfaceTextureEntry } from '@ohos/flutter_ohos/src/main/ets/view/TextureRegistry';

2.2 提供的实现方式

提供了两种将自渲染内容导入 Flutter 纹理的实现方式。


实现方式一:通过 getNativeWindowId 绘制到 Buffer

通过 getNativeWindowId 获取引擎层 Texture 对应的 OHNativeWindow 指针,然后将自渲染内容绘制到该 window 对应的 Buffer 上。

ArkTS 侧实现步骤

  1. 注册纹理时获取相关信息:
    this.textureId = this.textureRegistry!.getTextureId();
    this.surfaceTextureEntry = this.textureRegistry!.registerTexture(this.textureId);
    this.windowId = this.surfaceTextureEntry.getNativeWindowId();
    drawNapi.drawPatternWindow(this.windowId, 300, 300);// 需要在cpp层实现draw函数,接收window指针
  1. 调用 cpp 层函数,将自渲染内容绘制到该 window:

    drawNapi.drawPatternWindow(this.windowId, 300, 300); // 需要在 cpp 层实现此函数

CPP 侧实现步骤

  1. 使用 OH_NativeWindow_NativeWindowHandleOpt 设置 window 的 USAGE、宽高等信息。
  2. 调用 OH_NativeWindow_NativeWindowRequestBuffer 获取 window 的 Buffer。
  3. 使用 OH_NativeWindow_GetBufferHandleFromNative 获取 bufferHandle。
  4. 使用 OH_NativeWindow_NativeWindowFlushBuffer 将生产好的 Buffer 放到 Buffer 队列中供消费。

实现方式二:通过 setExternalNativeImage

直接将用于内容生产的 NativeImage 指针传递给 Flutter 引擎层,由引擎层利用该 NativeImage 通过 OH_NativeImage_SetOnFrameAvailableListener 注册帧可用回调进行内容消费。

ArkTS 侧实现步骤

  1. 注册纹理时获取相关信息:
    this.textureId = this.textureRegistry!.getTextureId();
    this.surfaceTextureEntry = this.textureRegistry!.registerTexture(this.textureId);
    drawNapi.drawPatternWindow(1000, 1000);
    this.nativeImageId = drawNapi.getNativeImage();// 获取用于内容生产的NativeImage
    this.textureRegistry!.setExternalNativeImage(this.textureId, this.nativeImageId);// 将NativeImage传入引擎层

CPP 侧实现步骤

以下为基于 OpenGL 的简单绘制实现步骤:

  1. 使用 OH_NativeImage_Create 创建 NativeImage。
  2. 使用 OH_NativeImage_AcquireNativeWindow 获取 NativeImage 关联的 window。
  3. 使用 OH_NativeWindow_NativeWindowHandleOpt 设置 USAGE 和宽高。
  4. 将 NativeWindow 转换为 EGLNativeWindowType 类型。
  5. 调用以下 OpenGL 相关指令完成绘制:
    • eglCreateWindowSurface
    • eglCreateContext
    • eglMakeCurrent
    • gl 绘制相关指令
    • eglSwapBuffers

纹理注销

无论使用上述哪种方式,都需要调用以下函数进行纹理注销:

this.textureRegistry!.unregisterTexture(textureId);


参考实现

实现参考

flutter_it_image

代码位置说明

  1. Dart 侧代码
    方式一: 相关代码位于 lib/PicturePage1.dart,最下方添加的纹理组件用于自渲染内容导入。
    方式二: 相关代码位于 lib/PicturePage2.dart。

  2. ArkTS 侧代码
    方式一: 相关代码位于 ohos/entry/src/main/ets/entryability/PicturePlugin1.ets,包含了纹理的注册和注销函数。
    方式二: 相关代码位于 ohos/entry/src/main/ets/entryability/PicturePlugin2.ets。

  3. 原生绘制代码
    相关代码位于 ohos/entry/src/main/cpp。


注意事项

  1. 开发者在使用方式二时,需要自行管理 NativeImage 的生命周期,并确保在 unregister 前对象不会销毁。