https://harmonyos.51cto.com/#zz
前言
上一篇,我们体验了一下鸿蒙上的界面的开发流程,这一篇我们继续深入一点点,尝试打通从用户态UI到内核态HDF之间的联系。其中涉及到的调用关系比较复杂,建议在“用鸿蒙开发AI应用(五)HDF 驱动补光灯”的基础上阅读本文,HDF的相关细节这里就不在赘述了。
背景知识
用户程序框架子系统包含两个大的模块:Ability子系统和包管理子系统。
1. Ability子系统
1.1 Ability
Ability是系统调度应用的最小单元,是能够完成一个独立功能的组件,一个应用可以包含一个或多个Ability。Ability分为两种类型:Page类型的Ability和Service类型的Ability
Page类型的Ability:带有界面,为用户提供人机交互的能力。
Service类型的Ability:不带界面,为用户提供后台任务机制。
1.2 AbilitySlice
AbilitySlice是单个页面及其控制逻辑的总和,是Page类型Ability特有的组件,一个Page类型的Ability可以包含多个AbilitySlice,此时,这些页面提供的业务能力应当是高度相关的。
1.3 生命周期
生命周期是Ability被调度到启动、激活、隐藏和退出等各个状态的的统称。
Ability生命周期各状态解析:
UNINITIALIZED:未初始状态,为临时状态,Ability被创建后会由UNINITIALIZED状态进入INITIAL状态;
INITIAL:初始化状态,也表示停止状态,表示当前Ability未运行,调用Start后进入INACTIVE,同时回调开发者的OnStart生命周期回调;
INACTIVE:未激活状态,表示当前窗口已显示但是无焦点状态,由于Window暂未支持焦点的概念,当前状态与ACTIVE一致。
ACTIVE:前台激活状态,表示当前窗口已显示,并获取焦点,Ability在退到后台之前先由ACTIVE状态进入INACTIVE状态;
BACKGROUND: 后台状态,表示当前Ability退到后台,Ability在被销毁后由BACKGROUND状态进入INITIAL状态,或者重新被激活后由BACKGROUND状态进入ACTIVE状态。
1.4 AbilityLoader
AbilityLoader负责注册和加载开发者Ability的模块。开发者开发的Ability先要调用AbilityLoader的注册接口注册到框架中,接着Ability启动时会被实例化。
1.5 AbilityManager
AbilityManager负责AbilityKit和Ability管理服务进行IPC的通信。
1.6 EventHandler
EventHandler是AbilityKit提供给开发者的用于在Ability中实现线程间通信的一个模块。
1.7 Ability运行管理服务
Ability运行管理服务是用于协调各Ability运行关系、及生命周期进行调度的系统服务。
其中,服务启动模块负责Ability管理服务的启动、注册等。
服务接口管理模块负责Ability管理服务对外能力的管理。
进程管理模块负责Ability应用所在进程的启动和销毁、及其进程信息维护等功能。Ability栈管理模块负责维护各个Ability之间跳转的先后关系。
生命周期调度模块是Ability管理服务根据系统当前的操作调度Ability进入相应的状态的模块。
连接管理模块是Ability管理服务对Service类型Ability连接管理的模块。
1.8 AppSpawn
AppSpawn是负责创建Ability应用所在进程的系统服务,该服务有较高的权限,为Ability应用设置相应的权限,并预加载一些通用的模块,加速应用的启动。
2. 包管理子系统
包管理子系统,是OpenHarmony为开发者提供的安装包管理框架。
BundleKit:是包管理服务对外提供的接口,有安装/卸载接口、包信息查询接口、包状态变化监听接口。
包扫描器:用来解析本地预制或者安装的安装包,提取里面的各种信息,供管理子模块进行管理,持久化。
包安装子模块:安装,卸载,升级一个包;包安装服务一个单独进程的用于创建删除安装目录,具有较高的权限。
包管理子模块:管理安装包相关的信息,存储持久化包信息。
包安全管理子模块:签名检查、权限授予、权限管理。
HDF驱动LED(可选)
之前在内核中已经注册过一个led_driver驱动,并以led_service服务发布,这一节稍微重构一下代码,功能上没有变化,我们快速过一遍,熟悉HDF的可以自行跳过。
1. 业务代码
先新建头文件vendor\huawei\hdf\led\include\led_ctrl.h。
- #ifndef _LED_CTRL_H
- #define _LED_CTRL_H
- #include "hdf_device_desc.h"
- #include "hdf_log.h"
- #include "device_resource_if.h"
- #include "osal_io.h"
- #include "osal_mem.h"
- #include "gpio_if.h"
- #include "osal_irq.h"
- #include "osal_time.h"
- #ifdef __cplusplus
- extern "C" {
- #endif /* __cplusplus */
- extern int32_t CtlLED(int mode);
- #ifdef __cplusplus
- }
- #endif /* __cplusplus */
- #endif /* _LED_CTRL_H */
再新建源文件 vendor\huawei\hdf\led\led_ctrl.c
- #include "led_ctrl.h"
- #define HDF_LOG_TAG led_driver // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签
- int32_t CtlLED(int mode)
- {
- int32_t ret;
- uint16_t valRead;
- /* LED的GPIO管脚号 */
- // uint16_t gpio = 5 * 8 + 1; // 红外补光灯
- uint16_t gpio = 2 * 8 + 3; // 绿色指示灯
- // uint16_t gpio = 3 * 8 + 4; // 红色指示灯
- /* 将GPIO管脚配置为输出 */
- ret = GpioSetDir(gpio, GPIO_DIR_OUT);
- if (ret != 0)
- {
- HDF_LOGE("GpioSerDir: failed, ret %d\n", ret);
- return ret;
- }
- if (mode == -1)
- {
- // 翻转输出口
- (void)GpioRead(gpio, &valRead);
- ret = GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW);
- }
- else
- {
- ret = GpioWrite(gpio, mode);
- }
- if (ret != 0)
- {
- HDF_LOGE("GpioWrite: failed, ret %d\n", ret);
- return ret;
- }
- return ret;
- }
先完成对绿色指示灯的控制逻辑。
2. 驱动实现
在 huawei/hdf 目录下新建一个文件夹 led, 然后在其中新建一个源文件 led.c。
- #include "hdf_device_desc.h" // HDF框架对驱动开放相关能力接口的头文件
- #include "hdf_log.h" // HDF 框架提供的日志接口头文件
- #include "led_ctrl.h"
- // #define HDF_LOG_TAG led_driver // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签
- #define LED_WRITE_READ 1 // 读写操作码1
- // Dispatch是用来处理用户态发下来的消息
- int32_t LedDriverDispatch(struct HdfDeviceIoClient *client, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
- {
- int32_t result = HDF_FAILURE;
- HDF_LOGE("Led driver dispatch");
- if (client == NULL || client->device == NULL)
- {
- HDF_LOGE("Led driver device is NULL");
- return HDF_ERR_INVALID_OBJECT;
- }
- switch (cmdCode)
- {
- case LED_WRITE_READ:
- const char *recv = HdfSbufReadString(data);
- if (recv != NULL)
- {
- HDF_LOGI("recv: %s", recv);
- result = CtlLED(-1);
- // result = CtlLED(GPIO_VAL_HIGH);
- if (!HdfSbufWriteInt32(reply, result))
- {
- HDF_LOGE("replay is fail");
- }
- return HdfDeviceSendEvent(client->device, cmdCode, data);
- }
- break;
- default:
- break;
- }
- return result;
- }
- //驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架
- int32_t HdfLedDriverBind(struct HdfDeviceObject *deviceObject)
- {
- if (deviceObject == NULL)
- {
- HDF_LOGE("Led driver bind failed!");
- return HDF_ERR_INVALID_OBJECT;
- }
- static struct IDeviceIoService ledDriver = {
- .Dispatch = LedDriverDispatch,
- };
- deviceObject->service = (struct IDeviceIoService *)(&ledDriver);
- HDF_LOGD("Led driver bind success");
- return HDF_SUCCESS;
- }
- // 驱动自身业务初始的接口
- int32_t HdfLedDriverInit(struct HdfDeviceObject *deviceObject)
- {
- if (deviceObject == NULL)
- {
- HDF_LOGE("Led driver Init failed!");
- return HDF_ERR_INVALID_OBJECT;
- }
- HDF_LOGD("Led driver Init success");
- return HDF_SUCCESS;
- }
- // 驱动资源释放的接口
- void HdfLedDriverRelease(struct HdfDeviceObject *deviceObject)
- {
- if (deviceObject == NULL)
- {
- HDF_LOGE("Led driver release failed!");
- return;
- }
- HDF_LOGD("Led driver release success");
- return;
- }
- // 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量
- struct HdfDriverEntry g_ledDriverEntry = {
- .moduleVersion = 1,
- .moduleName = "led_driver",
- .Bind = HdfLedDriverBind,
- .Init = HdfLedDriverInit,
- .Release = HdfLedDriverRelease,
- };
- // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
- HDF_INIT(g_ledDriverEntry);
3. 驱动编译
在 huawei/hdf/led 目录下新建编译文件 Makefile。
- include $(LITEOSTOPDIR)/../../drivers/hdf/lite/lite.mk
- MODULE_NAME := hdf_led_driver
- LOCAL_SRCS += led_ctrl.c \
- led.c \
- LOCAL_INCLUDE := ./include
- LOCAL_CFLAGS += -fstack-protector-strong -Wextra -Wall -Werror
- include $(HDF_DRIVER)
4. 编译结果链接到内核镜像
修改 huawei/hdf/hdf_vendor.mk 文件,添加以下代码
- LITEOS_BASELIB += -lhdf_led_driver #链接生成的静态库
- LIB_SUBDIRS += $(VENDOR_HDF_DRIVERS_ROOT)/led #驱动代码Makefile的目录
5. 驱动配置
修改 vendor/hisi/hi35xx/hi3516dv300/config/device_info/device_info.hcs配置文件,添加驱动的设备描述。
- platform :: host {
- hostName = "platform_host"; // host名称,host节点是用来存放某一类驱动的容器
- priority = 50; // host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序
- device_led :: device { // led设备节点
- device0 :: deviceNode { // led驱动的DeviceNode节点
- policy = 2; // policy字段是驱动服务发布的策略,在驱动服务管理章节有详细介绍
- priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序
- preload = 0; // 驱动按需加载字段
- permission = 0666; // 驱动创建设备节点权限
- moduleName = "led_driver"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
- serviceName = "led_service"; // 驱动对外发布服务的名称,必须唯一
- deviceMatchAttr = "led_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等
- }
- }
编译用户程序框架子系统
1. 添加配置文件
在 build/lite/platform/hi3516dv300_liteos_a/platform.json中的subsystems字段下面添加appexecfwk和aafwk。
- {
- "subsystem": "aafwk",
- "components": [
- {
- "component": "ability",
- "optional": "true",
- "dirs": [
- "foundation/aafwk"
- ],
- "targets": [
- "//foundation/aafwk/frameworks/ability_lite:aafwk_abilitykit_lite",
- "//foundation/aafwk/frameworks/ability_lite:aafwk_abilityMain_lite",
- "//foundation/aafwk/frameworks/abilitymgr_lite:aafwk_abilityManager_lite",
- "//foundation/aafwk/services/abilitymgr_lite:aafwk_services_lite"
- ],
- "features": [
- {"enable_ohos_appexecfwk_feature_ability": "true"}
- ],
- "deps": {
- "components": [
- "hilog_a",
- "bundle_mgr",
- "system_ability_manager",
- "distributed_schedule",
- "graphic",
- "utils",
- "ipc"
- ],
- "third_party": [
- "cjson",
- "bounds_checking_function"
- ]
- }
- }
- ]
- },
- {
- "subsystem": "appexecfwk",
- "components": [
- {
- "component": "bundle_mgr",
- "optional": "true",
- "dirs": [
- "foundation/appexecfwk"
- ],
- "targets": [
- "//foundation/appexecfwk/services/bundlemgr_lite:appexecfwk_services_lite",
- "//foundation/appexecfwk/frameworks/bundle_lite:appexecfwk_kits_lite"
- ],
- "features": [],
- "deps": {
- "components": [
- "iam",
- "app_verify",
- "hilog_a",
- "system_ability_manager",
- "global_resource_manager",
- "graphic",
- "utils"
- ],
- "third_party": [
- "cjson",
- "zlib"
- ]
- }
- }
- ]
- },
2. 添加编译文件
新建build\lite\config\subsystem\aafwk\BUILD.gn文件,
- import("//build/lite/config/subsystem/lite_subsystem.gni")
- lite_subsystem("aafwk") {
- subsystem_components = [
- "//foundation/aafwk/frameworks/ability_lite:aafwk_abilitykit_lite",
- "//foundation/aafwk/frameworks/abilitymgr_lite:aafwk_abilityManager_lite",
- "//foundation/aafwk/services/abilitymgr_lite:aafwk_services_lite",
- ]
- }
新建/build/lite/config/subsystem/appexecfwk/BUILD.gn文件,
- import("//build/lite/config/subsystem/lite_subsystem.gni")
- lite_subsystem("appexecfwk") {
- subsystem_components = [
- "//foundation/appexecfwk/kits/appkit_lite:appexecfwk_kit_lite",
- "//foundation/appexecfwk/services/bundlemgr_lite:appexecfwk_services_lite",
- ]
- }
3. 运行管理服务
用户程序框架有两个系统服务ability管理服务(abilityms)和(bundlems),两系统服务运行于foundation进程中。
abilityms和bundlems注册到sa_manager中,sa_manager运行于foundation进程中,sa_manager为abilityms和bundlems创建线程运行环境。
在foundation/distributedschedule/services/safwk_lite/BUILD.gn中添加对abilityms和bundlems
- deps = [
- "...",
- ]
- if (ohos_kernel_type == "liteos_a") {
- deps += [
- "...",
- "//foundation/aafwk/services/abilitymgr_lite:abilityms",
- "//foundation/appexecfwk/services/bundlemgr_lite:bundlems",
- "...",
- ]
- }
基于AbilityKit开发的Ability
1. 主页面实现
新建源文件applications\sample\camera\myLedApp\src\main_ability.cpp
- #include "main_ability.h"
- namespace OHOS {
- REGISTER_AA(MainAbility)
- void MainAbility::OnStart(const Want &want)
- {
- printf("MainAbility::OnStart\n");
- SetMainRoute("MainAbilitySlice");
- Ability::OnStart(want);
- }
2. 分片页面
2.1 定义控件常量
新建源文件main_ability_slice.cpp, 屏幕大小为960x480
- #include "main_ability_slice.h"
- #include "ability_manager.h"
- #include "components/ui_label.h"
- #include "components/ui_label_button.h"
- namespace OHOS
- {
- REGISTER_AS(MainAbilitySlice)
- constexpr static int BUTTON1_POSITION_X = 380;
- constexpr static int BUTTON1_POSITION_Y = 200;
- constexpr static int BUTTON_WIDTH = 200;
- constexpr static int BUTTON_HEIGHT = 80;
- constexpr static int ROOT_VIEW_POSITION_X = 0;
- constexpr static int ROOT_VIEW_POSITION_Y = 0;
- constexpr static int ROOT_VIEW_WIDTH = 960;
- constexpr static int ROOT_VIEW_HEIGHT = 480;
- constexpr static uint8_t ROOT_VIEW_OPACITY = 255;
- constexpr static uint8_t FONT_ID = 10;
- constexpr static int BUTTON1_POSITION_X = 380;
- constexpr static int BUTTON1_POSITION_Y = 200;
- constexpr static int BUTTON_WIDTH = 200;
- constexpr static int BUTTON_HEIGHT = 80;
- constexpr static int ROOT_VIEW_POSITION_X = 0;
- constexpr static int ROOT_VIEW_POSITION_Y = 0;
- constexpr static int ROOT_VIEW_WIDTH = 960;
- constexpr static int ROOT_VIEW_HEIGHT = 480;
- constexpr static uint8_t ROOT_VIEW_OPACITY = 255;
- constexpr static uint8_t FONT_ID = 10;
- } // namespace OHOS
2.2 创建按钮和布局
在生命周期函数OnStart中,全屏放置一个rootView_,居中位置放置一个按钮button1。
- void MainAbilitySlice::OnStart(const Want &want)
- {
- printf("MainAbilitySlice::OnStart\n");
- AbilitySlice::OnStart(want);
- auto button1 = new UILabelButton();
- button1->SetPosition(BUTTON1_POSITION_X, BUTTON1_POSITION_Y);
- button1->SetText("翻转 LED");
- button1->Resize(BUTTON_WIDTH, BUTTON_HEIGHT);
- button1->SetFontId(FONT_ID);
- button1->SetStyle(STYLE_TEXT_COLOR, Color::Black().full);
- button1->SetStyle(STYLE_TEXT_OPA, ROOT_VIEW_OPACITY);
- button1->SetStyle(STYLE_BACKGROUND_OPA, ROOT_VIEW_OPACITY);
- rootView_ = RootView::GetWindowRootView();
- rootView_->SetPosition(ROOT_VIEW_POSITION_X, ROOT_VIEW_POSITION_Y);
- rootView_->Resize(ROOT_VIEW_WIDTH, ROOT_VIEW_HEIGHT);
- rootView_->Add(button1);
- SetUIContent(rootView_);
- }
2.3 实现驱动消息机制
这里顺便提一下,文档中DevSvcManagerClntGetService接口仅在内核态有效,可以方便的获取服务并直接调用。鸿蒙作为微内核的OS,想从用户态调用内核态函数,要么用框架的消息机制,要么自己用中断服务实现。
- #define LED_WRITE_READ 1
- #define LED_SERVICE "led_service"
- static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
- {
- const char *string = HdfSbufReadString(data);
- if (string == NULL)
- {
- printf("fail to read string in event data\n");
- return HDF_FAILURE;
- }
- printf("%s: dev event received: %u %s\n", (char *)priv, id, string);
- return HDF_SUCCESS;
- }
- static int SendEvent(struct HdfIoService *serv, const char *eventData)
- {
- int ret = 0;
- struct HdfSBuf *data = HdfSBufObtainDefaultSize();
- if (data == NULL)
- {
- printf("fail to obtain sbuf data\n");
- return 1;
- }
- struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
- if (reply == NULL)
- {
- printf("fail to obtain sbuf reply\n");
- ret = HDF_DEV_ERR_NO_MEMORY;
- HdfSBufRecycle(data);
- return ret;
- }
- if (!HdfSbufWriteString(data, eventData))
- {
- printf("fail to write sbuf\n");
- ret = HDF_FAILURE;
- HdfSBufRecycle(data);
- HdfSBufRecycle(reply);
- return ret;
- }
- ret = serv->dispatcher->Dispatch(&serv->object, LED_WRITE_READ, data, reply);
- if (ret != HDF_SUCCESS)
- {
- printf("fail to send service call\n");
- HdfSBufRecycle(data);
- HdfSBufRecycle(reply);
- return ret;
- }
- int replyData = 0;
- if (!HdfSbufReadInt32(reply, &replyData))
- {
- printf("fail to get service call reply\n");
- ret = HDF_ERR_INVALID_OBJECT;
- HdfSBufRecycle(data);
- HdfSBufRecycle(reply);
- return ret;
- }
- printf("Get reply is: %d\n", replyData);
- HdfSBufRecycle(data);
- HdfSBufRecycle(reply);
- return ret;
- }
2.4 加入点击事件
每次点击按钮,向内核态发送一次消息。
- auto onClick = [this](UIView &view, const Event &event) -> bool {
- printf("led button pressed\n");
- struct HdfIoService *serv = HdfIoServiceBind(LED_SERVICE, 0);
- if (serv == NULL)
- {
- printf("fail to get service %s\n", LED_SERVICE);
- return false;
- }
- static struct HdfDevEventlistener listener = {
- .callBack = OnDevEventReceived,
- .priv = (void *)"Service0"};
- if (HdfDeviceRegisterEventListener(serv, &listener) != HDF_SUCCESS)
- {
- printf("fail to register event listener\n");
- return false;
- }
- const char *send_cmd = "toggle LED";
- if (SendEvent(serv, send_cmd))
- {
- printf("fail to send event\n");
- return false;
- }
- if (HdfDeviceUnregisterEventListener(serv, &listener))
- {
- printf("fail to unregister listener\n");
- return false;
- }
- HdfIoServiceRecycle(serv);
- return true;
- };
2.5 注销页面
在生命周期函数OnStop中,删除所有节点,回收系统资源。
- void DeleteViewChildren(UIView *view)
- {
- if (view == nullptr) {
- return;
- }
- while (view != nullptr) {
- UIView *tempView = view;
- view = view->GetNextSibling();
- if (tempView->IsViewGroup()) {
- DeleteViewChildren(dynamic_cast<UIViewGroup *>(tempView)->GetChildrenHead());
- }
- if (tempView->GetParent()) {
- dynamic_cast<UIViewGroup *>(tempView->GetParent())->Remove(tempView);
- }
- delete tempView;
- }
- }
- void MainAbilitySlice::OnStop()
- {
- printf("MainAbilitySlice::OnStop\n");
- AbilitySlice::OnStop();
- DeleteViewChildren(rootView_);
- }
3. 编译配置
新增 applications\sample\camera\myLedApp\BUILD.gn文件
- import("//build/lite/config/component/lite_component.gni")
- import("//build/lite/config/subsystem/aafwk/config.gni")
- HDF_FRAMEWORKS = "//drivers/hdf/frameworks"
- src_path = "//applications/sample/camera/myLedApp/src"
- lite_library("ledability") {
- target_type = "shared_library"
- ldflags = [
- "-shared",
- ]
- sources = [
- "${src_path}/main_ability.cpp",
- "${src_path}/main_ability_slice.cpp",
- ]
- include_dirs = [
- ".",
- "//foundation/aafwk/frameworks/ability_lite/example/entry/src/main/cpp",
- "//foundation/aafwk/interfaces/innerkits/abilitymgr_lite",
- "//foundation/aafwk/interfaces/kits/ability_lite",
- "//foundation/aafwk/interfaces/kits/want_lite",
- "//foundation/appexecfwk/interfaces/kits/bundle_lite",
- "//foundation/appexecfwk/utils/bundle_lite",
- "//foundation/communication/interfaces/kits/ipc_lite",
- "//foundation/graphic/lite/interfaces/kits/config",
- "//foundation/graphic/lite/interfaces/kits/ui",
- "//foundation/graphic/lite/interfaces/kits/utils",
- "//kernel/liteos_a/kernel/common",
- "//kernel/liteos_a/kernel/include",
- "//drivers/hdf/lite/include/host",
- "$HDF_FRAMEWORKS/ability/sbuf/include",
- "$HDF_FRAMEWORKS/core/shared/include",
- "$HDF_FRAMEWORKS/core/host/include",
- "$HDF_FRAMEWORKS/core/master/include",
- "$HDF_FRAMEWORKS/include/core",
- "$HDF_FRAMEWORKS/include/utils",
- "$HDF_FRAMEWORKS/utils/include",
- "$HDF_FRAMEWORKS/include/osal",
- "//kernel/liteos_a/platform/include",
- "$HDF_FRAMEWORKS/adapter/syscall/include",
- "$HDF_FRAMEWORKS/adapter/vnode/include",
- ]
- deps = [
- "//foundation/aafwk/frameworks/ability_lite:aafwk_abilitykit_lite",
- "//drivers/hdf/lite/manager:hdf_core",
- "//drivers/hdf/lite/adapter/osal/posix:hdf_posix_osal",
- ]
- defines = [
- "OHOS_APPEXECFWK_BMS_BUNDLEMANAGER",
- ]
- if (enable_ohos_appexecfwk_feature_ability == true) {
- deps += [
- "//foundation/graphic/lite/frameworks/ui:ui",
- ]
- defines += [
- "ENABLE_WINDOW=1",
- "ABILITY_WINDOW_SUPPORT"
- ]
- }
- output_dir = "$root_out_dir/dev_tools/led"
- }
4. 应用配置文件
新建 applications\sample\camera\myLedApp\config.json
- {
- "app": {
- "bundleName": "com.bluishfish.ledability",
- "vendor": "huawei",
- "version": {
- "code": 1,
- "name": "1.0"
- },
- "apiVersion": {
- "compatible": 3,
- "target": 3
- }
- },
- "deviceConfig": {
- "default": {
- "keepAlive": false
- }
- },
- "module": {
- "deviceType": [
- "smartVision"
- ],
- "distro": {
- "deliveryWithInstall": true,
- "moduleName": "ledability",
- "moduleType": "entry"
- },
- "abilities": [{
- "name": "MainAbility",
- "icon": "assets/entry/resources/base/media/icon.png",
- "label": "Led Ability",
- "launchType": "standard",
- "type": "page",
- "visible": true
- }
- ]
- }
- }
5. 板级编译配置
复制 build/lite/product/ipcamera_hi3516dv300.json,改名为my_hi3516dv300在子系统里加入
- {
- "ohos_version": "OpenHarmony 1.0",
- "board": "hi3516dv300",
- "kernel": "liteos_a",
- "compiler": "clang",
- "subsystem": [
- {
- "name": "aafwk",
- "component": [
- "......",
- { "name": "ability_led", "dir": "//applications/sample/camera/myLedApp:ledability", "features": []}
- ]
- "......"
6. 编译应用
- python build.py my_hi3516dv300 -b debug
将系统烧录到开发板上。
7. 打包应用
在 assets\entry\resources\base\media\目录下放置一个icon.png作为启动图标。
将applications\sample\camera\myLedApp\config.json和 Z:\openharmony\out\my_hi3516dv300\dev_tools\led\libledability.so打包压缩成zip包
改名为ledability.hap ,复制到NFS共享目录
8. 安装Hap
- mkdir nfs
- mount 192.168.1.57:/nfs /nfs nfs
- ./nfs/dev_tools/bin/bm set -s disable
- ./nfs/dev_tools/bin/bm install -p ./nfs/ledability.hap
9. 运行程序
- ./nfs/dev_tools/bin/aa start -p com.bluishfish.ledability -n MainAbility
完美!
总结
整理一下思路,
我们先用AbilityKit绘制Ability页面,在其button1上绑定一个按钮事件;
触发后,由用户子系统寻找到led_server服务,向HDF框架发送消息;
内核驱动led_driver接收到消息后,调用底层GPIO控制LED翻转,并将操作状态以reply消息的形式传回用户侧;
后续可以接着根据返回状态更新下界面。
好了,在此基础上美化下界面,接个继电器做个智能家居的App应该不是难事了。
源码下载
PS:最近收到了社区之星的礼物,还有前沿新书《鸿蒙应用开发实战》,感谢一下小编的辛苦工作。
下一篇预告
用C++来写UI开发效率总是不如java和js高的,
何况还没法用上DevEco Studio辅助设计,
下一篇我们尝试实现更多的设备能力,
并用JS框架来访问内核层,
敬请期待...
https://harmonyos.51cto.com/#zz