鸿蒙系统 (HarmonyOS)是华为推出的一款分布式操作系统,那么如何在保证开发迭代效率的前提下,以相对低的成本将移动应用快速移植到鸿蒙平台上呢?美团外卖 MTFlutter 团队近期做了一次技术探索,成功地实现了 Flutter 对于鸿蒙系统的原生支持。
// 创建一个用于管理 Surface 的容器组件 SurfaceProvider surfaceProvider = new SurfaceProvider(context); // 注册视图创建回调 surfaceProvider.getSurfaceOps().get().addCallback(surfaceCallback); // ... 在 surfaceCallback 中 @Override public void surfaceCreated(SurfaceOps surfaceOps) { Surface surface = surfaceOps.getSurface(); // ...将 surface 通过 JNI 交给 Native 侧 FlutterJNI.onSurfaceCreated(surface); }
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
b. 与 Surface 关联的本地窗口对象
鸿蒙目前开放的 Native API 并不多,在官方文档中,我们可以比较容易地找到 Native_layer API。根据文档的说明,Native API 中的 NativeLayer 对象刚好对应了 Java 侧的 Surface 类,借助 GetNativeLayer 方法,我们实现了两者之间的转化:
// platform_view_android_jni_impl.cc static void SurfaceCreated(JNIEnv* env, jobject jcaller, jlong shell_holder, jobject jsurface) { fml::jni::ScopedJavaLocalFrame scoped_local_reference_frame(env); // 通过鸿蒙 Native API 获取本地窗口对象 NativeLayer auto window = fml::MakeRefCounted<AndroidNativeWindow>( GetNativeLayer(env, jsurface)); ANDROID_SHELL_HOLDER->GetPlatformView()->NotifyCreated(std::move(window)); }
c. 与本地窗口对象关联的 EGLSurface
在 Android 的 AOSP 实现中,EGLSurface 可通过 EGL 库的 eglCreateWindowSurface 方法从本地窗口对象 ANativeWindow 创建而来。对于鸿蒙而言,虽然我们没有从公开文档找到类似的说明,但是鸿蒙标准库默认支持了 OpenGL ES,而且鸿蒙 SDK 中也附带了 EGL 相关的库及头文件,我们有理由相信在鸿蒙系统上,EGLSurface 也可以通过此方法从前一步生成的 NativeLayer 转化而来,在之后的验证中我们也确认了这一点:
// window->handle() 即为之前得到的 NativeLayer EGLSurface surface = eglCreateWindowSurface( display, config_, reinterpret_cast<EGLNativeWindowType>(window->handle()), attribs); //...交给 Flutter 渲染管线
2. 交互能力实现
交互能力是支撑 Flutter 应用能够正常运行的另一个基本要求。在 Flutter 中,交互包含了各种触摸事件、鼠标事件、键盘录入事件的传递及消费。以触摸事件为例,Flutter 事件传递的整个流程如下图所示:
iOS/Android 的原生容器通过触摸事件的回调 API 接收到事件之后,会将其打包传递至引擎层,后者将事件传发给 Flutter 框架层,并完成事件的消费、分发和逻辑处理。同样,整个流程的大部分工作已经由 Flutter 统一,我们要做的仅仅是在原生容器上监听用户的输入,并封装成指定格式交给引擎层而已。