跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
TypeScript大前端

鸿蒙 6.0 应用开发面试:应用程序包问题

鸿蒙 6.0 应用开发涉及应用程序包的多种核心问题。内容涵盖 HAR 与 HSP 包的区别、打包机制对体积的影响、代码安全措施、SO 库引用方法、应用卸载判断、Entry 与 Feature 模块区别、HSP 编译产物、HAR 转 HSP 及切换方法、跨模块页面跳转方案(命名路由、Navigation 组件、自定义框架)以及 HSP 共享流程。重点解析了静态共享与动态共享的加载时机差异,以及如何通过配置实现模块间的解耦与按需加载。

极客工坊发布于 2026/2/27更新于 2026/9/1194 浏览
鸿蒙 6.0 应用开发面试:应用程序包问题

鸿蒙 6.0 应用开发面试——应用程序包问题

HAR 与 HSP 包的区别是什么?

HAR(静态共享包)编译时打包:代码和资源在构建阶段被完整复制到每个依赖它的 HAP 中。启动即加载:随应用启动直接载入内存,调用时无额外开销。适用场景:少量模块引用、对加载速度敏感的场景(如基础工具库)。

HSP(动态共享包)运行时共享:仅存储一份实例,多个 HAP 在运行时动态加载同一份 HSP。按需加载:首次调用需查找、初始化,有性能损耗但避免重复拷贝。适用场景:被大量 HAP 引用的公共模块(如 UI 组件库),可显著减少包体积。

HSP 打包后,为什么会生成 HAR 包,它是否会导致 App 包大小膨胀?

HSP 编译生成的 HAR 包仅包含配置文件和接口定义,不包含代码逻辑。该 HAR 包仅用于开发阶段,不会影响 App 包的大小。

从包管理的角度,保证代码安全的措施有哪些?
  • 编译:编译时,HAR 和 HSP 支持代码混淆。
  • 打包:打包时为每个 HSP/HAP 单独签名,签名后的应用才允许安装。
  • 安装:终端设备上的应用市场用于安装和卸载应用,不支持其他安装方式。
  • 运行时:提供应用沙箱机制,这是一种以安全防护为目的的隔离机制,防止数据遭受恶意路径穿越访问。
HSP/HAR 包中如何引用外部编译的 so 库文件?
  1. 在 src/main/cpp/CMakeLists.txt 文件中链接 so 库文件。例如:target_link_libraries(entry PUBLIC libxxx)
  2. libxxx.so 库文件放入 HAR 或 HSP 的 libs/arm64-v8a 目录。设备类型不同时,需添加对应子目录。新版的 arm64 为 libs/arm64-v8a,老版的 arm64 为 libs/armeabi-v7a,x86 模拟器为 libs/x86_64。
如何判断应用可被卸载?
  1. 使用 bundleManager.getApplicationInfo 获取应用程序信息。
  2. ApplicationInfo 具有 removable 属性,可用于判断应用是否可卸载。
Entry 模块的 HAP 和 Feature 模块的 HAP 在使用和功能上的区别是什么?
  1. Entry 类型的 HAP:是应用的主模块,在 module.json5 配置文件中的 type 标签配置为'entry'类型。在同一个应用中,同一设备类型只支持一个 Entry 类型的 HAP,通常用于实现应用的入口界面、入口图标、主特性功能等。
  2. Feature 类型的 HAP:是应用的动态特性模块,在 module.json5 配置文件中的 type 标签配置为'feature'类型。一个应用程序包可以包含一个或多个 Feature 类型的 HAP,也可以不包含;Feature 类型的 HAP 通常用于实现应用的特性功能,可以配置成按需下载安装,也可以配置成随 Entry 类型的 HAP 一起下载安装。
HSP 包编译之后会生成什么文件?

HSP 包编译后会生成.hsp 文件和.har 文件。.hsp 文件用于安装,.har 文件仅暴露接口,不包含具体实现。HSP 包中导出的方法头文件位于.har 文件中,实现在.hsp 文件中。

HAR 如何转换为 HSP?

HAR 转为 HSP 主要是通过修改配置文件实现。具体步骤如下:

  1. 在 HAR 的 module.json5 中,将 type 字段的值改为'shared',并配置 deliveryWithInstall 字段为'true'。
  2. 若 HSP 需要对外声明可跳转的页面,在 module.json5 文件中添加 pages 字段,并在'resources/base'目录下创建'profile/main_pages.json'文件,配置'src'。
  3. 将 HAR 的 hvigorfile.ts 文件中的'harTasks'更改为'hspTasks'。
  4. HAR 的 build-profile.json5 文件中默认生成 consumerFiles 字段,该项字段 HAR 可配置,为默认导出的混淆加固规则,需要删除。
一个 HSP 模块如何快速切换成 HAR 模块?
  • 在 HSP 下的 module.json5 中,把"type": 'shared"修改为"type': 'har',删除"deliveryWithInstall"、"pages"字段;
  • 删除 HSP 下的 oh-package.json5 中"packageType"字段;
  • 删除 HSP 中的页面,如果要以页面的形式使用到的话,就需要改为命名路由的写法;
  • 然后再找到 HSP 下的 hvigorfile.ts 文件,将里面的 hspTasks 改为 harTasks;
  • 最后编译该模块即可。
  • 编译过程中遇到其他错误时,根据提示找到对应位置并进行修改。

    如何实现跨模块的页面跳转功能?

    在业务体系庞大或复杂的情况下,会将业务拆分成多个子业务模块,每个子业务模块为一个 HAR/HSP。在该场景下,存在从主业务入口跳转到不同子页面模块,或从一个子业务模块 A 页面跳转到另一个子业务模块 B 页面的需求。例如,从应用首页跳转到登录子业务模块页面。针对该场景,有以下三种解决方案:

    • 方案一:使用 router 的命名路由接口 router.pushNamedRoute() 跳转。
    • 方案二:使用 navigation 组件跳转。以从应用入口模块的页面 NavigationPage 跳转到 Login 子业务模块页面 LoginPage 为例。主要包含以下步骤:
      1. 组件定义:使用 @Component 装饰器定义了一个名为 LoginPage 的结构体组件。
      2. 依赖注入:通过 @Consume('pathStack') 注解,组件从其父组件中获取 NavPathStack 实例,用于页面导航。
      3. 状态声明:使用 @State 声明了一个字符串类型的状态变量 message,初始值为 'Login Page'。
      4. UI 构建:在 build 方法中,使用 NavDestination 构建导航目标,内部包含一个 Column 布局。
      5. 文本显示:在 Column 中,使用 Text 组件显示 message 变量的值,并设置字体大小为 50,字体加粗。
      6. 布局设置:设置 Column 的宽度和高度为 100%。
      7. 返回按钮处理:使用 .onBackPressed 方法注册返回按钮的事件处理函数,当返回按钮被按下时,调用 pathStack.pop() 方法返回到上一个页面,并返回 true 表示事件已被处理。
      8. 导入自定义组件:代码首先导入了 LoginPage 组件,这是从 @ohos/login 模块中导入的。
      9. 定义 NavigationPage 组件:使用 @Entry 和 @Component 装饰器定义了一个名为 NavigationPage 的组件。
      10. 提供 pathStack:使用 @Provide 装饰器定义了一个名为 pathStack 的 NavPathStack 实例,用于管理页面导航路径。
      11. 定义 pageMap 方法:使用 @Builder 装饰器定义了一个名为 pageMap 的方法,该方法根据传入的 name 参数决定返回哪个组件。如果 name 是 'loginPage',则返回 LoginPage 组件。
      12. 构建 UI:在 build 方法中,使用 Navigation 组件和 Button 组件构建了一个 UI。Navigation 组件使用 pathStack 来管理导航路径。Button 组件显示一个按钮,点击后会创建一个 NavPathInfo 对象,并使用 pathStack.pushDestination 方法导航到 loginPage。
      13. 设置导航目标:使用 .navDestination(this.pageMap) 设置导航的目标为 pageMap 方法返回的组件。
    // Import a custom component of the Login module
    import { LoginPage } from '@ohos/login';
    
    @Entry
    @Component
    struct NavigationPage {
      @Provide('pathStack') pathStack: NavPathStack = new NavPathStack();
    
      @Builder pageMap(name: string) {
        if (name === 'loginPage') {
          LoginPage()
        }
      }
    
      build() {
        Navigation(this.pathStack) {
          Button('jump to login page').onClick(() => {
            // The second parameter of NavPathInfo is a custom parameter that can be used for message transfer
            let pathInfo: NavPathInfo = new NavPathInfo('loginPage', new Object());
            this.pathStack.pushDestination(pathInfo, true);
          })
        }.navDestination(this.pageMap)
      }
    }
    

    代码逻辑走读:

    在入口模块的 oh-package.json5 文件中添加对 Login 模块的依赖项。

    {
      "...",
      "dependencies": {
        "@ohos/login": "file:../LoginModule"
      }
    }
    

    在 Login 模块的入口文件 Index.ets 中导出自定义组件。

    export { LoginPage } from './src/main/ets/pages/loginPage';
    

    在 Login 模块中开发自定义组件 LoginPage 作为路由跳转目的地,并对外导出。

    @Component
    export struct LoginPage {
      @Consume('pathStack') pathStack: NavPathStack;
      @State message: string = 'Login Page';
    
      build() {
        NavDestination() {
          Column() {
            Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)
          }.width('100%').height('100%')
        }.onBackPressed(() => {
          this.pathStack.pop();
          return true;
        })
      }
    }
    
    • 方案三:使用基于 navigation 组件的自定义路由框架跳转。方案二虽然可以实现跨模块跳转的功能,但当模块间跳转需求增多,各个模块间将存在非常复杂的依赖关系,甚至会导致多个 HAR/HSP 间循环依赖。为了解决模块间的强耦合关系,并且提升页面加载性能。

    入口模块导入 Login 模块的自定义组件,并添加到 Navigation 组件的路由表中。

    如何在应用内共享 HSP?

    如需在应用内共享 HSP,请将 HSP 共享包上传至私仓。动态共享包 HSP 不能直接发布在私仓内,需要先转换为.tgz 包。请按以下操作编译生成*.tgz 包。

    1. 构建完成后,build 目录下生成 HSP 包产物,其中.tgz 用来上传至私仓。
    2. 选中 HSP 模块的根目录,点击 Build > Make Module {libraryName},启动构建。
    3. 将编译模式设为 release。
    4. 上传到仓库,然后使用 ohpm install 命令将依赖安装到工程的 oh-package.json5 文件的 dependencies 字段中,即可查看对外共享的 HSP 方法。

    目录

    1. 鸿蒙 6.0 应用开发面试——应用程序包问题
    2. HAR 与 HSP 包的区别是什么?
    3. HSP 打包后,为什么会生成 HAR 包,它是否会导致 App 包大小膨胀?
    4. 从包管理的角度,保证代码安全的措施有哪些?
    5. HSP/HAR 包中如何引用外部编译的 so 库文件?
    6. 如何判断应用可被卸载?
    7. Entry 模块的 HAP 和 Feature 模块的 HAP 在使用和功能上的区别是什么?
    8. HSP 包编译之后会生成什么文件?
    9. HAR 如何转换为 HSP?
    10. 一个 HSP 模块如何快速切换成 HAR 模块?
    11. 如何实现跨模块的页面跳转功能?
    12. 如何在应用内共享 HSP?

    更多推荐文章

    查看全部
    • Google 秘密计划曝光:AI 或取代人类程序员敲代码
    • Z-Image-Turbo 对比 Stable Diffusion 核心优势解析
    • OpenClaw 配置飞书机器人完整指南
    • ToClaw 评测:不只是炫技 AI,更是易用桌面工具
    • C++ 四种强制类型转换运算符详解
    • OSS 实战指南:Bucket/外链/防盗链/计费与常见坑
    • Windows 11 安装 JDK 25:下载、配置环境变量及验证
    • 2026 年 3 月中旬 AI 产业动态:算力、智能体与生态
    • Java ThreadLocal 原理、使用场景及内存泄漏解析
    • 66 个机器人开源项目合集:科研、教育、工业与医疗方向精选
    • AI Agent 实战指南:框架解析与 7 个核心应用场景
    • DEIM 实时目标检测算法及 Visdrone2019 数据集实战
    • Flutter inappwebview_cookie_manager 在鸿蒙系统的适配与 Cookie 隔离实践
    • 大模型历史跃迁与商业应用展望
    • AI 编程工具选型:Copilot、Cursor、Codex 核心差异
    • Diffusion Transformer(DiT):将 U-Net 换成 ViT,应用于视频生成与机器人动作预测
    • Python 兼职变现指南:爬虫开发与数据服务实战
    • Spring Cloud Sentinel 熔断降级核心原理与实战指南
    • ESP-SparkBot 开源 AI 桌面机器人 ESP32-S3 核心方案解析
    • 双指针算法实战:移动零与复写零详解

    相关免费在线工具

    • Base64 字符串编码/解码

      将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

    • Base64 文件转换器

      将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

    • Markdown转HTML

      将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

    • HTML转Markdown

      将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

    • JSON 压缩

      通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

    • JSON美化和格式化

      将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online