鸿蒙端H5容器化建设——JSB通信机制建设

1. 背景

2023年鸿蒙开发者大会上,华为宣布为了应对国外技术封锁的潜在风险,2024年的HarmonyOS NEXT版本中将不再兼容Android,并推出鸿蒙系统以及其自研的开发框架,形成开发生态闭环。同时,在更高维度上华为希望将鸿蒙系统拓展应用到手机、智能穿戴、车机、家居等一系列物联网设备上,形成万物互联的品牌生态闭环。

基于以上背景,鸿蒙端上APP的适配问题是开发者不得不面对的问题,适配也将从原生和跨端两个方面进行。鸿蒙原生ArkTs包含的内容可以对标Android原生,既多又杂,可以参考官方文档;跨端则涉及H5、RN、Flutter的鸿蒙化适配。由于目前产品的跨端重心在H5,因此本文将主要介绍鸿蒙端H5容器化的适配工作,同时简述鸿蒙系统框架以及开发模式。

2. 鸿蒙系统架构

在这里插入图片描述
HarmonyOS整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。可以看出,已经了抛离AOSP和JVM,去除了对Android依赖。

内核层

采用多内核设计,提供进程/线程管理、内存管理、文件系统、网络管理和外设管理等基础内核能力。驱动子系统HDF提供统一外设访问能力和驱动开发管理框架。

系统服务层

包括适用于各类设备的基础能力以及面向特定设备的专有能力,每个子系统内部支持按功能粒度裁剪。

框架层

为应用开发提供Java/C/C++/JS等多语言的用户程序框架,以及各种软硬件服务对外开放的多语言框架API。

应用层

支持基于框架层实现业务功能开发,支持跨设备调度与分发,为用户提供一致、高效的应用体验。

3. 鸿蒙开发模式

开发工具DevEco-Studio

开发工具下载地址:HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者,和Android Studio的功能和设计大体一致,工程结构也有诸多相似之处。但是仅处于起步阶段,各种问题还需要完善和解决,诸如模拟器H5页面无法交互、以及各种调试问题等。

开发语言与UI框架

ArkTs是华为基于TypeScript的自研开发语言。ArkUI 是一套声明式开发框架,它具备简洁自然的 UI 信息语法、丰富的 UI 组件、多维状态管理,以及实时多维度预览等能力,只需使用一套ArkTS API,就能在多个HarmonyOS设备上提供生动而流畅的用户界面体验,帮助开发者提升应用开发效率。

编译模式

ArkCompiler利用ArkTS的静态类型信息,进行类型推导并生成对象描述和内联缓存,加速运行时对字节码的解释执行;AOT(Ahead-of-Time)Compiler利用静态类型信息直接将字节码编译生成优化机器码,让应用启动即可运行高性能代码,提升应用启动和运行性能。

APP包结构

APP由一个或多个HAP(Harmony Ability Package)包以及描述APP属性的pack.info文件组成。HAP是Abiltiy类型的模块编译后的产物,而Library类型的模块编译后的产物为HAR(静态共享包)或者HSP(动态共享包),两者都是为了实现代码和资源的共享。HAR中的代码和资源跟随使用方编译,多个使用方会存在多份拷贝,而HSP中的代码和资源可以独立编译,运行时在同一进程中仅有一份,从而避免包膨胀问题。

4. 适配工作

原生业务

目前项目中,Native原始业务与H5跨端业务并存,基于Native的业务在新的鸿蒙系统上将无法运行,为了兼顾用户体验问题,只能使用ArkTS进行重写。这将是一个繁杂且漫长的适配工程,需要明确App核心功能,在初期版本上优先适配核心业务能力。

H5业务

鸿蒙提供了H5页面运行所需的Web容器,H5页面是可以百分百复用的。但是H5侧依赖Native能力的各种API需要额外做定制和适配,从而实现真正的H5容器化SDK,这将是优先级极高的适配工作。其中,H5与Native之间的通信机制建设则是重中之重的适配内容。

5. H5容器化建设——JSB通信机制建设

ArkTS侧与H5的通信机制是首先要解决的问题,有了JSB的桥,才有后续Native能力支撑的可能。JSB通信总体可以分为四个步骤来进行:
在这里插入图片描述

5.1 JSBridge初始化

在初始化阶段,需要通过webviewControll.runJavaScript()将JSBridge初始化脚本注入H5执行。脚本代码如下所示。其中callID用来标识H5回调;JSBridgeCallback方法用来执行H5侧回调;window.ohosCallNative对象给H5侧提供调用函数。

export const code = `
  const JSBridgeMap = {};
  let callID = 0;
  
  // 执行H5回调函数
  function JSBridgeCallback (id, params) {
    JSBridgeMap[id](params);
    JSBridgeMap[id] = null;
    delete JSBridgeMap[id];
  }
  // 在window中声明callNative方法供H5调用
  window.ohosCallNative = {
    callNative(method, params, callback) {
      const id = callID++;
      const paramsObj = {
          callID: id,
          data: params || null
      }
      JSBridgeMap[id] = callback || (() => {});
      JSBridgeHandle.call(method, JSON.stringify(paramsObj));
    }
  }
`;

5.2 JS代理注入

通过Web组件的javaScriptProxy属性,将JSBridgeHandle对象注册到H5侧的window上,作为H5调用原生的通道。

// JsBridge.ets
export default class JsBridge {
  controller: WebView.WebviewController;

  constructor(controller: WebView.WebviewController) {
    this.controller = controller;
  }
  /**
   * 注入JavaScript对象到window对象中  
   */
  get javaScriptProxy(): JavaScriptItem {
    return {
      object: {
        call: this.call
      },
      name: "JSBridgeHandle",
      methodList: ['call'],
      controller: this.controller
    } as JavaScriptItem;
  }
  
   initJsBridge(): void {
    this.controller.runJavaScript(code);
  }
}

// PageDemo.ets
@Entry
@Component
struct PageDemo {
  webController: WebView.WebviewController = new WebView.WebviewController();
  private jsBridge: JSBridge = new JSBridge(this.webController);

  build() {
    Column() {
      Web({
        src: $rawfile('MainPage.html'),
        controller: this.webController
      })
        .javaScriptAccess(true)
        .javaScriptProxy(this.jsBridge.javaScriptProxy)
        .onPageBegin(() => {
          this.jsBridge.initJsBridge();
        })
        ...
    }
    ...
  }
}

/**
 * javaScriptProxy object type.
 */
export interface callType {
  call: (func: string, params: string) => void
}

export interface JavaScriptItem {
  object: callType,
  name: string,
  methodList: Array<string>,
  controller: WebviewController
}

5.3 H5侧入口与回调

H5侧调用ohosCallNative对象中的callNative方法,传递func、params以及callback回调。在callNative中保存callback回调,并调用JSBridgeHandle的call方法。call方法作为H5调用原生侧接口的统一入口,在该方法中根据H5调用的方法名,匹配到对应的接口后调用,调用结束后通过this.callback()方法,将调用结果回传到H5。

// JsBridge.ets
export default class JsBridge {
  /**
   * 将ArkTS侧数据传递给call方法
   */
  call = (func: string, params: string): void => {
    const paramsObject: ParamsItem = JSON.parse(params);
    let result: Promise<string> = new Promise((resolve) => resolve(''));
    switch (func) {
      case 'funName':
        result = "result from ArkTS";
        break;
      default:
        break;
    }
    result.then((data: string) => {
      this.callback(paramsObject?.callID, data);
    })
  }

  /**
   * 将ArkTS侧数据传递到H5
   */
  callback = (id: number, data: string): void => {
    this.controller.runJavaScript(`JSBridgeCallback("${id}", ${JSON.stringify(data)})`);
  }
}


/**
 * Function params object.
 */
export interface ParamsItem {
  callID: number
}

5.4 H5侧主动发起调用ArkTS

实现了上述桥接逻辑后,在H5侧只需要调用ohosCallNative方法,将函数名以及回调函数传递到ArkTS。

  window.ohosCallNative.callNative('funName', {}, (data) => {
    ...
  });

6. 总结

本文概述了鸿蒙系统的架构以及开发模式,并且指出鸿蒙的适配工作任重而道远。其中,Native侧的迁移适配需要大量的时间和成本;而H5作为天然的跨端生态,尤其是在业务中本来就有很重的业务承载,那么H5容器化是首先要去适配的。ArkTS与H5的JSB通信机制则是本文的重点描述内容,剩下的H5容器所需的Native能力,则需要一点一点去补齐。

  • 26
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Smobiler是一款基于Visual Studio的.Net移动开发平台,可以帮助开发者快速构建跨平台的移动应用程序。本教程将介绍如何使用Smobiler平台开发移动应用程序。 ## 环境准备 在开始使用Smobiler平台之前,您需要先准备好以下环境: - 安装Visual Studio 2015或更高版本(支持Community、Professional和Enterprise版本)。 - 下载并安装Smobiler插件。您可以从Smobiler官方网站下载最新版本的插件。 ## 创建一个新项目 在Visual Studio中创建一个新项目时,选择Smobiler模板。您可以选择创建一个空白项目或使用预定义的模板。 ![smobiler1](https://img-blog.csdn.net/20180517195225849?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Jsb2c4MzY3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ## Smobiler设计器 Smobiler设计器是一个可视工具,用于创建和编辑移动应用程序。您可以使用设计器来添加控件、设置属性和布局等操作。 ![smobiler2](https://img-blog.csdn.net/2018051719533935?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Jsb2c4MzY3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 在设计器中,您可以通过拖放控件来创建移动应用程序。Smobiler平台提供了大量的控件,包括标签、按钮、文本框、列表、图像等。 ![smobiler3](https://img-blog.csdn.net/20180517200003835?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Jsb2c4MzY3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) 您可以通过属性窗口来设置控件的属性。例如,您可以设置按钮的文本、字体、颜色和大小等。 ![smobiler4](https://img-blog.csdn.net/20180517200135489?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Jsb2c4MzY3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) ## 编写代码 在Smobiler平台中,您可以使用C#或VB.NET编写代码。您可以通过拖放控件并设置属性来创建用户界面,然后在代码中添加事件处理程序。 例如,以下代码演示了如何在按钮单击事件中弹出一个消息框。 ``` private void button1_Press(object sender, EventArgs e) { MessageBox.Show("Hello, Smobiler!"); } ``` ## 打包和发布应用程序 一旦您完成了应用程序的开发,您可以使用Smobiler平台来打包并发布应用程序。Smobiler提供了多种打包选项,包括Android、iOS和Windows Phone等。 要打包应用程序,请在Smobiler IDE中选择“Build”菜单,并选择相应的打包选项。然后,您可以将生成的应用程序发布到适当的应用商店或网站上。 ## 总结 本教程介绍了如何使用Smobiler平台来创建移动应用程序。通过使用Smobiler平台,您可以快速构建跨平台的移动应用程序,并且可以使用C#或VB.NET编写代码。如果您想深入了解Smobiler平台的更多功能,请访问官方网站或查看其他教程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值