今天详细讲讲如何一键只装hap。
首先要明白-什么是hap包!
HAP
鸿蒙操作系统(HarmonyOS)中的HAP(Harmony Ability Package)是应用安装和运行的基本单元。它是一个模块化的包,包含了应用程序的代码、资源文件、第三方库以及配置信息。HAP包在鸿蒙系统中扮演着重要的角色,其主要作用包括:
应用部署:HAP包作为应用程序的基础单位,可以独立部署到鸿蒙设备上。一个完整的鸿蒙应用可能由多个HAP组成,其中至少包含一个entry类型的HAP作为应用的主入口。
模块化开发:通过将功能拆分为不同的HAP包,开发者可以更方便地进行模块化开发和维护。例如,核心业务逻辑可以放在一个HAP中,而特定的功能或扩展可以放在其他的HAP中,这样便于管理和更新。
动态特性支持:HAP包可以分为两种类型——entry和feature。Entry HAP通常包含了应用的基础功能和用户界面,作为应用的主要入口点。Feature HAP则是应用的动态特性模块,可以根据用户的需要和设备类型来选择性地安装和卸载,从而节省存储空间和优化用户体验。
跨设备能力:鸿蒙系统强调的是分布式技术,HAP的设计允许开发者构建能够适应多种不同设备的应用程序。这意味着同一个HAP可以在手机、平板、智能手表等不同形态的设备上运行,并且根据设备的能力提供相应的体验。
组件化架构:HAP内部是以Ability为基本单位组织的。Ability有两种类型:FA (Feature Ability) 和 PA (Particle Ability)。FA拥有UI界面,可以处理用户交互;PA则没有UI界面,主要用于后台服务或数据处理。这种组件化的设计使得应用更加灵活和可复用。
安全与权限管理:每个HAP都可以定义自己的权限需求,这有助于保护用户隐私和确保应用的安全性。当用户安装HAP时,系统会提示用户授予必要的权限。
版本控制与升级:由于HAP可以单独发布,因此可以实现细粒度的版本控制和升级策略。对于大型应用来说,只需要更新发生变更的HAP,而不必重新发布整个应用,从而提高效率并减少用户的下载量。
了解了hap包的基本信息后,我们要知道如何打包。
打包
打包的步骤很简单,当我们完成应用开发后,首先进行应用签名,然后进行hap编译,这时在“xxx\entry\build\default\outputs\default\"下便生成了hap包。
安装
经过我的摸索,发现可以先把本地hap包从rawFile下复制到应用沙箱路径,然后再安装。关于如何从rawFile文件夹下推送到沙箱路径,请参考我这篇帖子(https://blog.csdn.net/weixin_51416826/article/details/142830919?spm=1001.2014.3001.5501)。
当hap包复制到沙箱路径下后,使用@ohos.bundle.installer模块进行安装。如果遇到系统权限问题,请参考上一篇帖子(https://blog.csdn.net/weixin_51416826/article/details/142878360?spm=1001.2014.3001.5501)。
代码
/** * 静默安装 * 事前准备:打包、放在rawFile文件夹下 */ import installer from '@ohos.bundle.installer'; import { BusinessError } from '@ohos.base'; import common from '@ohos.app.ability.common'; import fs from '@ohos.file.fs'; import buffer from '@ohos.buffer'; let TAG = 'APPInstall-' let context = getContext(this) as common.UIAbilityContext; let filesDir = context.filesDir; let installParam: installer.InstallParam = { userId: 100, isKeepData: false, installFlag: 1, }; export class AppInstaller { // hap包沙箱路径 static hapFilePaths: Array<string> // hap包名 static hapName: string = '' // 待卸载应用名 static bundleName: string = '' /** * 从rawFile向沙箱路径复制文件 * @param name:待安装的hap包名 */ public static async FromRawToBox(name: string){ let file = filesDir + '/' + name; AppInstaller.hapFilePaths = [file] const data = fs.access(file).then((res: boolean) => { if (res) { console.info(TAG + "file exists"); } else { let sss = fs.createStreamSync(file, "w+"); //没有会创建一个空的 sss.closeSync(); //获取rawfile下hap包 let uint8Array: Uint8Array = context.resourceManager.getRawFileContentSync(name); let bf = buffer.from(uint8Array).buffer; // 打开文件 const fsOpen = fs.openSync(file, fs.OpenMode.READ_WRITE | fs.OpenMode.READ_ONLY | fs.OpenMode.CREATE | fs.OpenMode.TRUNC) // 写入文件 let destFile = fs.writeSync(fsOpen.fd, bf); console.info(TAG + 'write successfully!') // 关闭文件 fs.close(destFile) } }).catch((err: BusinessError) => { console.error("access failed with error message: " + err.message + ", error code: " + err.code); }); } /** * 安装hap包 * @param src:hap包沙箱路径 */ public static async SlientInstaller(src: string) { let hapFilePaths = [src] try { const data = await installer.getBundleInstaller().then((data: installer.BundleInstaller) => { data.install(hapFilePaths, installParam) .then((data: void) => { console.info(TAG + 'install successfully: ' + JSON.stringify(data)); }).catch((error: BusinessError) => { console.error(TAG + 'install failed:' + error.message); }); }).catch((error: BusinessError) => { console.error(TAG + 'getBundleInstaller failed. Cause: ' + error.message); }); } catch (error) { let message = (error as BusinessError).message; console.error('getBundleInstaller failed. Cause: ' + message); } } }
页面
注:虚拟机没法用,代码运行大概 也许没问题……,还望各位看官老爷多多指点。
源码已上传git,如有需要,请自取。点他?
本文链接:https://hqyman.cn/post/9493.html 非本站原创文章欢迎转载,原创文章需保留本站地址!

