专栏名称: 郭霖
Android技术分享平台,每天都有优质技术文章推送。你还可以向公众号投稿,将自己总结的技术心得分享给大家。
目录
相关文章推荐
青塔  ·  开门红!C9高校,发Nature ·  4 天前  
高校人才网V  ·  四川城市职业学院2024-2025学年度招聘公告 ·  2 天前  
高校人才网V  ·  招募博士英才!四川工商学院2025年诚邀您共 ... ·  3 天前  
长江云新闻  ·  湖北下雪了!一直要下到…… ·  5 天前  
长江云新闻  ·  湖北下雪了!一直要下到…… ·  5 天前  
51好读  ›  专栏  ›  郭霖

写给Android开发者的HarmoneyOS入门指南

郭霖  · 公众号  ·  · 2024-02-28 20:53

正文



/   今日科技快讯   /

近日,抖音集团旗下北京字跳网络技术有限公司申请注册3枚“抖音游戏”商标,国际分类为广告销售、科学仪器、通讯服务,当前商标状态均为申请中。此前,北京字跳网络技术有限公司已成功注册“抖音云游戏”“嗷哩游戏”“蛋卷游戏”等商标,“抖音游戏”商标则为首次申请。

/   作者简介   /

本篇文章来自 王杰0822 的投稿,文章主要分享了 如何快速入门HarmoneyOS开发 ,相信会对大家有所帮助!同时也感谢作者贡献的精彩文章。

王杰0822 的博客 地址:
https://juejin.cn/user/4424090522225959/posts

/   前言   /

自2023华为开发者大会之后,HarmonyOS 后续版本将不再支持Android应用的说法愈演愈烈,虽然网络上有很多相关的新闻,但大多都是基于 HarmoneyOS NEXT 开发者预览版不支持 Android应用安装做的推测,目前未见华为官方正式发布说明。

也有人说目前的鸿蒙开发工具 DevEco Studio 里面都没有集成 Android SDK,但这也只能说明原生的鸿蒙应用无法安装在 Android 系统上,这个说法尚未定论。

但是 HarmonyOS 的发展是必然的,作为移动端的从业人员,自然不能停滞不前,今天我们就来走进 HarmoneyOS 的世界。

/   准备及注意   /

这篇文章是面向 Android开发者的,因此一些基本的东西我就不再赘述,相关文档可以在华为开发者联盟查看。

  • 以下内容都是基于已经搭建好 HarmonyOS 开发环境(DevEco Studio、HarmoneyOS SDK)
  • DevEco Studio应用签名是和华为账号绑定的,所以开始前需要注册一个华为账号(首次运行失败会有提示)
  • 运行 HarmoneyOS 项目需要一部鸿蒙系统的手机(目前仅Mate 50、60系列手机能正常使用,其它机型需要使用投屏工具进行操作,直接在手机上操作会卡死)

/   从Hello World开始   /

DevEco Studio


Android 开发要使用 Android Studio 开发,HarmonyOS 也提供了一个 DevEco Studio 开发工具,同样是基于 IDEA 开发的,因此功能界面和 Android Studio 大致相同,很容易上手,并且可以从 Import Sample 菜单里选择官方提供的模板库,下载到本地运行。

工具下载地址:HUAWEI DevEco Studio和SDK下载和升级 | 华为开发者联盟


创建项目


点击欢迎界面的 Create Project,创建新项目的流程也和 Android Studio 类似,这里的 Ability UI组件类似 Android 中的 Activity,用于提供UI显示及生命周期回调,这里我们简单的用默认模板创建一个 Demo 项目。


Bundle name 等同于 Android 中的 package name,项目名、保存位置可以自选,其他配置保持默认就可以了,完成项目创建。


项目结构


待项目创建完成,你就能看到如下的项目目录结构,文件看上去很多,但是我们只需要关注重点部分。


Demo/build-profile.json5 项目配置文件,等同于 Android 项目中的 settings.gradle.kts:

{
  "app": {
    "signingConfigs": [], // 签名配置
    "compileSdkVersion"9// SDK 版本配置
    "compatibleSdkVersion"9// SDK 版本配置
    "products": [
      {
        "name""default" ,
        "signingConfig""default",
      }
    ]
  },
  "modules": [ // 模块配置
    {
      "name""entry"// 模块名
      "srcPath""./entry"// 模块路径
      "targets": [
        {
          "name""default",
          "applyToProducts": [
            "default"
          ]
        }
      ]
    }
  ]
}

  • Demo/AppScope 存放全局资源及配置的路径;
  • Demo/AppScope/resources 应用全局资源路径;
  • Demo/AppScope/app.json5 应用配置,定义包名、版本、应用图标、名称等配置:

{
  "app": {
    "bundleName""com.sample.demo"// 包名
    "vendor""example"// 供应商
    "versionCode"1000000// 版本号
    "versionName""1.0.0"// 版本名
    "icon""$media:app_icon"// 应用图标,此处配置影响应用管理中显示
    "label""$string:app_name" // 应用名,此处配置影响应用管理中显示
  }
}

使用的图标


名称资源

{
  "string": [
    {
      "name""app_name",
      "value""Demo"
    }
  ]
}

   

在应用管理中显示


  • Demo/entry 应用主模块,应用入口,存放代码、资源的路径;
  • Demo/entry/src/main/module.json5 模块配置文件,类似 Android 项目中的 AndroidManifest.xml:

{
  "module": {
    "name""entry"// 当前module的名字,module打包成hap后,表示hap的名称,标签值采用字符串表示(最大长度31个字节),该名称在整个应用要唯一
    "type""entry"// 表示模块的类型,类型有三种,分别是entry、feature和har
    "srcEntry""./ets/DemoAbilityStage.ts"// 模块的入口文件路径,默认没有,需要手动创建,类似 Android 中的 Application
    "description""$string:module_desc"// 当前模块的描述信息
    "mainElement""EntryAbility"// 该标签标识hap的入口ability名称或者extension名称。只有配置为mainElement的ability或者extension才允许在服务中心露出
    "deviceTypes": [ // 该标签标识hap可以运行在哪类设备上
      "phone",
      "tablet"
    ],
    "deliveryWithInstall"true// 该模块是否随应用一起安装
    "installationFree"false// 释放支持免安装
    "pages""$profile :main_pages"// ability 中使用的 page 信息配置
    "abilities": [ // ability 配置列表,类似 Android 中的 Activity 列表
      {
        "name""EntryAbility"// 逻辑名,整个应用要唯一
        "srcEntry""./ets/entryability/EntryAbility.ts"// 入口代码路径
        "description""$string:EntryAbility_desc"// 描述信息
        "icon""$media:icon"// 图标,如果为 MainElement,必填,此处配置影响应用列表显示及任务栈显示
        "label""$string:EntryAbility_label"// 标签名,此处配置影响应用列表显示及任务栈显示
        "startWindowIcon""$media:icon"// 启动页图标
        "startWindowBackground""$color:start_window_background"// 启动页背景颜色
        "exported"true,
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ]
      }
    ]
  }
}

使用的图标:


名称资源:

{
  "string": [
    {
      "name""EntryAbility_label",
      "value""Ability1"
    }
  ]
}

在桌面显示:


在任务栈显示:


如果有多个 UIAbility,则配置了 skills 为 entity.system.home 的都会在桌面创建图标:

"skills": [
    {
        "entities": [
            "entity.system.home"
        ],
        "actions": [
            "action.system.home"
        ]
    }
]

  • Demo/entry/src/main/ets 源码文件路径;
  • Demo/entry/src/main/ets/entryability/EntryAbility.ts UI 组件,类似 Android 中的 Activity;
  • Demo/entry/src/main/resources 资源文件路径;

/   项目架构及与Android对比   /

从总体的项目架构来看,HarmonyOS 项目是比较贴近 Android 项目中 Compose + 单Activity 架构的,并且我们在 HarmonyOS 中也能找到一些与 Android 项目对应的关系:


生命周期


在 module.json5 中的 module 节点声明 srcEntry,我们也能和 Android 应用一样配置一个全局的应用程序入口,拥有类似的生命周期方法回调:

import AbilityStage from '@ohos.app.ability.AbilityStage';

export default class DemoAbilityStage extends AbilityStage {

    onCreate() {
        // 应用启动回调
    }
}

而 HarmonyOS 中的UI组件 UIAbility 也和 Android 中的 Activity 有着类似的生命周期:

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';

export default class EntryAbility extends UIAbility {
  onCreate(want, launchParam) {
    // 组件创建
    hilog.info(0x0000'testTag''%{public}s''Ability onCreate');
  }

  onDestroy() {
    // 组件销毁
    hilog.info(0x0000'testTag''%{public}s''Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage) {
    // window 创建
    // Main window is created, set main page for this ability
    hilog.info(0x0000'testTag''%{public}s''Ability onWindowStageCreate');

    // 设置布局,显示 ets/pages/Index.ets 的布局
    windowStage.loadContent('pages/Index', (err, data) => {
      if (err.code) {
        hilog.error(0x0000'testTag''Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000'testTag''Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
    });
  }

  onWindowStageDestroy() {
    // window 销毁
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000'testTag''%{public}s''Ability onWindowStageDestroy');
  }

  onForeground() {
    // 进入前台
    // Ability has brought to foreground
    hilog.info(0x0000'testTag''%{public}s''Ability onForeground');
  }

  onBackground() {
    // 进入后台
    // Ability has back to background
    hilog.info(0x0000'testTag''%{public}s''Ability onBackground');
  }
}

HarmonyOS 的 UIAbility 没有 Android 中 Activity 的 onResume onPause 生命周期回调方法,当然如果需要的话还是有方案可以实现的,需要在 onWindowStageCreate 方法里,通过 windowStage 实现:

onWindowStageCreate(windowStage: window.WindowStage) {
    windowStage.on('windowStageEvent', (event) => {
        // event 取值为枚举类型 window.WindowStageEventType
        if(event === window.WindowStageEventType.ACTIVE) {
            // 获取焦点
        } else {
            // 失去焦点
        }
    })
}

布局


HarmonyOS 使用 ArkTS 作为开发语言,并且提供 ArkTS UI 组件用于UI布局,就像上面 UIAbility 中显示的布局 ets/pages/Index.ets:

@Entry // 声明这个组件可作为页面入口,即在 UIAbility 中加载或进行页面跳转
@Component // 声明这是一个UI组件
struct Index {
  @State message: string = 'Hello World'

  build() {
    // 声明布局
    Row() { // 横向布局
      Column() { // 竖向布局
        Text(this.message) // 文本控件
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%'// 宽度铺满
    }
    .height('100%'// 高度铺满
  }
}


上面是新建项目默认生成的布局,效果是在屏幕中间显示 Hello World 文本。

界面跳转


Pages 跳转


HarmonyOS 生成的项目里,默认只有一个 UIAbility,并通过 windowStage.loadContent 来加载显示布局,因此一种多界面的方式就是编写不同的 Page,在不同的 Page 直接跳转;

首先,我们在 ets/pages 路径下新建一个 Second.ets 文件,并参照 Index.ets 声明布局,并添加按钮用于返回上一级:

import router from '@ohos.router'

@Entry
@Component
struct Second {
  @State message: string = 'Second Page'

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
        // 添加按钮
        Button("点击返回")
          .onClick(() => {
            // 按钮点击通过 router 返回上一级
            router.back()
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

然后,我们需要在 resources/base/profile/main_pages.json 文件中添加这个界面的声明:

{
  "src": [
    "pages/Index"






请到「今天看啥」查看全文