Ace(foundation/arkui/ace_engine_lite)是OpenHarmony的轻量级系统所使用的UI框架子系统,为开发者提供JS-UI开发框架。包括.html,.css,.js。
想了解更多关于开源的内容,请访问:
51CTO 开源基础软件社区
https://ost.51cto.com
在《#跟着小白一起学鸿蒙# [九] 写个简单的LED驱动》我们熟悉了如何在开源鸿蒙开发驱动应用,并通过hdc工具拷贝至开发板运行。在《#跟着小白一起学鸿蒙#[六]第一个hap应用》的文章里我们学会如何用IDE工具编写hap应用并他通过IDE工具安装至开发板运行。我们学会了hap程序的开发,但是hap程序是运行在标准系统的应用,对于轻量和小型系统我们应该如何进行开发呢?接下来我们需要学习下如何开发JS应用。
轻量、小型系统JS应用
Ace(foundation/arkui/ace_engine_lite)是OpenHarmony的轻量级系统所使用的UI框架子系统,为开发者提供JS-UI开发框架。包括.html,.css,.js。开发者可以通过DevEco工具进行开发。其中JS的引擎采用三方库里的JerryScript(jerryscript是IoT设备上的轻量级JS引擎,支持ECMAScript 5.1标准,适配低内存硬件,最小运行在64KB RAM和小于200KB的flash,提供C API)。关于jerryscript的详细介绍可以看如下参考链接(https://github.com/jerryscript-project/jerryscript )。
详细的内容介绍在一下链接内可以看到官方的说明:
参考链接:https://gitee.com/openharmony/arkui_ace_engine_lite。
此样例参考小熊派设计,使用小熊派HM_Micro开发板进行验证。
JS-UI开发流程
graph LR
--> 配置工程 --> 增加LED程序 --> 添加JSAPI接口
创建工程配置工程增加LED程序添加JSAPI接口编译运行。
建立[Lite]Empty Ability。
配置工程。
工程结构说明。
工程目录主要在entry里,有以下内容:
- .preview: 界面预览目录。
- build: 工程编译目录。
- src:包括i18n(国际化翻译路径),pages(界面目录,index.css, index.hml, index.js)。
工程预览。
添加按键功能控制LED灯。
<div class="container">
<text class="title">
{{ $t('strings.hello') }} {{ title }}
</text>
<div class="rowcontainer">
<text class="content" if="{{statu == '0'}}">[状态:{{ $t('strings.ledoff') }}]</text>
<text class="content" if="{{statu == '1'}}">[状态:{{ $t('strings.ledon') }}]</text>
<text class="content" onclick="ledon">
{{ $t('strings.ledon') }}
</text>
<text class="content" onclick="ledoff">
{{ $t('strings.ledoff') }}
</text>
<text class="content" onclick="ledtoggle">
{{ $t('strings.ledtoggle') }}
</text>
</div>
<text class="content" onclick="exit">
{{ $t('strings.exit') }}
</text>
</div>
.container {
width: 100%;
height: 100%;
flex-direction: column;
justify-content: center;
align-items: center;
}
.title {
width: 200px;
font-size: 30px;
text-align: center;
}
.content{
width: 200px;
font-size: 30px;
text-align: center;
}
.rowcontainer {
width: 100%;
height: 50%;
flex-direction: row;
justify-content: center;
align-items: center;
}
var led = {open:1,close:0,change:2}
import app from '@system.app';
export default {
data: {
title: "",
statu:'0'
},
onInit() {
this.title = this.$t('strings.world');
},
ledon(e) {
let that = this
console.info("ledon")
app.ledcontrol({
code:led.open,
success(res){
that.statu = res.led_status
},
fail(res,code){
console.error("ledon error")
},
complete(){
console.info("ledon complete")
}
})
},
ledoff(e) {
let that = this
console.info("ledoff")
app.ledcontrol({
code:led.close,
success(res){
that.statu = res.led_status
},
fail(res,code){
console.error("ledoff error")
},
complete(){
console.info("ledoff complete")
}
})
},
ledtoggle(e) {
let that = this
console.info("ledtoggle")
app.ledcontrol({
code:led.change,
success(res){
that.statu = res.led_status
},
fail(res,code){
console.error("ledtoggle failed")
},
complete(){
console.info("ledtoggle complete")
}
})
},
exit(e) {
app.terminate()
},
}
- 将代码编译成hap包:点击编辑器最左下角的OhosBuild Varilants,打开编译模式选择视图,编译模式分debug和release,选择release模式;
- 点击编辑器上方菜单栏的Build->Build Hap(s)/App(s)->Build Hap(s),系统就会开始自动编译代码成hap包,等到下方Build Output无编译错误,就表示代码编译完成了。
增加JS的API接口。
JSI::SetModuleAPI(exports, "ledcontrol", AppModule::ToggleLed);
#include "hdf_sbuf.h"
#include "hdf_io_service_if.h"
#define LED_WRITE_READ 1
#define LED_SERVICE "hdf_led"
......
static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
{
uint32_t value;
HdfSbufReadUint32(data, &value);
HILOG_ERROR(HILOG_MODULE_ACE,"%s: dev event received: %u %u\n", (char *)priv, id, value);
return HDF_SUCCESS;
}
static int GpioWriteRead(struct HdfIoService *serv, int32_t eventData, int32_t *val)
{
int ret = HDF_FAILURE;
struct HdfSBuf *data = HdfSBufObtainDefaultSize();
struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
if (data == NULL || reply == NULL) {
HILOG_ERROR(HILOG_MODULE_ACE,"fail to obtain sbuf data\n");
return ret;
}
if (!HdfSbufWriteUint8(data, (uint8_t)eventData))
{
HILOG_ERROR(HILOG_MODULE_ACE,"fail to write sbuf\n");
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
return ret;
}
ret = serv->dispatcher->Dispatch(&serv->object, LED_WRITE_READ, data, reply);
if (ret != HDF_SUCCESS)
{
HILOG_ERROR(HILOG_MODULE_ACE,"fail to send service call\n");
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
return ret;
}
if (!HdfSbufReadInt32(reply, val))
{
HILOG_ERROR(HILOG_MODULE_ACE,"fail to get service call reply\n");
ret = HDF_ERR_INVALID_OBJECT;
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
return ret;
}
HILOG_ERROR(HILOG_MODULE_ACE,"Get reply is: %d\n", val);
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
return ret;
}
JSIValue AppModule::ToggleLed(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
{
HILOG_ERROR(HILOG_MODULE_ACE, "led button pressed.");
struct HdfIoService *serv = HdfIoServiceBind(LED_SERVICE);
if (serv == NULL)
{
HILOG_ERROR(HILOG_MODULE_ACE,"fail to get service2 %s\n", LED_SERVICE);
return JSI::CreateUndefined();
}
if ((args == nullptr) || (argsNum == 0) || (JSI::ValueIsUndefined(args[0]))) {
return JSI::CreateUndefined();
}
JSIValue success = JSI::GetNamedProperty(args[0], CB_SUCCESS);
JSIValue fail = JSI::GetNamedProperty(args[0], CB_FAIL);
JSIValue complete = JSI::GetNamedProperty(args[0], CB_COMPLETE);
int32_t num = (int32_t)JSI::GetNumberProperty(args[0], "code");
int32_t replyData = 0;
if (GpioWriteRead(serv, num, &replyData))
{
HILOG_ERROR(HILOG_MODULE_ACE,"fail to send event\n");
JSI::CallFunction(fail, thisVal, nullptr, 0);
JSI::CallFunction(complete, thisVal, nullptr, 0);
JSI::ReleaseValueList(success, fail, complete);
return JSI::CreateUndefined();
}
JSIValue result = JSI::CreateObject();
JSI::SetNumberProperty(result, "led_status", replyData);
JSIValue argv[ARGC_ONE] = {result};
JSI::CallFunction(success, thisVal, argv, ARGC_ONE);
JSI::CallFunction(complete, thisVal, nullptr, 0);
JSI::ReleaseValueList(success, fail, complete, result);
HdfIoServiceRecycle(serv);
return JSI::CreateUndefined();
}
- 在foundation\ace\ace_engine_lite\ace_lite.gni中添加HDF头文件路径
ace_lite_include_dirs += [
......
"//drivers/framework/ability/sbuf/include",
"//drivers/framework/include/core",
"//drivers/framework/include/utils",
"//drivers/adapter/uhdf/posix/include",
]
修改foundation\ace\ace_engine_lite\frameworks\BUILD.gn,在public_deps中添加以下代码
"//drivers/adapter/uhdf/manager:hdf_core",
修改foundation\ace\ace_engine_lite\test\ace_test_config.gni,在extra_deps中添加以下代码
"//drivers/adapter/uhdf/manager:hdf_core",
总结
- 基于JS扩展的类Web开发范式的方舟开发框架,采用经典的HML、CSS、JavaScript三段式开发方式。使用HML标签文件进行布局搭建,使用CSS文件进行样式描述,使用JavaScript文件进行逻辑处理。UI组件与数据之间通过单向数据绑定的方式建立关联,当数据发生变化时,UI界面自动触发更新。此种开发方式,更接近Web前端开发者的使用习惯,快速将已有的Web应用改造成方舟开发框架应用。主要适用于界面较为简单的中小型应用开发;
- 通过appmodule调用framework层接口,然后通过framework接口调用Hdf接口。
这样我们就有了自己的driver和配置,后面的章节我们会讲如何在hap应用里调用驱动接口。
想了解更多关于开源的内容,请访问:
51CTO 开源基础软件社区
https://ost.51cto.com。