diff --git a/AppScope/app.json5 b/AppScope/app.json5 index 1648b84731ab5394f0079adb9d9dc9c4296a7a3f..e80fed48f0d7c17f43c75a0695c61c7a38aa875e 100644 --- a/AppScope/app.json5 +++ b/AppScope/app.json5 @@ -4,7 +4,7 @@ "vendor": "example", "versionCode": 1000000, "versionName": "1.0.0", - "icon": "$media:app_icon", + "icon": "$media:layered_image", "label": "$string:app_name" } } diff --git a/AppScope/resources/base/media/background.png b/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/AppScope/resources/base/media/background.png differ diff --git a/AppScope/resources/base/media/foreground.png b/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/AppScope/resources/base/media/foreground.png differ diff --git a/AppScope/resources/base/media/layered_image.json b/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/README.en.md b/README.en.md index 3afbb78e19fbc9cf50feaa5a01731f30b9a87be3..3ea364112b9677c6c4477e1e96b82e49cc320ee6 100644 --- a/README.en.md +++ b/README.en.md @@ -1,26 +1,55 @@ -# UIAbility and Custom Component Lifecycle +# UIAbility Lifecycle -### Introduction +## Overview -This codelab introduces UIAbility and the custom component lifecycle. +This example triggers the lifecycle of the application by the user, and then uses EventHub to listen and print the +triggered lifecycle on the homepage. -### Concepts +## Preview -- UIAbility: This component provides the UI for user interaction. It functions as the basic unit scheduled by the system and provides a window for applications to draw UIs. A UIAbility component can implement a functional module through multiple pages. Each UIAbility component instance corresponds to a task in Recents. -- Custom component lifecycle: The lifecycle callbacks of a custom component are used to notify users of the lifecycle of the component. These callbacks are private and are invoked by the development framework at a specified time at runtime. They cannot be manually invoked from applications. -- Window: This module provides a mechanism for displaying multiple application UIs and allowing the end user to interact with them on the same physical screen. +![lifecycle_en.gif](screenshots/device/lifecycle_en.gif) -### Permissions +## How to Use + +1. The user clicks on the application and prints out the triggered lifecycle on the homepage. +2. The user returns to the desktop, clicks on the application, and adds the lifecycle triggered by printing on the + homepage. + +## Project Directory + +``` +├──entry/src/main/ets/ +│ ├──entryability +│ │ └──EntryAbility.ets // Entry ability +│ ├──entrybackupability +│ │ └──EntryBackupAbility.ets // Backup and restoration +│ ├──model +│ │ └──DataModel.ets // DataModel operation +│ └──pages +│ └──Index.ets // Home page +└──entry/src/main/resources // Application resource directory +``` + +## Implementation Details + +The homepage printing lifecycle is achieved by adding eventHub listener in the ElementAbility.ts file: + +- Open the homepage for the first time, trigger the onCreate, onWindowStageCreate, and onForeground lifecycles, listen + through eventHub, and print on the page. +- Switch to the desktop, return to the application, trigger the onBackground and onForeground lifecycles, listen through + eventHub, and add printing to the page. + +## Permissions N/A -### How to Use +## Dependency -1. Search for the keyword **LifeCyclePage** on the console to view the lifecycle invoking process. +N/A -### Constraints +## Constraints 1. The sample is only supported on Huawei phones with standard systems. -2. HarmonyOS: HarmonyOS 5.0.0 Release or later. -3. DevEco Studio: DevEco Studio 5.0.0 Release or later. -4. HarmonyOS SDK: HarmonyOS 5.0.0 Release SDK or later. +2. The HarmonyOS version must be HarmonyOS 5.0.5 Release or later. +3. The DevEco Studio version must be DevEco Studio 5.0.5 Release or later. +4. The HarmonyOS SDK version must be HarmonyOS 5.0.5 Release SDK or later. \ No newline at end of file diff --git a/README.md b/README.md index d1557a22d5a541f12efbf36734b445f2cfae5746..d28dff48695f73e70761ab78864e9f492d310e37 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,51 @@ -# 实现UIAbility和自定义组件生命周期管理 +# UIAbility生命周期 -### 简介 +## 介绍 -本篇Codelab主要介绍UIAbility和自定义组件生命周期,通过日志打印可以在控制台观察生命周期的调用过程,为开发者讲解UIAbility声明周期的过程。 +本示例通过用户触发应用的生命周期,再使用EventHub监听,在首页打印已触发过的生命周期。 -### 相关概念 +## 效果预览 -- UIAbility:UIAbility组件是一种包含UI界面的应用组件,主要用于和用户交互。UIAbility组件是系统调度的基本单元,为应用提供绘制界面的窗口;一个UIAbility组件中可以通过多个页面来实现一个功能模块。每一个UIAbility组件实例,都对应于一个最近任务列表中的任务。 -- 自定义组件的生命周期:自定义组件的生命周期回调函数用于通知用户该自定义组件的生命周期,这些回调函数是私有的,在运行时由开发框架在特定的时间进行调用,不能从应用程序中手动调用这些回调函数。 -- 窗口开发指导:窗口模块用于在同一块物理屏幕上,提供多个应用界面显示、交互的机制。 +![lifecycle_zh.gif](screenshots/device/lifecycle_zh.gif) -### 相关权限 +## 使用说明 + +1. 用户点击应用,在首页打印出已触发的生命周期。 +2. 用户返回桌面,再点击应用,在首页追加打印后续触发的生命周期。 + +## 工程目录 + +``` +├──entry/src/main/ets/ +│ ├──entryability +│ │ └──EntryAbility.ets // 程序入口类 +│ ├──entrybackupability +│ │ └──EntryBackupAbility.ets // 备份恢复类 +│ ├──model +│ │ └──DataModel.ets // 数据操作类 +│ └──pages +│ └──Index.ets // 首页 +└──entry/src/main/resources // 应用资源目录 +``` + +## 具体实现 + +首页打印生命周期是通过在EntryAbility.ets文件中添加eventHub监听实现: + +- 首次打开首页,触发onCreate、onWindowStageCreate、onForeground生命周期,通过eventHub监听,在页面打印。 +- 切换到桌面,在返回应用,触发onBackground、onForeground生命周期,通过eventHub监听,在页面追加打印。 + +## 相关权限 不涉及 -### 使用说明 +## 依赖 -1. 通过日志打印可以在控制台检索关键字“[LifeCyclePage]”用来观察生命周期的调用过程。 +不涉及 -### 约束与限制 +## 约束与限制 1. 本示例仅支持标准系统上运行,支持设备:华为手机。 -2. HarmonyOS系统:HarmonyOS 5.0.0 Release及以上。 -3. DevEco Studio版本:DevEco Studio 5.0.0 Release及以上。 -4. HarmonyOS SDK版本:HarmonyOS 5.0.0 Release SDK及以上。 +2. HarmonyOS系统:HarmonyOS 5.0.5 Release及以上。 +3. DevEco Studio版本:DevEco Studio 5.0.5 Release及以上。 +4. HarmonyOS SDK版本:HarmonyOS 5.0.5 Release SDK及以上。 \ No newline at end of file diff --git a/build-profile.json5 b/build-profile.json5 index 1d12140d202702d7c73d64f1b291fe5c45a660ce..0791c1b0924ceff16b5897378b4d4f5f43a89689 100644 --- a/build-profile.json5 +++ b/build-profile.json5 @@ -1,12 +1,26 @@ { "app": { - "signingConfigs": [], "products": [ { "name": "default", "signingConfig": "default", - "compatibleSdkVersion": "5.0.0(12)", - "runtimeOS": "HarmonyOS" + "targetSdkVersion": "5.0.5(17)", + "compatibleSdkVersion": "5.0.5(17)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug" + }, + { + "name": "release" } ] }, diff --git a/code-linter.json5 b/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..073990fa45394e1f8e85d85418ee60a8953f9b99 --- /dev/null +++ b/code-linter.json5 @@ -0,0 +1,32 @@ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/entry/build-profile.json5 b/entry/build-profile.json5 index 20c75049f2d45e57d267899b6547c79fb6aa84c1..4d611879c7913fb0610c686e2399258ab3a6dad1 100644 --- a/entry/build-profile.json5 +++ b/entry/build-profile.json5 @@ -1,11 +1,25 @@ { - "apiType": 'stageMode', + "apiType": "stageMode", "buildOption": { }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], "targets": [ { - "name": "default", - "runtimeOS": "HarmonyOS" + "name": "default" }, { "name": "ohosTest", diff --git a/entry/hvigorfile.ts b/entry/hvigorfile.ts index 80e4ec5b81689f238c34614b167a0b9e9c83e8d9..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 100644 --- a/entry/hvigorfile.ts +++ b/entry/hvigorfile.ts @@ -1,2 +1,6 @@ -// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. -export { hapTasks } from '@ohos/hvigor-ohos-plugin'; +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/entry/obfuscation-rules.txt b/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/entry/oh-package.json5 b/entry/oh-package.json5 index 33d71937fca78db86a6619c308a36f1fda432553..248c3b7541a589682a250f86a6d3ecf7414d2d6a 100644 --- a/entry/oh-package.json5 +++ b/entry/oh-package.json5 @@ -1,8 +1,10 @@ { - "license": "ISC", - "devDependencies": {}, "name": "entry", - "description": "Please describe the basic information.", "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", "dependencies": {} } + diff --git a/entry/src/main/ets/entryability/EntryAbility.ets b/entry/src/main/ets/entryability/EntryAbility.ets index 285fa52e2439c93ff165315812178337ac95d875..2bafd45442deb2d29e51ba7259d4743a668db8da 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ets +++ b/entry/src/main/ets/entryability/EntryAbility.ets @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,79 +13,82 @@ * limitations under the License. */ -import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { window } from '@kit.ArkUI'; +import { ModelData } from '../model/ModelData'; -export default class EntryAbility extends UIAbility { - windowStage: window.WindowStage | undefined = undefined; - tag: string = 'EntryAbility'; - domain: number = 0x0000; - want: Want | undefined = undefined; - launchParam: AbilityConstant.LaunchParam | undefined = undefined; - windowStageEventFunc: (data: window.WindowStageEventType) => void = (data: window.WindowStageEventType): void => { - hilog.info( - this.domain, - 'Succeeded in enabling the listener for window stage event changes. Data: %{public}', - JSON.stringify(data) ?? '' - ); - } +const DOMAIN = 0x0000; +let modelDataList: ModelData[] = []; + +export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { - this.want = want; - this.launchParam = launchParam; - hilog.info(this.domain, this.tag, 'Ability is onCreate.'); + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + + // Get eventHub. + let eventhub = this.context.eventHub; + modelDataList.push(new ModelData('Ability Create', new Date().toLocaleString())); + eventhub.emit('ability', modelDataList); + + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); } - onDestroy() { - hilog.info(this.domain, this.tag, 'Ability is onDestroy.'); + onDestroy(): void { + let eventhub = this.context.eventHub; + modelDataList.push(new ModelData('Ability Destroy', new Date().toLocaleString())); + eventhub.emit('ability', modelDataList); + + this.context.eventHub.off('ability'); + + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); } - onWindowStageCreate(windowStage: window.WindowStage) { - this.windowStage = windowStage; - - // Set WindowStage event subscription (onFocus/onBlur or visible/invisible). - try { - windowStage.on('windowStageEvent', this.windowStageEventFunc); - } catch (exception) { - hilog.error( - this.domain, - 'Failed to enable the listener for window stage event changes. Cause: %{public}', - JSON.stringify(exception) ?? '' - ); - } - - // Main window is created, set main page for this ability - // Set the UI page to be loaded. - windowStage.loadContent('pages/LifeCyclePage', (err, data) => { + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability. + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + let eventhub = this.context.eventHub; + modelDataList.push(new ModelData('WindowStage Create', new Date().toLocaleString())); + eventhub.emit('ability', modelDataList); + + // Storage parameters. + AppStorage.setOrCreate("modelDataList", modelDataList); + + // Set UI loading. + windowStage.loadContent('pages/Index', (err) => { if (err.code) { - hilog.error(this.domain, 'testTag', 'Failed to load the content. Cause: %{public}s', - JSON.stringify(err) ?? ''); + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); return; } - hilog.info(this.domain, this.tag, 'Succeeded in loading the content. Data: %{public}s', - JSON.stringify(data) ?? ''); + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); }); } - onWindowStageDestroy() { - // Releasing UI Resources - // Unregisters the WindowStage event for getting/out of focus in onWindowStageDestroy() - try { - this.windowStage?.off('windowStageEvent'); - } catch (exception) { - hilog.error(this.domain, 'Failed to disable the listener for window stage event changes. Cause: %{public}s', - JSON.stringify(exception)); - } + onWindowStageDestroy(): void { + let eventhub = this.context.eventHub; + modelDataList.push(new ModelData('WindowStage Destroy', new Date().toLocaleString())); + eventhub.emit('ability', modelDataList); + + // Main window is destroyed, release UI related resources. + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); } - onForeground() { - // Ability has brought to foreground - hilog.info(this.domain, this.tag, 'Ability is onForeground.'); + onForeground(): void { + let eventhub = this.context.eventHub; + modelDataList.push(new ModelData('Ability Foreground', new Date().toLocaleString())); + eventhub.emit('ability', modelDataList); + + // Ability has brought to foreground. + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); } - onBackground() { - // Ability has back to background - hilog.info(this.domain, this.tag, 'Ability is onBackground.'); + onBackground(): void { + let eventhub = this.context.eventHub; + modelDataList.push(new ModelData('Ability Background', new Date().toLocaleString())); + eventhub.emit('ability', modelDataList); + + // Ability has back to background. + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); } -} +} \ No newline at end of file diff --git a/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/entry/src/main/ets/model/ModelData.ets b/entry/src/main/ets/model/ModelData.ets new file mode 100644 index 0000000000000000000000000000000000000000..90152b2a3340d1f942e3f087bfac9de1a4a36edf --- /dev/null +++ b/entry/src/main/ets/model/ModelData.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class ModelData { + title: string; + time: string; + + constructor(title:string, time: string) { + this.title = title; + this.time = time; + } +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1dfae97873c04a0ae9816c9c8381a771730f995 --- /dev/null +++ b/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { common } from '@kit.AbilityKit'; +import { ModelData } from '../model/ModelData'; + +@Entry +@Component +struct Index { + private context = this.getUIContext().getHostContext() as common.UIAbilityContext; + @StorageProp('modelDataList') modelDataList: ModelData[] = []; + private listScroller: ListScroller = new ListScroller(); + + aboutToAppear(): void { + this.context.eventHub.on('ability', (modelDataList: ModelData[]) => { + this.modelDataList = modelDataList; + }) + } + + @Builder + titleBuilder() { + Column() { + Text($r('app.string.home_title')) + .fontSize(30) + .lineHeight(40) + .fontWeight(700) + .width('100%') + .fontColor('rgba(0, 0, 0, 0.9)') + } + .justifyContent(FlexAlign.Center) + .margin({ + left: 16, + right: 16, + top: 64, + bottom: 8 + }) + .height(36) + } + + build() { + Navigation() { + Column() { + Row() { + Text($r('app.string.home_log')) + .width(158) + .height(45) + .fontSize(14) + .fontWeight(500) + .lineHeight(19) + .fontColor('rgba(0, 0, 0, 0.6)') + } + .width('100%') + .height(56) + .justifyContent(FlexAlign.Start) + .padding({ left: 12 }) + + List({ space: 5, scroller: this.listScroller }) { + ForEach(this.modelDataList, (modelData: ModelData) => { + ListItem() { + Row({ space: 10 }) { + Text(modelData.time + ':' + modelData.title) + .fontSize(16) + .fontWeight(400) + .lineHeight(21) + .fontColor('rgba(0, 0, 0, 0.6)') + .textOverflow({ overflow: TextOverflow.Ellipsis }) + } + .width('100%') + } + }, (modelData: ModelData, index: number) => JSON.stringify(modelData) + index) + } + .width('100%') + .layoutWeight(1) + .backgroundColor(Color.White) + .borderRadius(16) + .padding({ + left: 16, + right: 16, + top: 8, + bottom: 8 + }) + } + .height('100%') + .width('100%') + .padding(16) + } + .title({ builder: this.titleBuilder, height: 112 }) + .navBarWidth(300) + .backgroundColor('rgb(241, 243, 245)') + } +} \ No newline at end of file diff --git a/entry/src/main/module.json5 b/entry/src/main/module.json5 index 3800d8e5f16b3f5d69bfa6dc050ca574b22f5238..a1cea8b6a4560cee7bda7a2db52f310c035ab6c8 100644 --- a/entry/src/main/module.json5 +++ b/entry/src/main/module.json5 @@ -5,7 +5,9 @@ "description": "$string:module_desc", "mainElement": "EntryAbility", "deviceTypes": [ - "phone" + "phone", + "tablet", + "2in1" ], "deliveryWithInstall": true, "installationFree": false, @@ -15,9 +17,9 @@ "name": "EntryAbility", "srcEntry": "./ets/entryability/EntryAbility.ets", "description": "$string:EntryAbility_desc", - "icon": "$media:icon", + "icon": "$media:layered_image", "label": "$string:EntryAbility_label", - "startWindowIcon": "$media:icon", + "startWindowIcon": "$media:startIcon", "startWindowBackground": "$color:start_window_background", "exported": true, "skills": [ @@ -31,6 +33,20 @@ } ] } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } ] } } \ No newline at end of file diff --git a/entry/src/main/resources/base/element/float.json b/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6 --- /dev/null +++ b/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/entry/src/main/resources/base/element/string.json b/entry/src/main/resources/base/element/string.json index 4b78ca0cebe6be09dac9cadafc5d32a5ea432b14..b62d722ae1ba164a75eb97b427082533186078c5 100644 --- a/entry/src/main/resources/base/element/string.json +++ b/entry/src/main/resources/base/element/string.json @@ -10,15 +10,15 @@ }, { "name": "EntryAbility_label", - "value": "UIAbilityLifeCycle" + "value": "UIAbilityLifecycle" }, { - "name": "hello_message", - "value": "Hello World" + "name": "home_title", + "value": "LifeCircle" }, { - "name": "button_name", - "value": "jump" + "name": "home_log", + "value": "Log" } ] } \ No newline at end of file diff --git a/entry/src/main/resources/base/media/background.png b/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/entry/src/main/resources/base/media/background.png differ diff --git a/entry/src/main/resources/base/media/foreground.png b/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/entry/src/main/resources/base/media/foreground.png differ diff --git a/entry/src/main/resources/base/media/layered_image.json b/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/entry/src/main/resources/base/media/startIcon.png b/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/entry/src/main/resources/base/media/startIcon.png differ diff --git a/entry/src/main/resources/base/profile/backup_config.json b/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/entry/src/main/resources/base/profile/main_pages.json b/entry/src/main/resources/base/profile/main_pages.json index 807f94a9a0b4c525286fcabce73164930d521c3d..1898d94f58d6128ab712be2c68acc7c98e9ab9ce 100644 --- a/entry/src/main/resources/base/profile/main_pages.json +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -1,5 +1,5 @@ { "src": [ - "pages/LifeCyclePage" + "pages/Index" ] } diff --git a/entry/src/main/resources/dark/element/color.json b/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/entry/src/main/resources/en_US/element/string.json b/entry/src/main/resources/en_US/element/string.json index 4b78ca0cebe6be09dac9cadafc5d32a5ea432b14..b62d722ae1ba164a75eb97b427082533186078c5 100644 --- a/entry/src/main/resources/en_US/element/string.json +++ b/entry/src/main/resources/en_US/element/string.json @@ -10,15 +10,15 @@ }, { "name": "EntryAbility_label", - "value": "UIAbilityLifeCycle" + "value": "UIAbilityLifecycle" }, { - "name": "hello_message", - "value": "Hello World" + "name": "home_title", + "value": "LifeCircle" }, { - "name": "button_name", - "value": "jump" + "name": "home_log", + "value": "Log" } ] } \ No newline at end of file diff --git a/entry/src/main/resources/zh_CN/element/string.json b/entry/src/main/resources/zh_CN/element/string.json index b3d86b8f957487a4574d81cdc7857091e937cf24..2009b6bed64b6ec82f64fdb84b6a1fcb4e2d0494 100644 --- a/entry/src/main/resources/zh_CN/element/string.json +++ b/entry/src/main/resources/zh_CN/element/string.json @@ -6,19 +6,19 @@ }, { "name": "EntryAbility_desc", - "value": "description" + "value": "描述" }, { "name": "EntryAbility_label", - "value": "生命周期" + "value": "UIAbility生命周期" }, { - "name": "hello_message", - "value": "你好世界" + "name": "home_title", + "value": "生命周期" }, { - "name": "button_name", - "value": "跳转" + "name": "home_log", + "value": "日志" } ] } \ No newline at end of file diff --git a/entry/src/test/List.test.ets b/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..bb5b5c3731e283dd507c847560ee59bde477bbc7 --- /dev/null +++ b/entry/src/test/List.test.ets @@ -0,0 +1,5 @@ +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/entry/src/test/LocalUnit.test.ets b/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..165fc1615ee8618b4cb6a622f144a9a707eee99f --- /dev/null +++ b/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,33 @@ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/hvigor/hvigor-config.json5 b/hvigor/hvigor-config.json5 index 73bfab4e997c8d4aea53b22fdd7f10112b30987f..5bebc9755447385d82ce4138f54d991b1f85f348 100644 --- a/hvigor/hvigor-config.json5 +++ b/hvigor/hvigor-config.json5 @@ -1,17 +1,22 @@ { - "modelVersion": "5.0.0", + "modelVersion": "5.0.5", "dependencies": { }, "execution": { - // "daemon": true, /* Enable daemon compilation. Default: true */ - // "incremental": true, /* Enable incremental compilation. Default: true */ - // "parallel": true, /* Enable parallel compilation. Default: true */ - // "typeCheck": false, /* Enable typeCheck. Default: false */ + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ }, "logging": { // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ }, "debugging": { - // "stacktrace": false /* Disable stacktrace compilation. Default: false */ + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ } -} \ No newline at end of file +} diff --git a/hvigorfile.ts b/hvigorfile.ts index 6478186902c0c1ad7c966a929c7d6b7d8ae7a9f3..f3cb9f1a87a81687554a76283af8df27d8bda775 100644 --- a/hvigorfile.ts +++ b/hvigorfile.ts @@ -1,2 +1,6 @@ -// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. -export { appTasks } from '@ohos/hvigor-ohos-plugin'; \ No newline at end of file +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/oh-package.json5 b/oh-package.json5 index 3dbe199d39f06ff74caff3e9f793471aab53e59b..a8aff0c5aff22d78aa26fd19c3861f4320e951ff 100644 --- a/oh-package.json5 +++ b/oh-package.json5 @@ -1,12 +1,10 @@ { - "modelVersion": "5.0.0", - "license": "", - "devDependencies": { - }, - "author": "", - "name": "uiabilitylifecycle", + "modelVersion": "5.0.5", "description": "Please describe the basic information.", - "main": "", - "version": "1.0.0", - "dependencies": {} -} \ No newline at end of file + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.21", + "@ohos/hamock": "1.0.0" + } +} diff --git a/screenshots/device/lifecycle_en.gif b/screenshots/device/lifecycle_en.gif new file mode 100644 index 0000000000000000000000000000000000000000..757bbe51ab7448ca40f47c821c1b02c64d791b12 Binary files /dev/null and b/screenshots/device/lifecycle_en.gif differ diff --git a/screenshots/device/lifecycle_zh.gif b/screenshots/device/lifecycle_zh.gif new file mode 100644 index 0000000000000000000000000000000000000000..f9e8558461112489e1782dfcc0bf8e0553cb6f93 Binary files /dev/null and b/screenshots/device/lifecycle_zh.gif differ