предисловие
Система Хунмэн(HarmonyOS) — ориентированная на будущее, ориентированная на все сценарии распределенная операционная система, выпущенная Huawei. Основываясь на традиционных возможностях системы с одним устройством, Hongmeng предлагает распределенную концепцию, основанную на том же наборе системных возможностей и адаптирующуюся к множеству форм терминалов. С момента выпуска HarmonyOS 2.0 в сентябре 2020 г. компания Huawei ускорила масштабное внедрение системы Hongmeng. Ожидается, что к концу 2021 г. система Hongmeng будет охватывать сотни миллионов конечных устройств, включая мобильные телефоны, планшеты, умные носимые устройства, умные экраны и автомобильные машины. Для мобильных приложений,Новые системные концепции и новые формы взаимодействия также означают новые возможности.. Если мы сможем эффективно использовать экологию разработки Hongmeng, ее функции и возможности, мы сможем позволить приложениям охватывать больше интерактивных сценариев и типов устройств, создавая тем самым новые точки роста.
По сравнению с открывающимися возможностями проблемы, связанные с адаптацией системы Hongmeng, столь же огромны. Что касается текущих мобильных телефонов, хотя система Hongmeng по-прежнему поддерживает установку и работу Android APK, в долгосрочной перспективе Huawei обязана отказаться от AOSP и постепенно развивать собственную экологию, а это означает, что существующие приложения Android на устройствах Hongmeng постепенно станут " «Граждане второго сорта». Однако, если мы повторно разработаем и будем поддерживать набор приложений Hongmeng в дополнение к iOS и Android, в сегодняшних условиях, когда отрасль уделяет все больше и больше внимания эффективности разработки и итерации, стоимость разработки будет неисчислимой. Поэтому очень важным вариантом стало создание подходящей кросс-энд фреймворка, перенос приложения на платформу Hongmeng с относительно низкой стоимостью и эффективное использование функций и возможностей системы.
Среди множества существующих кросс-энд фреймворков Flutter имеет заметное преимущество в адаптации новых систем благодаря своей высокой согласованности с несколькими конечными точками, обеспечиваемой возможностью саморендеринга. Хотя официальный FlutterАдаптироваться к Hongmeng не планируется, но после периода исследований и практики команда Meituan Food Delivery MTFlutter успешно внедрила встроенную поддержку Flutter для системы Hongmeng.
Это также следует объяснить заранее, потому что система Hongmeng все еще находится в бета-версии, поэтому этот план адаптации еще не был запущен в реальном бизнесе, что является относительно ранним исследованием на техническом уровне. Далее в этой статье мы поделимся нашим опытом в процессе переноса и разработки, представив принцип и некоторые детали реализации. Надеюсь, это может вдохновить или помочь вам всем.
Введение в базовые знания и основные понятия
Прежде чем начнется адаптация, нам нужно знать, что делать в первую очередь. Давайте сначала рассмотрим трехуровневую структуру Flutter:
В архитектурном дизайне Flutter верхний слойслой кадра, разработанный на языке Dart, для разработчиков бизнеса Flutter, средний слой —слой двигателя, разработанный на C/C++ и реализующий основные возможности, такие как конвейер рендеринга Flutter и среда выполнения Dart; нижний слой —Встраиваемый слой, отвечающий за реализацию возможностей, связанных с платформой. Очевидно, что мы хотим портировать слой встраивания в Hongmeng, точнее, мы хотимПовторно внедрить уровень внедрения Flutter с помощью возможностей платформы, изначально предоставляемых Hongmeng..
Для адаптации встроенного слоя Flutter у официального Flutter есть не очень подробныйгид, фактическая стоимость операции очень высока. Поскольку языком бизнес-разработки Hongmeng по-прежнему может быть Java, и он имеет сходство с Android во многих основных концепциях (как показано в следующей таблице), мы можем начать с реализации Android и завершить портирование Hongmeng.
Адаптация Flutter на Hongmeng
Как упоминалось выше, для завершения переноса Flutter на новую систему нам необходимо полностью реализовать все подмодули, необходимые для встроенного уровня Flutter, и с точки зрения поддержки возможностей,оказывать,взаимодействоватьтак же какДругие необходимые встроенные возможности платформыЭто самый основной элемент, гарантирующий, что приложение Flutter может работать, и его необходимо поддерживать в первую очередь. Он будет представлен по очереди.
1. Процесс рендеринга завершен
Давайте еще раз рассмотрим процесс рендеринга изображений во Flutter. Как показано на рисунке, устройство инициируетВертикальная синхронизацияПосле сигнала (VSync) он сначала проходит через конвейер рендеринга потока пользовательского интерфейса (Animate/Build/Layout/Paint), затем проходит через комбинацию и растеризацию потока Raster и, наконец, преобразует изображение в OpenGL или Vulkan.верхний экран.这个流程的大部分工作都由框架层和引擎层完成,对于鸿蒙的适配,我们主要关注的是与设备自身能力相关的问题,即:
(1) Как отслеживать сигнал VSync устройства и уведомлять механизм Flutter? (2) Откуда берется объект окна, используемый OpenGL/Vulkan для экрана?
Мониторинг и передача сигналов VSync
В реализации движка Flutter для Android сигнал VSync устройства передается черезChoreographerСрабатывает, процесс его производства и потребления показан на следующем рисунке:
После того, как инфраструктура Flutter регистрирует обратный вызов VSync, она ожидает сигнала VSync через класс VsyncWaiter на стороне C++, последний вызывает через серию вызовов, таких как JNI, и, наконец, класс VsyncWaiter на стороне Java вызывает Android SDK.Choreographer.postFrameCallbackМетод, затем передайте механизм флаттера механизму FLUTTER через слой JNI. Основной код VsyncWaiter на стороне Java выглядит следующим образом:
@Override
public void asyncWaitForVsync(long cookie) {
Choreographer.getInstance()
.postFrameCallback(
new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
float fps = windowManager.getDefaultDisplay().getRefreshRate();
long refreshPeriodNanos = (long) (1000000000.0 / fps);
FlutterJNI.nativeOnVsync(
frameTimeNanos, frameTimeNanos + refreshPeriodNanos, cookie);
}
});
}
Во всем процессе, кроме Choreographer из Android SDK, большая часть логики почти реализована базовым SDK C++ и Java, который можно переиспользовать прямо на Hongmeng.Проблема в том, что текущие документы API Hongmeng еще не открылись возможности аналогичны Choreographer. Так что на данном этапе мы можем позаимствовать аналогичную iOS от Hongmeng.Grand Central DispatchAPI потока имитирует триггер сигнала и обратный вызов VSync:
@Override
public void asyncWaitForVsync(long cookie) {
// 模拟每秒 60 帧的屏幕刷新间隔:向主线程发送一个异步任务, 16ms 后调用
applicationContext.getUITaskDispatcher().delayDispatch(() -> {
float fps = 60; // 设备刷新帧率,HarmonyOS 未暴露获取帧率 API,先写死 60 帧
long refreshPeriodNanos = (long) (1000000000.0 / fps);
long frameTimeNanos = System.nanoTime();
FlutterJNI.nativeOnVsync(frameTimeNanos, frameTimeNanos + refreshPeriodNanos, cookie);
}, 16);
};
Визуализация конструкции и доставки окон
В этой части нам нужно создать контейнер платформы в системе Hongmeng, чтобы предоставить объект окна для верхнего экрана для графического рендеринга движка Flutter. Точно так же мы обращаемся к реализации Flutter для Android, чтобы увидеть, как это делает система Android:
Flutter поддерживает механизмы рендеринга Vulkan и OpenGL на Android.Для экономии места мы сосредоточимся только на OpenGL. Помимо сложных деталей регистрации и вызова, по сути, весь процесс в основном делает три вещи:
- создалпросмотр объекта, предоставьте Surface, который можно использовать для прямого рисования, и передайте его нативной стороне через JNI;
- Получить поверхность, связанную с исходной сторонойобъект локального окна, и передайте его контейнеру платформы Flutter;
- Преобразование собственного объекта окна в OpenGL ES с поддержкойПоверхность рисования (EGLSurface), который используется для рендеринга на экране с помощью движка Flutter.
Затем мы используем возможности платформы, предоставляемые Hongmeng, для достижения этих трех пунктов.
А. Просмотр объектов, которые можно использовать для прямого рисования
Структура пользовательского интерфейса системы HongmengПредоставляет множество общих компонентов представления (Component), такие как кнопки, текст, картинки, списки и т. д., но нам нужно избавиться от этих компонентов верхнего уровня и получить возможность рисовать напрямую. С помощью официальныхРуководство по разработке медиаплеераДокументация, вы можете найти, что Hongmeng предоставляетSurfaceProviderкласс, который управляетSurfaceОбъекты можно использовать для презентаций с декодированием видео. Рендеринг Flutter в принципе похож на видео на экране, поэтому мы можем использовать SurfaceProvider для управления и создания Surface:
// 创建一个用于管理 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);
}
б) объект локального окна, связанный с поверхностью
В настоящее время в Hongmeng открыто не так много нативных API, и мы можем легко найти их в официальных документах.Native_layer API. Согласно документации, в Native APINativeLayerОбъект просто соответствует классу Surface на стороне Java, с помощью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реализация АОСП, к EGLSurface можно получить доступ через библиотеку EGL.eglCreateWindowSurfaceметод из собственного объекта окнаANativeWindowсозданный. Для Hongmeng, хотя мы не нашли подобных инструкций в общедоступных документах,Стандартная библиотека ХунмэнOpenGL ES поддерживается по умолчанию, а связанные с EGL библиотеки и файлы заголовков также включены в Hongmeng SDK.У нас есть основания полагать, что в системе Hongmeng EGLSurface также может быть сгенерирован из предыдущего шага с помощью этого метода.NativeLayerПреобразованные, мы также подтвердили это в последующих проверках:
// window->handle() 即为之前得到的 NativeLayer
EGLSurface surface = eglCreateWindowSurface(
display, config_, reinterpret_cast<EGLNativeWindowType>(window->handle()),
attribs);
//...交给 Flutter 渲染管线
2. Реализация возможности взаимодействия
Возможность взаимодействияЭто еще одно основное требование для поддержки нормальной работы приложений Flutter. Во Flutter взаимодействие включает в себя передачу и потребление различных событий касания, событий мыши и событий ввода с клавиатуры. Взяв в качестве примера сенсорные события, весь процесс доставки событий Flutter показан на следующем рисунке:
После того, как нативный контейнер iOS / Android получает событие через API обратного вызова сенсорного события, он упадет его и передает его на слой двигателя, который будет передавать мероприятие на слой фрейдера, и завершить потребление, распределение и Логическая обработка события. Кроме того, большая часть работы всего процесса была объединена трепетом, все, что нам нужно сделать, это работать на родном контейнеремониторпользовательский ввод иупаковкаОн просто передается на уровень движка в указанном формате.
В системе Hongmeng мы можем использоватьМультимодальный входной API, для реализации мониторинга различных типов событий:
flutterComponent.setTouchEventListener(touchEventListener); // 触摸及鼠标事件
flutterComponent.setKeyEventListener(keyEventListener); // 键盘录入事件
flutterComponent.setSpeechEventListener(speechEventListener); // 语音录入事件
Для инкапсуляции и обработки событий можно повторно использовать существующую логику Android, нужно только обратить внимание на соответствующие отношения между Hongmeng и Android в обработке событий, такие как частичное соответствие сенсорных событий:
3. Другие необходимые возможности платформы
Чтобы обеспечить нормальную работу приложений Flutter, в дополнение к самому базовому рендерингу и взаимодействию наш встроенный уровень также предоставляет возможности платформы, такие как управление ресурсами, цикл событий и синхронизация жизненного цикла. Для большинства из этих возможностей Flutter имеет объявления абстрактных классов в общедоступной части уровня встраивания, и их нужно только повторно реализовать с помощью API Hongmeng.
Например, управление ресурсами, движок обеспечиваетAssetResolverЗаявление о том, что мы можем использовать HongmengRawfileAPI для достижения:
class HAPAssetMapping : public fml::Mapping {
public:
HAPAssetMapping(RawFile* asset) : asset_(asset) {}
~HAPAssetMapping() override { CloseRawFile(asset_); }
size_t GetSize() const override { return GetRawFileSize(asset_); }
const uint8_t* GetMapping() const override {
return reinterpret_cast<const uint8_t*>(GetRawFileBuffer(asset_));
}
private:
RawFile* const asset_;
FML_DISALLOW_COPY_AND_ASSIGN(HAPAssetMapping);
};
Для контура события двигатель обеспечиваетMessageLoopImplАбстрактный класс, мы можем использовать HongmengNative_EventHandlerРеализация API:
// runner_ 为鸿蒙 EventRunnerNativeImplement 的实例
void MessageLoopHarmony::Run() {
FML_DCHECK(runner_ == GetEventRunnerNativeObjForThread());
int result = ::EventRunnerRun(runner_);
FML_DCHECK(result == 0);
}
void MessageLoopHarmony::Terminate() {
int result = ::EventRunnerStop(runner_);
FML_DCHECK(result == 0);
}
Для синхронизации жизненного цикла Hongmeng'sPage AbilityОбеспечивает полный обратный вызов жизненного цикла (как показано на рисунке ниже), нам нужно только сообщить о состоянии движку в соответствующее время.
Когда вышеуказанные возможности готовы, мы можем успешно запустить приложение Flutter. Следующее черезDevEco Studioработать официальноflutter galleryСкриншот приложения, движок Flutter переписан с использованием возможностей платформы системы Hongmeng:
Благодаря возможностям поддержки нескольких устройств Hongmeng это приложение может работать даже на телевизорах, автомобильных телефонах, часах, планшетах и других устройствах:
Резюме и перспективы
Благодаря вышеуказанным работам по созданию и адаптации мы реализовали трансплантацию Flutter в системе Hongmeng с очень небольшими затратами на разработку.Бизнес верхнего уровня, разработанный на основе Flutter, может изначально работать в системе Hongmeng без каких-либо изменений.Чтобы соответствовать Система Hongmeng Последующее крупномасштабное продвижение также заранее подготовило технические резервы.
Конечно, на этом история не заканчивается. Помимо самых основных возможностей работы и взаимодействия, нам нужно уделять больше внимания комбинации Flutter и собственной экологии Hongmeng: как элегантно адаптироваться к распределенной технологии Hongmeng? Как использовать Flutter для быстрого подключения и совместного использования ресурсов между устройствами? Как применить множество существующих плагинов Flutter к системе Hongmeng? В будущем команда MTF Flutter проведет более глубокие исследования в этих областях, потому что решение этих проблем является ключом к тому, чтобы приложение действительно охватывало всю сцену жизни пользователя.
использованная литература
- developer.huawei.com/consumer/can…
- developer.harmony OS.com/talent/document…
- flutter.Dev/docs/ Горячие запросы, такие как…
- GitHub.com/flutter/Appendix…
об авторе
Ян Чао, который присоединился к технической команде Meituan по доставке еды в 2016 году, в настоящее время в основном отвечает за инфраструктуру, связанную с MTFlutter.
|Чтобы прочитать больше технических статей, подпишитесь на официальный аккаунт Meituantech в WeChat.
|В строке меню официальной учетной записи ответьте на такие ключевые слова, как [акции 2019 г.], [акции 2018 г.], [акции 2017 г.], [алгоритм], и вы сможете просмотреть коллекцию технических статей, подготовленных технической командой Meituan за эти годы. .