Harmony多目标产物方案

原文链接:Harmony多目标产物方案

前言

Android多渠道打包简单介绍

概述

多目标产物在HarmonyOS系统中的应用主要体现在软件开发与分发方面,特别是针对不同用户群体、不同业务场景的需求进行定制化开发。多目标产物为开发者提供了更加灵活和高效的开发方式,使得应用能够更好地适应市场需求和变化。通过定制化开发,还可以更好地满足用户的个性化需求,提升用户体验。

基本概念

target:对应HAR、HSP、HAP的多目标产物。工程内的每一个模块可以定义多个target,每个Target对应一个定制的HAP、HAR包,通过配置可以实现一个模块构建出不同的HAP、HAR包。
product:对应App的多目标产物。一个HarmonyOS工程的构建产物为App包,一个工程可以定义多个product,每个product对应一个定制化应用包,通过配置可以实现一个工程构建出多个不同的应用包。

应用场景

主要应用场景:

不同用户群体:针对不同的用户群体(如国内用户与国际用户等),HarmonyOS系统支持构建不同的应用版本。这些版本在功能、界面、语言等方面可能有所不同,以满足不同用户群体的需求。
不同业务场景:在不同的业务场景中,同一个应用可能需要提供不同的功能或资源。例如,一个在线教育应用可能需要为学生提供学习资料,而为教师提供教学资料。HarmonyOS系统支持通过配置不同的Target来实现这种差异化定制。

  1. Community社区版本,免费,向个人开发者用户提供该应用绝大部分基础功能,但是不提供部分定制化限定功能及技术支持。
  2. Ultimate终极版本,收费,向个人、政企等开发者用户提供该应用全部基础功能,同时提供定制化限定功能及技术支持。

构建原理图

构建原理图

使用

多产物

如在我们的工程下的build-profile.json5下添加两个product

      {
        "name": "Community",
        "compatibleSdkVersion": "5.0.0(12)"
      },
      {
        "name": "Business",
        "compatibleSdkVersion": "5.0.0(12)",
      }

Community代表社区版、Business代表商业版。可以看到Product下多了CommunityBusiness两个,当切到CommunityModule Target提示No target to apply是什么原因呢?后面会介绍。

product_target_screen1.png

那么假如现在有个需求,当前社区版我们想跑在HarmonyOS的机器上,但是商用还是OpenHarmony上,需要出不同的包怎么实现呢?
如果当我们没有了解多产物目标方案时,最传统的可能就是注释default下的环境替换了,或者通过hvigorfile脚本编译替换,
而当了解了多产物则比较好实现,我们在不同的product中可以配置不同的编译环境,如Business改为:

      {
        "name": "Business",
        "runtimeOS": "OpenHarmony",
        "compileSdkVersion": 11,
        "compatibleSdkVersion": 11
      }

多目标

接下来我们在模块下的build-profile.json5中定义两个target,如:

    {
      "name": "free",
    },
    {
      "name": "pay"
    }

把target指定给product,工程下的build-profile.json5中当前module节点下的targets增加如下:

        {
          "name": "free",
          "applyToProducts": [
            "default",
            "Community"
          ]
        },
        {
          "name": "pay",
          "applyToProducts": [
            "default",
            "Business"
          ]
        }

此时再点击DevEco Studio中的Product,可以看到有target了:
!(https://upload-images.jianshu.io/upload_images/1834726-df477d6bea792841.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

更多实践

自定义代码资源目录及自定义参数

    {
      "name": "free",
      "runtimeOS": "HarmonyOS",
      "config": {
        "buildOption": {
          "arkOptions": {
            "buildProfileFields": {
              "buildData": "free"
            }
          }
        }
      },
      "source": {
        "sourceRoots": [
          "./src/free"
        ]
      },
      "resource": {
        "directories": [
          "./src/main/resources",
          "./src/main/resource_free"
        ]
      },
      "output": {
        "artifactName": "free"
      }
    },
    {
      "name": "pay",
      "runtimeOS": "OpenHarmony",
      "config": {
        "buildOption": {
          "arkOptions": {
            "buildProfileFields": {
              "buildData": "pay"
            }
          }
        }
      },
      "source": {
        "sourceRoots": [
          "./src/pay"
        ]
      },
      "resource": {
        "directories": [
          "./src/main/resources",
          "./src/main/resource_pay"
        ]
      },
      "output": {
        "artifactName": "pay"
      }
    }

main同级目录中创建freepay两个文件夹,在mainets下创建component文件夹,其中再创建DemoComponent组件,
resource同级目录创建reource_freeresource_pay两个资源目录,分别放入不同图片命名为product_target_screen,
DemoComponent组件代码示例如下:

@Component
export struct DemoComponent {
  build() {
    Text('The custom build data is:' + BuildProfile.buildData)
      .backgroundImage($r('app.media.product_target_screen'))
      .width('100%')
      .height('100%')
  }
}

然后再在默认的Index.ets中添加该组件,引用包如下:

import { DemoComponent } from 'demo/ets/component/DemoComponent';

此时切换不同的target查看Previewer,可以看到文本和图片显示不一样了:

product_target_screen3.png

product_target_screen4.png

hvigorfile脚本实践

通过脚本移除三方库依赖

假如我们想社区版带开源库,商业版不集成三方库,这时我们可以通过hvigor脚本在编译时移除商业版的依赖。
如模块下的hvigorfile.ts文件:

import { hapTasks, OhosHapContext, OhosPluginId } from '@ohos/hvigor-ohos-plugin';
import { getNode } from '@ohos/hvigor'

const entryNode = getNode(__filename);
// 为此节点添加一个afterNodeEvaluate hook 在hook中修改module.json5的内容并使能
entryNode.afterNodeEvaluate(node => {
  // 获取此节点使用插件的上下文对象 此时为hap插件 获取hap插件上下文对象
  const hapContext = node.getContext(OhosPluginId.OHOS_HAP_PLUGIN) as OhosHapContext;
  hapContext.targets((target: Target)=> {
    console.log(target.getCurrentProduct().getProductName())
    if (target.getCurrentProduct().getProductName() == 'Business') {
      const depOpt = hapContext.getDependenciesOpt()
      delete depOpt.utils
      hapContext.setDependenciesOpt(depOpt)
    }
  })
})

export default {
  system: hapTasks,  /* Built-in plugin of Hvigor. It cannot be modified. */
  plugins:[]         /* Custom plugin to extend the functionality of Hvigor. */
}

通过脚本重命名hap包名称

如果我们想要定制hap包名称,可以在模块下的build-profile.json5文件进行修改,对应的target节点下添加

  "output": {
        "artifactName": "freehap"
      }

但是假如我们想打出来的包不止名称不一样,还想加时间后缀呢,json配置文件中无法动态获取时间,这时我们就可以在模块下的hvigorfile.ts中添加如下方法:

function renameHapName(hapContext: OhosHapContext) {
  const buildProfile = hapContext.getBuildProfileOpt();
  const targets = buildProfile.targets
  for (const target of targets) {
    console.log('target:' + target);
    target['output']={
      "artifactName": 'demo_' + target.name + '_'+ getTime()
    }
  }
  hapContext.setBuildProfileOpt(buildProfile);
}

读取配置文件,获取output节点,对其中对artifactName字段自定义赋值,getTime()方法便可以自定义获取时间

通过脚本动态修改权限

function changePermissions(hapContext: OhosHapContext) {
  hapContext.targets((target: Target)=> {
    const targetName = target.getTargetName();
    console.log(targetName);
    if('free' == targetName){
      // 通过上下文对象获取从module.json5文件中读出来的obj对象
      const moduleJsonOpt = hapContext.getModuleJsonOpt();
      moduleJsonOpt['module']['requestPermissions'] = [
        {
          "name": "ohos.permission.INTERNET"
        }
      ]
      hapContext.setModuleJsonOpt(moduleJsonOpt)
    }
  })
}

通过脚本动态修改hap包桌面显示名称,图标

直接通过脚本修改app.json5中不生效,实际需要修改EntryAbility中的属性,先在string.json中添加EntryAbility_label_free字段,
然后再在上面动态修改权限遍历target判断targetName后添加如下配置:

      let abilities = moduleJsonOpt['module']['abilities']
      for (let abilitiesElement of abilities) {
        abilitiesElement['label'] = "$string:EntryAbility_label_free"
        abilitiesElement['icon'] = "$media:icon_free"
      }

通过脚本动态配置签名

在工程的build-profile.json5文件中,我们可以在signingConfigs节点下添加其他不同的签名配置,然后在product节点下配置对应的签名配置.
但是如果我们想在同一个product下针对不同的target生成不同签名的hap包呢,这种方式就可以通过脚本动态配置了,我们判断在编译当前target的时候,
修改product中的signingConfig为指定的签名配置名称:

function reSign(appContext: OhosAppContext, signName) {
  // 获取外部参数
  const exitParams = hvigor.getParameter().getExtParams();
  const module = exitParams['module']; 
  if (!module) return
  if (module.includes('vip') ) {
    const buildProfileOpt = appContext.getBuildProfileOpt();
    const products = buildProfileOpt.app.products
    for (const product of products) {
      product['signingConfig']= signName
    }
    appContext.setBuildProfileOpt(buildProfileOpt);
  }
}

通过脚本动态修改包名

function changePackageName(appContext: OhosAppContext, packageName) {
  const appJson5: AppJson.AppOptObj = appContext.getAppJsonOpt();
  appJson5.app.bundleName = packageName
  appContext.setAppJsonOpt(appJson5);
}

参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352

推荐阅读更多精彩内容