当前位置:   article > 正文

鸿蒙Harmony开发:NDK接口接入ArkTS页面

鸿蒙Harmony开发:NDK接口接入ArkTS页面

占位组件

使用NDK接口构建UI界面时,需要在ArkTS页面创建用于挂载NDK接口创建组件的占位组件。占位组件类型为ContentSlot,ContentSlot能够绑定一个NodeContent对象,该对象可通过Node-API传递到Native侧挂载显示Native组件。

  • 占位组件和其他ArkTS内置组件使用方法相同。

    1. import { NodeContent } from '@kit.ArkUI';
    2. @Entry
    3. @Component
    4. struct Index {
    5. // 初始化NodeContent对象。
    6. private rootSlot = new NodeContent();
    7. @State @Watch('changeNativeFlag') showNative: boolean = false;
    8. changeNativeFlag(): void {
    9. if (this.showNative) {
    10. // 传递NodeContent对象用于Native创建组件的挂载显示
    11. nativeNode.createNativeRoot(this.rootSlot)
    12. } else {
    13. // 销毁NativeModule组件
    14. nativeNode.destroyNativeRoot()
    15. }
    16. }
    17. build() {
    18. Column() {
    19. Button(this.showNative ? "HideNativeUI" : "ShowNativeUI").onClick(() => {
    20. this.showNative = !this.showNative
    21. })
    22. Row() {
    23. // 将NodeContent和ContentSlot占位组件绑定。
    24. ContentSlot(this.rootSlot)
    25. }.layoutWeight(1)
    26. }
    27. .width('100%')
    28. .height('100%')
    29. }
    30. }
  • 占位组件可以通过相关接口在Native侧转化为挂载对象。

    1. ArkUI_NodeContentHandle contentHandle;
    2. OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
  • 挂载对象提供了相关挂载和卸载组件接口。

    1. OH_ArkUI_NodeContent_AddNode(handle_, myNativeNode);
    2. OH_ArkUI_NodeContent_RemoveNode(handle_, myNativeNode);

NDK组件模块

NDK提供的UI组件能力如组件创建、树操作、属性设置、事件注册等是通过函数指针结构体(如ArkUI_NativeNodeAPI_1)进行暴露,该函数指针结构体可以通过模块查询接口获取。

  1. ArkUI_NativeNodeAPI_1* arkUINativeNodeApi = nullptr;
  2. OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, arkUINativeNodeApi);

在获取到函数指针结构体后,可以使用该结构体内的函数实现相关UI组件操作。

  • 组件创建和销毁。

    1. auto listNode = arkUINativeNodeApi->createNode(ARKUI_NODE_LIST);
    2. arkUINativeNodeApi->disposeNode(listNode);

    获取NDK接口支持的组件范围可以通过查询ArkUI_NodeType枚举值。

  • 组件树操作。

    1. auto parent = arkUINativeNodeApi->createNode(ARKUI_NODE_STACK);
    2. auto child = arkUINativeNodeApi->createNode(ARKUI_NODE_STACK);
    3. arkUINativeNodeApi->addChild(parent, child);
    4. arkUINativeNodeApi->removeChild(parent, child);
  • 属性设置。

    1. auto stack = arkUINativeNodeApi->createNode(ARKUI_NODE_STACK);
    2. ArkUI_NumberValue value[] = {{.f32 = 100}};
    3. ArkUI_AttributeItem item = {value, 1};
    4. arkUINativeNodeApi->setAttribute(stack, NODE_WIDTH, &item);
    5. ArkUI_NumberValue value[] = {{.u32 = 0xff112233}};
    6. ArkUI_AttributeItem item = {value, 1};
    7. arkUINativeNodeApi->setAttribute(stack, NODE_BACKGROUND_COLOR, &item);

    获取NDK接口支持的属性范围可以通过查询ArkUI_NodeAttributeType枚举值。

  • 事件注册。

    1. auto stack = arkUINativeNodeApi->createNode(ARKUI_NODE_STACK);
    2. arkUINativeNodeApi->addNodeEventReceiver(stack, [](ArkUI_NodeEvent* event){
    3. // process event
    4. });
    5. arkUINativeNodeApi->registerNodeEvent(stack, NODE_ON_CLICK, 0, nullptr);

    获取NDK接口支持的事件范围可以通过查询ArkUI_NodeEventType枚举值。

示例

下面的示例展示了如何使用ContentSlot挂载Native侧的文本列表。

图1 Native文本列表

  1. 在ArkTS页面上声明用于Native页面挂载的占位组件,并在页面创建时通知Native侧创建文本列表。

    1. import nativeNode from 'libentry.so';
    2. import { NodeContent } from '@kit.ArkUI';
    3. @Entry
    4. @Component
    5. struct Index {
    6. // 初始化NodeContent对象。
    7. private rootSlot = new NodeContent();
    8. @State @Watch('changeNativeFlag') showNative: boolean = false;
    9. changeNativeFlag(): void {
    10. if (this.showNative) {
    11. // 传递NodeContent对象用于Native创建组件的挂载显示
    12. nativeNode.createNativeRoot(this.rootSlot)
    13. } else {
    14. // 销毁NativeModule组件
    15. nativeNode.destroyNativeRoot()
    16. }
    17. }
    18. build() {
    19. Column() {
    20. Button(this.showNative ? "HideNativeUI" : "ShowNativeUI").onClick(() => {
    21. this.showNative = !this.showNative
    22. })
    23. Row() {
    24. // 将NodeContent和ContentSlot占位组件绑定。
    25. ContentSlot(this.rootSlot)
    26. }.layoutWeight(1)
    27. }
    28. .width('100%')
    29. .height('100%')
    30. }
    31. }
  2. 使用Native模板创建工程,并在Native侧提供Node-API的桥接方法,实现ArkTS侧的NativeNode模块接口。

    接口声明。

    1. // entry/src/main/cpp/types/libentry/Index.d.ts
    2. export const createNativeRoot: (content: Object) => void;
    3. export const destroyNativeRoot: () => void;

    Native实现。

    1. // entry/src/main/cpp/napi_init.cpp
    2. #include "NativeEntry.h"
    3. #include "napi/native_api.h"
    4. EXTERN_C_START
    5. static napi_value Init(napi_env env, napi_value exports) {
    6. // 绑定Native侧的创建组件和销毁组件。
    7. napi_property_descriptor desc[] = {
    8. {"createNativeRoot", nullptr, NativeModule::CreateNativeRoot, nullptr, nullptr, nullptr, napi_default, nullptr},
    9. {"destroyNativeRoot", nullptr, NativeModule::DestroyNativeRoot, nullptr, nullptr, nullptr, napi_default, nullptr}};
    10. napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    11. return exports;
    12. }
    13. EXTERN_C_END
    14. static napi_module demoModule = {
    15. .nm_version = 1,
    16. .nm_flags = 0,
    17. .nm_filename = nullptr,
    18. .nm_register_func = Init,
    19. .nm_modname = "entry",
    20. .nm_priv = ((void *)0),
    21. .reserved = {0},
    22. };
    23. extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
  3. 在NativeEntry.h文件中创建Native界面。

    1. // NativeEntry.h
    2. #ifndef MYAPPLICATION_NATIVEENTRY_H
    3. #define MYAPPLICATION_NATIVEENTRY_H
    4. #include <js_native_api_types.h>
    5. namespace NativeModule {
    6. napi_value CreateNativeRoot(napi_env env, napi_callback_info info);
    7. napi_value DestroyNativeRoot(napi_env env, napi_callback_info info);
    8. // 管理Native组件的生命周期和内存。
    9. class NativeEntry {
    10. public:
    11. static NativeEntry *GetInstance() {
    12. static NativeEntry nativeEntry;
    13. return &nativeEntry;
    14. }
    15. void SetContentHandle(ArkUI_NodeContentHandle handle) {
    16. handle_ = handle;
    17. }
    18. void SetRootNode(const std::shared_ptr<ArkUIBaseNode> &baseNode) {
    19. root_ = baseNode;
    20. // 添加Native组件到NodeContent上用于挂载显示。
    21. OH_ArkUI_NodeContent_AddNode(handle_, root_->GetHandle());
    22. }
    23. void DisposeRootNode() {
    24. // 从NodeContent上卸载组件并销毁Native组件。
    25. OH_ArkUI_NodeContent_RemoveNode(handle_, root_->GetHandle());
    26. root_.reset();
    27. }
    28. private:
    29. std::shared_ptr<ArkUIBaseNode> root_;
    30. ArkUI_NodeContentHandle handle_;
    31. };
    32. } // namespace NativeModule
    33. #endif // MYAPPLICATION_NATIVEENTRY_H

    对应实现文件。

    1. // NativeEntry.cpp
    2. #include "NativeEntry.h"
    3. #include <arkui/native_node_napi.h>
    4. #include <hilog/log.h>
    5. #include <js_native_api.h>
    6. namespace NativeModule {
    7. napi_value CreateNativeRoot(napi_env env, napi_callback_info info) {
    8. size_t argc = 1;
    9. napi_value args[1] = {nullptr};
    10. napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    11. // 获取NodeContent
    12. ArkUI_NodeContentHandle contentHandle;
    13. OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
    14. NativeEntry::GetInstance()->SetContentHandle(contentHandle);
    15. // 创建文本列表
    16. auto list = CreateTextListExample();
    17. // 保持Native侧对象到管理类中,维护生命周期。
    18. NativeEntry::GetInstance()->SetRootNode(list);
    19. return nullptr;
    20. }
    21. napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) {
    22. // 从管理类中释放Native侧对象。
    23. NativeEntry::GetInstance()->DisposeRootNode();
    24. return nullptr;
    25. }
    26. } // namespace NativeModule

    使用NDK 提供的C接口需要在CMakeLists.txt 中增加libace_ndk.z.so 的引用,如下所示,其中entry为工程导出的动态库名称,如当前示例使用的是默认的名称 libentry.so。

    target_link_libraries(entry PUBLIC libace_napi.z.so libace_ndk.z.so)
  4. 由于NDK接口提供的是C接口,为了使用面向对象的方式简化编程和工程管理,这里建议使用C++进行二次封装,下面示例代码展示了示例界面中所需的列表,文本组件封装类。

    1)获取ArkUI在NDK接口的入口模块ArkUI_NativeNodeAPI_1,该结构体模块提供了一系列组件创建、树构建、属性设置和事件注册等函数指针。

    1. // NativeModule.h
    2. // 提供获取ArkUI在Native侧模块的封装接口
    3. #ifndef MYAPPLICATION_NATIVEMODULE_H
    4. #define MYAPPLICATION_NATIVEMODULE_H
    5. #include <arkui/native_node.h>
    6. #include <functional>
    7. #include <cassert>
    8. #include <arkui/native_interface.h>
    9. namespace NativeModule {
    10. class NativeModuleInstance {
    11. public:
    12. static NativeModuleInstance *GetInstance() {
    13. static NativeModuleInstance instance;
    14. return &instance;
    15. }
    16. NativeModuleInstance() {
    17. // 获取NDK接口的函数指针结构体对象,用于后续操作。
    18. OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, arkUINativeNodeApi_);
    19. assert(arkUINativeNodeApi_);
    20. }
    21. // 暴露给其他模块使用。
    22. ArkUI_NativeNodeAPI_1 *GetNativeNodeAPI() { return arkUINativeNodeApi_; }
    23. private:
    24. ArkUI_NativeNodeAPI_1 *arkUINativeNodeApi_ = nullptr;
    25. };
    26. } // namespace NativeModule
    27. #endif // MYAPPLICATION_NATIVEMODULE_H

    2)提供列表,文本组件的基类对象,用于封装通用属性和事件。

    1. // ArkUIBaseNode.h
    2. // 提供组件树操作的基类。
    3. #ifndef MYAPPLICATION_ARKUIBASENODE_H
    4. #define MYAPPLICATION_ARKUIBASENODE_H
    5. #include <arkui/native_type.h>
    6. #include <list>
    7. #include <memory>
    8. #include "NativeModule.h"
    9. namespace NativeModule {
    10. class ArkUIBaseNode {
    11. public:
    12. explicit ArkUIBaseNode(ArkUI_NodeHandle handle)
    13. : handle_(handle), nativeModule_(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()) {}
    14. virtual ~ArkUIBaseNode() {
    15. // 封装析构函数,实现子节点移除功能。
    16. if (!children_.empty()) {
    17. for (const auto& child : children_) {
    18. nativeModule_->removeChild(handle_, child->GetHandle());
    19. }
    20. children_.clear();
    21. }
    22. // 封装析构函数,统一回收节点资源。
    23. nativeModule_->disposeNode(handle_);
    24. }
    25. void AddChild(const std::shared_ptr<ArkUIBaseNode> &child) {
    26. children_.emplace_back(child);
    27. OnAddChild(child);
    28. }
    29. void RemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) {
    30. children_.remove(child);
    31. OnRemoveChild(child);
    32. }
    33. void InsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) {
    34. if (index >= children_.size()) {
    35. AddChild(child);
    36. } else {
    37. auto iter = children_.begin();
    38. std::advance(iter, index);
    39. children_.insert(iter, child);
    40. OnInsertChild(child, index);
    41. }
    42. }
    43. ArkUI_NodeHandle GetHandle() const { return handle_; }
    44. protected:
    45. // 针对父容器子类需要重载下面的函数,实现组件挂载和卸载。
    46. virtual void OnAddChild(const std::shared_ptr<ArkUIBaseNode> &child) {}
    47. virtual void OnRemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) {}
    48. virtual void OnInsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) {}
    49. ArkUI_NodeHandle handle_;
    50. ArkUI_NativeNodeAPI_1 *nativeModule_ = nullptr;
    51. private:
    52. std::list<std::shared_ptr<ArkUIBaseNode>> children_;
    53. };
    54. } // namespace NativeModule
    55. #endif // MYAPPLICATION_ARKUIBASENODE_H
    1. // ArkUINode.h
    2. // 提供通用属性和事件的封装。
    3. #ifndef MYAPPLICATION_ARKUINODE_H
    4. #define MYAPPLICATION_ARKUINODE_H
    5. #include "ArkUIBaseNode.h"
    6. #include "NativeModule.h"
    7. #include <arkui/native_node.h>
    8. #include <arkui/native_type.h>
    9. namespace NativeModule {
    10. class ArkUINode : public ArkUIBaseNode {
    11. public:
    12. explicit ArkUINode(ArkUI_NodeHandle handle) : ArkUIBaseNode(handle) {}
    13. ~ArkUINode() override {}
    14. // NDK相关通用属性调用封装
    15. void SetWidth(float width) {
    16. assert(handle_);
    17. ArkUI_NumberValue value[] = {{.f32 = width}};
    18. ArkUI_AttributeItem item = {value, 1};
    19. nativeModule_->setAttribute(handle_, NODE_WIDTH, &item);
    20. }
    21. void SetPercentWidth(float percent) {
    22. assert(handle_);
    23. ArkUI_NumberValue value[] = {{.f32 = percent}};
    24. ArkUI_AttributeItem item = {value, 1};
    25. nativeModule_->setAttribute(handle_, NODE_WIDTH_PERCENT, &item);
    26. }
    27. void SetHeight(float height) {
    28. assert(handle_);
    29. ArkUI_NumberValue value[] = {{.f32 = height}};
    30. ArkUI_AttributeItem item = {value, 1};
    31. nativeModule_->setAttribute(handle_, NODE_HEIGHT, &item);
    32. }
    33. void SetPercentHeight(float percent) {
    34. assert(handle_);
    35. ArkUI_NumberValue value[] = {{.f32 = percent}};
    36. ArkUI_AttributeItem item = {value, 1};
    37. nativeModule_->setAttribute(handle_, NODE_HEIGHT_PERCENT, &item);
    38. }
    39. void SetBackgroundColor(uint32_t color) {
    40. assert(handle_);
    41. ArkUI_NumberValue value[] = {{.u32 = color}};
    42. ArkUI_AttributeItem item = {value, 1};
    43. nativeModule_->setAttribute(handle_, NODE_BACKGROUND_COLOR, &item);
    44. }
    45. protected:
    46. // 组件树操作的实现类对接。
    47. void OnAddChild(const std::shared_ptr<ArkUIBaseNode> &child) override {
    48. nativeModule_->addChild(handle_, child->GetHandle());
    49. }
    50. void OnRemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) override {
    51. nativeModule_->removeChild(handle_, child->GetHandle());
    52. }
    53. void OnInsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) override {
    54. nativeModule_->insertChildAt(handle_, child->GetHandle(), index);
    55. }
    56. };
    57. } // namespace NativeModule
    58. #endif // MYAPPLICATION_ARKUINODE_H

    3)实现列表组件。

    1. // ArkUIListNode.h
    2. // 提供列表组件的封装。
    3. #ifndef MYAPPLICATION_ARKUILISTNODE_H
    4. #define MYAPPLICATION_ARKUILISTNODE_H
    5. #include "ArkUINode.h"
    6. namespace NativeModule {
    7. class ArkUIListNode : public ArkUINode {
    8. public:
    9. ArkUIListNode()
    10. : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST)) {} // 创建ArkUI的列表组件。
    11. ~ArkUIListNode() override {}
    12. // List组件的属性NDK接口封装。
    13. void SetScrollBarState(bool isShow) {
    14. assert(handle_);
    15. ArkUI_ScrollBarDisplayMode displayMode =
    16. isShow ? ARKUI_SCROLL_BAR_DISPLAY_MODE_ON : ARKUI_SCROLL_BAR_DISPLAY_MODE_OFF;
    17. ArkUI_NumberValue value[] = {{.i32 = displayMode}};
    18. ArkUI_AttributeItem item = {value, 1};
    19. nativeModule_->setAttribute(handle_, NODE_SCROLL_BAR_DISPLAY_MODE, &item);
    20. }
    21. };
    22. } // namespace NativeModule
    23. #endif // MYAPPLICATION_ARKUILISTNODE_H

    4)实现列表项组件。

    1. // ArkUIListItemNode.h
    2. // 提供列表项的封装类。
    3. #ifndef MYAPPLICATION_ARKUISTACKNODE_H
    4. #define MYAPPLICATION_ARKUISTACKNODE_H
    5. #include "ArkUINode.h"
    6. namespace NativeModule {
    7. class ArkUIListItemNode : public ArkUINode {
    8. public:
    9. ArkUIListItemNode()
    10. : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST_ITEM)) {}
    11. };
    12. } // namespace NativeModule
    13. #endif // MYAPPLICATION_ARKUISTACKNODE_H

    5)实现文本组件。

    1. // ArkUITextNode.h
    2. // 实现文本组件的封装类。
    3. #ifndef MYAPPLICATION_ARKUITEXTNODE_H
    4. #define MYAPPLICATION_ARKUITEXTNODE_H
    5. #include "ArkUINode.h"
    6. #include <string>
    7. namespace NativeModule {
    8. class ArkUITextNode : public ArkUINode {
    9. public:
    10. ArkUITextNode()
    11. : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_TEXT)) {}
    12. // 文本属性NDK接口封装。
    13. void SetFontSize(float fontSize) {
    14. assert(handle_);
    15. ArkUI_NumberValue value[] = {{.f32 = fontSize}};
    16. ArkUI_AttributeItem item = {value, 1};
    17. nativeModule_->setAttribute(handle_, NODE_FONT_SIZE, &item);
    18. }
    19. void SetFontColor(uint32_t color) {
    20. assert(handle_);
    21. ArkUI_NumberValue value[] = {{.u32 = color}};
    22. ArkUI_AttributeItem item = {value, 1};
    23. nativeModule_->setAttribute(handle_, NODE_FONT_COLOR, &item);
    24. }
    25. void SetTextContent(const std::string &content) {
    26. assert(handle_);
    27. ArkUI_AttributeItem item = {nullptr, 0, content.c_str()};
    28. nativeModule_->setAttribute(handle_, NODE_TEXT_CONTENT, &item);
    29. }
    30. void SetTextAlign(ArkUI_TextAlignment align) {
    31. assert(handle_);
    32. ArkUI_NumberValue value[] = {{.i32 = align}};
    33. ArkUI_AttributeItem item = {value, 1};
    34. nativeModule_->setAttribute(handle_, NODE_TEXT_ALIGN, &item);
    35. }
    36. };
    37. } // namespace NativeModule
    38. #endif // MYAPPLICATION_ARKUITEXTNODE_H
  5. 完善步骤3的CreateTextListExample函数,实现Native文本列表的创建和挂载显示。

    1. // NativeEntry.h
    2. // 自定义NDK接口入口函数。
    3. #ifndef MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H
    4. #define MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H
    5. #include "ArkUIBaseNode.h"
    6. #include "ArkUIListItemNode.h"
    7. #include "ArkUIListNode.h"
    8. #include "ArkUITextNode.h"
    9. #include <hilog/log.h>
    10. namespace NativeModule {
    11. std::shared_ptr<ArkUIBaseNode> CreateTextListExample() {
    12. // 创建组件并挂载
    13. // 1:使用智能指针创建List组件。
    14. auto list = std::make_shared<ArkUIListNode>();
    15. list->SetPercentWidth(1);
    16. list->SetPercentHeight(1);
    17. // 2:创建ListItem子组件并挂载到List上。
    18. for (int32_t i = 0; i < 30; ++i) {
    19. auto listItem = std::make_shared<ArkUIListItemNode>();
    20. auto textNode = std::make_shared<ArkUITextNode>();
    21. textNode->SetTextContent(std::to_string(i));
    22. textNode->SetFontSize(16);
    23. textNode->SetPercentWidth(1);
    24. textNode->SetHeight(100);
    25. textNode->SetBackgroundColor(0xFFfffacd);
    26. textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
    27. listItem->AddChild(textNode);
    28. list->AddChild(listItem);
    29. }
    30. return list;
    31. }
    32. } // namespace NativeModule
    33. #endif // MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H

最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

点击→【纯血版鸿蒙全套最新学习资料】希望这一份鸿蒙学习资料能够给大家带来帮助!~


 鸿蒙(HarmonyOS NEXT)最新学习路线

该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案

路线图适合人群:

IT开发人员:想要拓展职业边界
零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能。
技术提升/进阶跳槽:发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术

点击→纯血版全套鸿蒙HarmonyOS学习资料

2.视频学习资料+学习PDF文档

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、(南向驱动、嵌入式等)鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

HarmonyOS Next 最新全套视频教程

​​

 

 大厂面试必问面试题

​​

鸿蒙南向开发技术

​​

鸿蒙APP开发必备

​​

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

​​

《鸿蒙开发基础》

​​

《鸿蒙开发进阶》

《鸿蒙进阶实战》

​​


点击→纯血版全套鸿蒙HarmonyOS学习资料

总结

总的来说,华为鸿蒙不再兼容安卓,对程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,才能在这个变革的时代中立于不败之地。 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/1003269
推荐阅读
相关标签
  

闽ICP备14008679号