diff --git a/BackGroundTasksKit/ReminderAgentManager/.gitignore b/BackGroundTasksKit/ReminderAgentManager/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/AppScope/app.json5 b/BackGroundTasksKit/ReminderAgentManager/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..60c1dfe72c61c2dc3a3bbd2c476d448afe77f1d1 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * 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. + */ + +{ + "app": { + "bundleName": "com.example.reminderagentmanager", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/BackGroundTasksKit/ReminderAgentManager/AppScope/resources/base/element/string.json b/BackGroundTasksKit/ReminderAgentManager/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..84966173d598cfa4fc7990c7f387f05cf06b5a36 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "ReminderAgentManager" + } + ] +} diff --git a/BackGroundTasksKit/ReminderAgentManager/AppScope/resources/base/media/background.png b/BackGroundTasksKit/ReminderAgentManager/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/AppScope/resources/base/media/background.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/AppScope/resources/base/media/foreground.png b/BackGroundTasksKit/ReminderAgentManager/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/AppScope/resources/base/media/foreground.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/AppScope/resources/base/media/layered_image.json b/BackGroundTasksKit/ReminderAgentManager/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/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/BackGroundTasksKit/ReminderAgentManager/README_zh.md b/BackGroundTasksKit/ReminderAgentManager/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..032bccc1d528edea633c2e7ecd0f23ef0ddce889 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/README_zh.md @@ -0,0 +1,121 @@ +# 后台代理提醒 + +### 介绍 + +本示例通过使用后台代理提醒的能力,创建闹钟、日历、计时器三种类型的定时提醒,保证应用被冻结或退出时,计时和弹出提醒的功能可以被后台系统服务代理。 + +本示例使用 [Tabs组件](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-container-tabs.md) 进行应用布局,使用 [Canvas组件](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/arkui-js/js-components-canvas-canvas.md) 绘制时钟、倒计时,使用 [后台代理提醒](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-backgroundtasks-kit/js-apis-reminderAgentManager.md) 发布后台代理提醒,使用 [振动](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-sensor-service-kit/js-apis-vibrator.md) 设置振动效果。 + +### 效果预览 + +| 闹钟 | 日历 | 计时器 | +|---------------------------------------------|------------------------------------------|---------------------------------------| +| ![](screenshots/devices/alarm_clock_zh.png) | ![](screenshots/devices/calendar_zh.png) | ![](screenshots/devices/timer_zh.png) | + +使用说明: + +1.点击**闹钟**、**日历**、**计时器**三个按钮切换不同视图。 + +2.1.点击闹钟页面右上角**+**按钮选择闹钟提醒时间添加闹钟提醒。 + +2.2.点击闹钟列表中可设置闹钟重复日期、延迟次数、延迟时长、是否震动、响铃音乐。 + +2.3.点击闹钟列表右侧开关按钮,可关闭或打开当前提醒。 + +2.4.右滑当前闹钟列表可选择删除当前提醒。 + +3.1.点击点击日历页面右上角**+**按钮选择日期提醒时间添加日期提醒。 + +3.2.点击日期列表中可设置日历提醒当天具体提醒时间、是否振动、是否响铃。 + +3.3.点击日历列表右侧开关按钮,可关闭或打开当前提醒。 + +3.4.右滑当前日历列表可选择删除当前提醒。 + +4.1.滑动计时器时间选项设置计时器时间。 + +4.2.点击**开始**按钮,开始当前计时器并设置倒计时后台提醒。 + +4.3.点击**重置**按钮,取消当前计时器提醒并重新设置计时器。 + +4.4.点击**暂停**按钮,暂停当前计时器提醒与倒计时;再次点击按钮恢复计时器提醒与计时器计时。 + +### 工程目录 +``` +entry/src/main/ets/ +|---Application +| |---MyAbilityStage.ts +|---common +| |---Constant.ets // 数据初始化 +| |---Reminder.ets // 定义数据类型 +|---MainAbility +| |---MainAbility.ts +|---pages +| |---Index.ets // 首页 +| |---alarmClock +| | |---AlarmClock.ets // 闹钟页面 +| | |---AlarmClockSetting.ets // 设置闹钟 +| | |---DrawClock.ets // 绘制闹钟 +| |---calendar +| | |---Calendar.ets // 日历页面 +| | |---CalendarSetting.ets // 设置日历 +| |---timer +| | |---SelectTime.ets // 计时器页面 +| | |---Timer.ets // 计时 +|---util +| |---AlarmClockReminder.ets // 闹钟管理 +| |---AudioPlayer.ets // 音频播放 +| |---CalendarReminder.ets // 日历管理 +| |---PreferencesDataManager.ets // 数据管理 +| |---TimeConversion.ets // 时间转换 +| |---Logger.ts // 日志打印 +``` +### 具体实现 + +* 该示例分为闹钟,日历,计时器三个模块 + * 闹钟模块 + * 使用Canvas组件绘制一个闹钟,SlotType方法获取对应的系统能力内容类型,addNotificationSlot方法添加一个NotificationSlot,ReminderRequestAlarm方法获取闹钟实例对象,用于设置提醒的时间,ReminderType方法设置提醒的类型,ActionButtonType方法设置按钮的类型,VibratorStopMode方法停止的振动。 + * 源码链接:[AlarmClockReminder.ets](entry/src/main/ets/util/AlarmClockReminder.ets),[Reminder.ets](entry/src/main/ets/common/Reminder.ets),[AlarmClock.ets](entry/src/main/ets/pages/alarmClock/AlarmClock.ets),[Constant.ets](entry/src/main/ets/common/Constant.ets) + * 接口参考:[@ohos.notificationManager](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-notification-kit/js-apis-notificationManager.md),[@ohos.reminderAgentManager](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-backgroundtasks-kit/js-apis-reminderAgentManager.md),[@ohos.vibrator](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-sensor-service-kit/js-apis-vibrator.md) + + * 日历模块 + * 使用SlotType方法获取对应的系统能力内容类型,ReminderRequestCalendar方法获取日历实例对象,用于设置提醒的时间,ReminderType方法设置提醒的类型,ActionButtonType方法设置按钮的类型,VibratorStopMode方法停止的振动。 + * 源码链接:[CalendarReminder.ets](entry/src/main/ets/util/CalendarReminder.ets),[Reminder.ets](entry/src/main/ets/common/Reminder.ets),[Calendar.ets](entry/src/main/ets/pages/calendar/Calendar.ets),[Constant.ets](entry/src/main/ets/common/Constant.ets) + * 接口参考:[@ohos.notificationManager](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-notification-kit/js-apis-notificationManager.md),[@ohos.reminderAgentManager](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-backgroundtasks-kit/js-apis-reminderAgentManager.md),[@ohos.vibrator](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-sensor-service-kit/js-apis-vibrator.md) + + * 计时器模块 + * 使用SlotType方法获取对应的系统能力内容类型,addNotificationSlot方法添加一个NotificationSlot,ReminderRequestTimer方法获取倒计时实例对象,用于设置提醒的时间,ReminderType方法设置提醒的类型,ActionButtonType方法设置按钮的类型,VibratorStopMode方法停止的振动。 + * 源码链接:[Timer.ets](entry/src/main/ets/pages/timer/Timer.ets),[Reminder.ets](entry/src/main/ets/common/Reminder.ets),[Constant.ets](entry/src/main/ets/common/Constant.ets) + * 接口参考:[@ohos.notificationManager](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-notification-kit/js-apis-notificationManager.md),[@ohos.reminderAgentManager](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-backgroundtasks-kit/js-apis-reminderAgentManager.md),[@ohos.vibrator](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-sensor-service-kit/js-apis-vibrator.md) + +### 相关权限 + +1.允许该应用使用后台代理提醒 [ohos.permission.PUBLISH_AGENT_REMINDER](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissionpublish_agent_reminder) + +2.允许应用控制马达振动 [ohos.permission.VIBRATE](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissionvibrate) + +3.允许应用读取用户外部存储中的媒体文件信息 [ohos.permission.READ_MEDIA](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissionread_media) + +### 依赖 + +不涉及。 + +### 约束与限制 + +1.本示例仅支持标准系统上运行,支持设备:RK3568。 + +2.本示例已适配API version 20版本SDK,版本号:6.0.0(20)。 + +3.本示例需要使用DevEco Studio 6.0.0 Release (Build Version: 6.0.0.868, built on October 22, 2025)及以上版本才可编译运行。 + +### 下载 + +如需单独下载本工程,执行如下命令: +``` +git init +git config core.sparsecheckout true +echo code/BasicFeature/TaskManagement/ReminderAgentManager/ > .git/info/sparse-checkout +git remote add origin https://gitcode.com/openharmony/applications_app_samples.git +git pull origin master + +``` \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/build-profile.json5 b/BackGroundTasksKit/ReminderAgentManager/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..6c383a087d7197af1b819b4ab709a548b067bb0b --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/build-profile.json5 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022-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. + */ + +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "targetSdkVersion": "6.0.0(20)", + "compatibleSdkVersion": "6.0.0(20)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/code-linter.json5 b/BackGroundTasksKit/ReminderAgentManager/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ed05653cca31b61d64cf6471529eaf50d4f70709 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/code-linter.json5 @@ -0,0 +1,47 @@ +/* + * 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. + */ + +{ + "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/BackGroundTasksKit/ReminderAgentManager/entry/.gitignore b/BackGroundTasksKit/ReminderAgentManager/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/build-profile.json5 b/BackGroundTasksKit/ReminderAgentManager/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5442fd9006e6407d41b8903182feb116b60a9c10 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/build-profile.json5 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022-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. + */ + +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/hvigorfile.ts b/BackGroundTasksKit/ReminderAgentManager/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..cfa8a00f74f409d9647f55cdf270ab6aec69fe41 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * 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 { 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. */ +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/obfuscation-rules.txt b/BackGroundTasksKit/ReminderAgentManager/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/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/BackGroundTasksKit/ReminderAgentManager/entry/oh-package.json5 b/BackGroundTasksKit/ReminderAgentManager/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..2e7a2670d6a76ffb01ec132c2cf707efcc7455c9 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* +* Copyright (C) 2023-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. +*/ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/common/Constant.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/common/Constant.ets new file mode 100644 index 0000000000000000000000000000000000000000..b4989ee072bfd17b962c4d013657f74562b57c97 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/common/Constant.ets @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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 default class Constant { + static readonly PROMPT_DURATION: number = 300 + static readonly REMINDER_DURATION: number = 30 + static readonly FONT_WEIGHT: number = 400 + static readonly VIBRATOR_DURATION: number = 3000 + static readonly SECONDS_MILLISECONDS: number = 1000 + static readonly ANGLE: number = 360 + static readonly HOUR_SECONDS: number = 3600 + static readonly TIME_COUNTDOWN: number = 59 + static readonly MINUTES_SECONDS: number = 60 + static readonly HORIZONTAL_POINTER_HEIGHT: number = 310 + static readonly HORIZONTAL_LINE_LENGTH: number = 345 + static readonly HORIZONTAL_CLOCK_DIAL_HEIGHT: number = 212 + static readonly HORIZONTAL_CLOCK_DIAL_WIDTH: number = 212 + static readonly HORIZONTAL_CLOCK_HEIGHT: number = 188 + static readonly HORIZONTAL_CLOCK_WIDTH: number = 188 + static readonly HORIZONTAL_CENTER_Y: number = 99 + static readonly VERTICAL_POINTER_HEIGHT: number = 375 + static readonly VERTICAL_LINE_LENGTH: number = 410 + static readonly VERTICAL_CLOCK_DIAL_HEIGHT: number = 280 + static readonly VERTICAL_CLOCK_DIAL_WIDTH: number = 280 + static readonly VERTICAL_CLOCK_HEIGHT: number = 250 + static readonly VERTICAL_CLOCK_WIDTH: number = 250 + static readonly VERTICAL_CENTER_Y: number = 125 + static readonly VERTICAL_PICKER_HEIGHT: number = 128 +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/common/Reminder.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/common/Reminder.ets new file mode 100644 index 0000000000000000000000000000000000000000..44c527f87e38f80792a7ae918728546ac9af2cae --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/common/Reminder.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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 reminderAgent from '@ohos.reminderAgentManager'; + +export interface Reminder { + audioSrc: string, + audioTimeouts: number, + isStart: boolean, + isVibrator: boolean, + reminderName: string, + reminderId: number, + vibratorTimeouts: number, + reminderRequestAlarm?: reminderAgent.ReminderRequestAlarm, + reminderRequestCalendar?: reminderAgent.ReminderRequestCalendar, +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/entryability/EntryAbility.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..b9704d4e13f8e7ca8206cef85b27330fbbe588ea --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,74 @@ +/* + * 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 { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; +import Logger from '../util/Logger' +import common from '@ohos.app.ability.common'; +import notification from '@ohos.notificationManager' + +export let mContext: common.UIAbilityContext | null = null; +const TAG: string = 'MainAbility'; +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + mContext = this.context; + notification.requestEnableNotification(mContext).then(() => { + Logger.info(TAG, `requestEnableNotification success`); + }).catch((err: Error) => { + Logger.error(TAG, `requestEnableNotification fail: ${JSON.stringify(err)}`); + }); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/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/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/Index.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f0897686c12fbabe48667a81c909bce3d340e53 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022-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 { AlarmClock } from './alarmClock/AlarmClock' +import { ReminderCalendar } from './calendar/Calendar' +import { Timer } from './timer/Timer' + +interface categoryType { + tabBarName: Resource, + selectedImage: Resource, + unSelectImage: Resource +} + +const CATEGORY: Array = [ + { + tabBarName: $r('app.string.alarm_clock'), + selectedImage: $r('app.media.ic_public_clock_filled'), + unSelectImage: $r('app.media.ic_public_clock') + }, + { + tabBarName: $r('app.string.calendar'), + selectedImage: $r('app.media.ic_public_calendar_filled'), + unSelectImage: $r('app.media.ic_public_calendar') + }, + { + tabBarName: $r('app.string.timer'), + selectedImage: $r('app.media.ic_public_timer_filled'), + unSelectImage: $r('app.media.ic_public_timer') + } +] + +@Entry +@Component +struct Index { + @State tabsIndex: number = 0 + + build() { + Column() { + Tabs({ barPosition: BarPosition.End }) { + ForEach(CATEGORY, (item: categoryType, index) => { + TabContent() { + if (index === 0) { + AlarmClock({ title: item.tabBarName }) + } else if (index === 1) { + ReminderCalendar({ title: item.tabBarName }) + } else { + Timer({ title: item.tabBarName }) + } + } + .tabBar(this.TabBarBuilder(index, item.selectedImage, item.unSelectImage, item.tabBarName)) + }) + } + .barHeight(56) + .barWidth('100%') + .vertical(false) + .scrollable(false) + .backgroundColor($r('app.color.background_shallow_grey')) + .onChange((index: number) => { + this.tabsIndex = index + }) + } + .width('100%') + .height('100%') + } + + @Builder TabBarBuilder(index: number, selectedImage: Resource, unSelectedImage: Resource, tabBarName: Resource) { + Column() { + Image(this.tabsIndex === index ? selectedImage : unSelectedImage) + .width(28) + .height(28) + .margin({ bottom: 4 }) + + Text(tabBarName) + .fontSize(12) + .fontFamily('HarmonyHeiTi-Medium') + .fontColor(this.tabsIndex === index ? $r('app.color.tab_bar_select') : $r('app.color.tab_bar_unselect')) + } + .width('100%') + .padding({ top: 6, bottom: 6 }) + .alignItems(HorizontalAlign.Center) + } +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/alarmClock/AlarmClock.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/alarmClock/AlarmClock.ets new file mode 100644 index 0000000000000000000000000000000000000000..9dab844b81d4a55ba67efd67bb36b967d4b15678 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/alarmClock/AlarmClock.ets @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2022 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 AlarmClockReminder from '../../util/AlarmClockReminder' +import { AlarmClockSetting } from './AlarmClockSetting' +import { DrawClock } from './DrawClock' +import PreferencesDataManager from '../../util/PreferencesDataManager' + +const TAG: string = 'AlarmClock'; + +@Component +export struct AlarmClock { + @State isEdit: boolean = false + @State canvasWidth: number = 0 + @State canvasRadius: number = 0 + @State alarmClockName: string[] = [] + @State selectAlarmClockIndex: number = 0 + private title: Resource | undefined = undefined; + private alarmClockSetting: CustomDialogController = new CustomDialogController({ + builder: AlarmClockSetting({ selectAlarmClockIndex: this.selectAlarmClockIndex }) + }) + + build() { + Column() { + Row() { + Text(this.title) + .fontSize(24) + .margin({ left: 8 }) + Blank() + Image($r('app.media.ic_public_add')) + .width(30) + .height(30) + .margin({ right: 8 }) + .id('addClock') + .onClick(() => { + TimePickerDialog.show({ + selected: new Date, + useMilitaryTime: true, + onAccept: async (value: TimePickerResult) => { + await AlarmClockReminder.setAlarmReminder(value) + if (AlarmClockReminder.alarmClockReminders.length !== 0) { + for (let i = 0; i < AlarmClockReminder.alarmClockReminders.length; i++) { + this.alarmClockName[i] = AlarmClockReminder.alarmClockReminders[i].reminderName + } + } else { + this.alarmClockName = [] + } + } + }) + }) + } + .height(56) + .padding(8) + .width('100%') + + Row() { + DrawClock({ canvasWidth: $canvasWidth, radius: $canvasRadius }) + .margin(8) + } + .justifyContent(FlexAlign.Center) + .width('100%') + + List({ space: 8 }) { + ForEach(this.alarmClockName, (item: string, index) => { + ListItem() { + Row() { + Text(item) + .fontSize(24) + Blank() + if (AlarmClockReminder.alarmClockReminders[index]) { + Toggle({ type: ToggleType.Switch, isOn: AlarmClockReminder.alarmClockReminders[index].isStart }) + .margin({ left: 8 }) + .id(`clockSwitch${index}`) + .onChange(async (isOn: boolean) => { + await AlarmClockReminder.setToggle(isOn, index); + }) + } + } + .width('100%') + .borderRadius(24) + .backgroundColor(Color.White) + .padding({ left: 12, right: 12, top: 8, bottom: 8 }) + } + .padding({ left: 12, right: 12 }) + .id(`clock${this.selectAlarmClockIndex}`) + .gesture( + GestureGroup(GestureMode.Parallel, + SwipeGesture({ direction: SwipeDirection.Horizontal }) + .onAction((event: GestureEvent) => { + this.isEdit = !this.isEdit; + this.deleteItem(index); + }), + TapGesture() + .onAction(async (event: GestureEvent) => { + this.selectAlarmClockIndex = index; + AlarmClockReminder.alarmClockReminders[index].isStart = false; + await AlarmClockReminder.openDialog(this.alarmClockSetting, index); + }) + ) + ) + }) + } + .layoutWeight(1) + + Blank() + Divider() + .height(0.75) + .width('100%') + .alignSelf(ItemAlign.Baseline) + .color($r('app.color.tab_bar_divider')) + } + .width('100%') + .height('100%') + .onAreaChange((oldValue: Area, newValue: Area) => { + let size = newValue.width < newValue.height ? newValue.width : Number(newValue.height) * 0.8 + this.canvasWidth = Number(size) * 0.5 + this.canvasRadius = this.canvasWidth / 2 + }) + } + + deleteItem(index: number): boolean { + AlarmClockReminder.deleteAlarmReminder(index) + .then(() => { + this.alarmClockName = [] + if (AlarmClockReminder.alarmClockReminders.length !== 0) { + for (let i = 0; + i < AlarmClockReminder.alarmClockReminders.length; + i++) { + this.alarmClockName[i] = AlarmClockReminder.alarmClockReminders[i].reminderName + } + } + this.isEdit = false + } + ) + return true + } + + aboutToAppear() { + PreferencesDataManager.getData('alarmClock').then((result) => { + if (result !== undefined) { + AlarmClockReminder.alarmClockReminders = result + for (let i = 0; i < AlarmClockReminder.alarmClockReminders.length; i++) { + this.alarmClockName[i] = AlarmClockReminder.alarmClockReminders[i].reminderName + } + } + }) + } +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/alarmClock/AlarmClockSetting.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/alarmClock/AlarmClockSetting.ets new file mode 100644 index 0000000000000000000000000000000000000000..2c8777e0d249d53869661baef55d6ea1e124d33e --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/alarmClock/AlarmClockSetting.ets @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2022 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 AlarmClockReminder from '../../util/AlarmClockReminder' +import PreferencesDataManager from '../../util/PreferencesDataManager' +import logger from '../../util/Logger'; + +interface daysType { + name: Resource, + value: number, + isSelect: boolean +} + +interface musicsType { + value: string, + src: string +} + +@CustomDialog +export struct AlarmClockSetting { + @State snoozeTimes: number = 0 + @State timeInterval: number = 0 + @State selectName: string = 'Demo' + @State days: Array = + [ + { name: $r('app.string.alarm_clock_one'), value: 1, isSelect: false }, + { name: $r('app.string.alarm_clock_two'), value: 2, isSelect: false }, + { name: $r('app.string.alarm_clock_three'), value: 3, isSelect: false }, + { name: $r('app.string.alarm_clock_four'), value: 4, isSelect: false }, + { name: $r('app.string.alarm_clock_five'), value: 5, isSelect: false }, + { name: $r('app.string.alarm_clock_six'), value: 6, isSelect: false }, + { name: $r('app.string.alarm_clock_seven'), value: 7, isSelect: false } + ] + private selectAlarmClockIndex: number = 0 + private controller: CustomDialogController + private musics: Array = [{ value: 'Demo', src: '/system/etc/demo.wav' }, + { value: 'Dynamic', src: '/system/etc/dynamic.wav' }]; + + build() { + Column() { + Row() { + Text($r('app.string.alarm_clock_remind_day')) + .fontSize(20) + Blank() + ForEach(this.days, (item: daysType, index) => { + Column() { + Text(item.name) + .margin(2) + .fontSize(18) + Checkbox({ name: item.name.toString(), group: 'days' }) + .select(item.isSelect) + .selectedColor(0x39a2db) + .id(`day${this.selectAlarmClockIndex}${index}`) + .onChange((value: boolean) => { + item.isSelect = value + }) + } + .layoutWeight(1) + }) + } + .width('100%') + .padding({ left: 8, right: 8, top: 8 }) + + Row() { + Text($r('app.string.alarm_clock_snooze')) + .fontSize(20) + Blank() + Counter() { + Text(`${JSON.stringify(this.snoozeTimes)}`) + .id('timeCounter') + } + .id(`intervalTime${this.selectAlarmClockIndex}`) + .onInc(() => { + this.snoozeTimes++ + }) + .onDec(() => { + this.snoozeTimes <= 0 ? 0 : this.snoozeTimes-- + }) + } + .width('100%') + .margin({ top: 4, bottom: 4 }) + .padding({ left: 8, right: 8 }) + + Row() { + Text($r('app.string.alarm_clock_interval')) + .fontSize(20) + Blank() + Counter() { + Text(`${JSON.stringify(this.timeInterval)}`) + .id('durationCounter') + } + .id(`intervalDuration${this.selectAlarmClockIndex}`) + .onInc(() => { + this.timeInterval++ + }) + .onDec(() => { + this.timeInterval <= 0 ? 0 : this.timeInterval-- + }) + } + .width('100%') + .margin({ top: 4, bottom: 4 }) + .padding({ left: 8, right: 8 }) + + Row() { + Text($r('app.string.is_vibrator')) + .fontSize(20) + Blank() + Toggle({ + type: ToggleType.Switch, + isOn: AlarmClockReminder.alarmClockReminders[this.selectAlarmClockIndex].isVibrator + }) + .id(`vibrationSwitch${this.selectAlarmClockIndex}`) + .margin({ left: 8 }) + .onChange((isOn: boolean) => { + AlarmClockReminder.alarmClockReminders[this.selectAlarmClockIndex].isVibrator = isOn + }) + } + .width('100%') + .padding({ left: 8, right: 8 }) + + Row() { + Text($r('app.string.setting_ringtone')) + .fontSize(20) + Blank() + Select(this.musics) + .selected(0) + .id(`selectMusic${this.selectAlarmClockIndex}`) + .value(this.selectName) + .padding({ left: 20, right: 20 }) + .font({ size: 20 }) + .optionFont({ size: 20 }) + .selectedOptionFont({ size: 20 }) + .onSelect((index: number, value: string) => { + this.selectName = value + AlarmClockReminder.alarmClockReminders[this.selectAlarmClockIndex].audioSrc = this.musics[index].src + }) + } + .padding(8) + .width('100%') + + Row() { + Button($r('app.string.cancel')) + .fontSize(24) + .margin({ right: 12 }) + .onClick(() => { + this.controller.close() + }) + Button($r('app.string.confirm')) + .fontSize(24) + .margin({ left: 12 }) + .onClick(async () => { + let selectDays: number[] = [] + for (let i = 0; i < this.days.length; i++) { + if (this.days[i].isSelect) { + selectDays.push(this.days[i].value) + } + } + AlarmClockReminder.alarmClockReminders[this.selectAlarmClockIndex].reminderRequestAlarm!.snoozeTimes = this.snoozeTimes; + AlarmClockReminder.alarmClockReminders[this.selectAlarmClockIndex].reminderRequestAlarm!.timeInterval = this.timeInterval; + AlarmClockReminder.alarmClockReminders[this.selectAlarmClockIndex].reminderRequestAlarm!.daysOfWeek = selectDays; + await PreferencesDataManager.putData('alarmClock', AlarmClockReminder.alarmClockReminders) + this.controller.close() + }) + } + .padding(8) + .width('100%') + .margin({ top: 8, bottom: 8 }) + .justifyContent(FlexAlign.Center) + } + } + + aboutToAppear() { + // Read the data of the settings and display it + this.snoozeTimes = AlarmClockReminder.alarmClockReminders[this.selectAlarmClockIndex].reminderRequestAlarm!.snoozeTimes!; + this.timeInterval = AlarmClockReminder.alarmClockReminders[this.selectAlarmClockIndex].reminderRequestAlarm!.timeInterval!; + this.selectName = AlarmClockReminder.alarmClockReminders[this.selectAlarmClockIndex].audioSrc === '/system/etc/demo.wav' ? 'Demo' : 'Dynamic'; + let selectDays = AlarmClockReminder.alarmClockReminders[this.selectAlarmClockIndex].reminderRequestAlarm!.daysOfWeek; + if(selectDays !== undefined){ + for (let i = 0; i < this.days.length; i++) { + for (let j = 0; j < selectDays.length; j++) { + if (this.days[i].value === selectDays[j]) { + this.days[i].isSelect = true; + break; + } + } + } + }else{ + logger.error('selectDays is undefined!'); + } + } +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/alarmClock/DrawClock.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/alarmClock/DrawClock.ets new file mode 100644 index 0000000000000000000000000000000000000000..60b3a629dbf12ee470c32b3277e0d952cbb1d4a7 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/alarmClock/DrawClock.ets @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2022 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 Constant from '../../common/Constant' + +const HOURS: Array = ['3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '1', '2'] +const TIME_TEXT_HEIGHT: number = 150 // The underside of the dial needs to be drawn, and the canvas height is width plus 150 + +@Component +export struct DrawClock { + @Link radius: number + @Link canvasWidth: number + private settings: RenderingContextSettings = new RenderingContextSettings(true) + private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings) + private intervalId: number = 0 + updateTime = () => { + this.context.clearRect(0, 0, this.canvasWidth, this.canvasWidth + TIME_TEXT_HEIGHT) + let nowTime = new Date() + let hour = nowTime.getHours() + let minute = nowTime.getMinutes() + let second = nowTime.getSeconds() + let time = `${this.fillTime(hour)}:${this.fillTime(minute)}:${this.fillTime(second)}` + this.drawBackground() + this.drawHour(hour, minute) + this.drawMinute(minute) + this.drawSecond(second) + this.drawDot() + this.drawTime(time) + this.context.translate(-this.radius, -this.radius) + } + + build() { + Canvas(this.context) + .width(this.canvasWidth) + .height(this.canvasWidth + TIME_TEXT_HEIGHT) + .onReady(() => { + this.updateTime() + this.intervalId = setInterval(this.updateTime, Constant.SECONDS_MILLISECONDS) + }) + } + + fillTime(time: number) { + return time < 10 ? `0${time}` : `${time}` + } + + drawBackground() { + this.context.save() + // Draw the background + let grad = this.context.createRadialGradient(this.radius, this.radius, this.radius - 35, this.radius, + this.radius, this.radius) + grad.addColorStop(0.0, '#F1F3F5') + grad.addColorStop(0.9, '#EEEEEE') + grad.addColorStop(1.0, '#F1F3F5') + this.context.fillStyle = grad + this.context.fillRect(0, 0, this.canvasWidth, this.canvasWidth) + // Draw an outer circle + this.context.translate(this.radius, this.radius) + this.context.lineWidth = 6 + this.context.beginPath() + this.context.strokeStyle = '#FFFFFF' + this.context.arc(0, 0, this.radius - 6, 0, 2 * Math.PI, false) + this.context.stroke() + // Draw time text + this.context.font = '25px' + this.context.textAlign = 'center' + this.context.textBaseline = 'middle' + this.context.fillStyle = '#000000' + HOURS.forEach((num, index) => { + this.context.save() + let rad = 2 * Math.PI / 12 * index + let x = Math.cos(rad) * (this.radius - 38) + let y = Math.sin(rad) * (this.radius - 38) + this.context.fillText(num, x, y) + }) + // Draw the scale + for (let i = 0; i < 60; i++) { + let rad = 2 * Math.PI / 60 * i + let x = Math.cos(rad) * (this.radius - 12) + let y = Math.sin(rad) * (this.radius - 12) + this.context.beginPath() + this.context.moveTo(x, y) + if (i % 5 == 0) { + let x1 = Math.cos(rad) * (this.radius - 20) + let y1 = Math.sin(rad) * (this.radius - 20) + this.context.strokeStyle = '#000000' + this.context.lineWidth = 4 + this.context.lineTo(x1, y1) + } else { + let x1 = Math.cos(rad) * (this.radius - 18) + let y1 = Math.sin(rad) * (this.radius - 18) + this.context.strokeStyle = '#CCCCCC' + this.context.lineWidth = 3 + this.context.lineTo(x1, y1) + } + this.context.stroke() + } + } + + // Draw the hour hand + drawHour(hour: number, minute: number) { + this.context.save() + this.context.beginPath() + this.context.lineWidth = 8 + this.context.lineCap = 'round' + let rad = 2 * Math.PI / 12 * hour + let mrad = 2 * Math.PI / 12 / 60 * minute + this.context.rotate(rad + mrad) + this.context.moveTo(0, 10) + this.context.strokeStyle = '#000000' + this.context.lineTo(0, -this.radius / 2) + this.context.stroke() + this.context.restore() + } + + // Draw the minute hand + drawMinute(minute: number) { + this.context.save() + this.context.beginPath() + this.context.lineWidth = 6 + this.context.lineCap = 'round' + let rad = 2 * Math.PI / 60 * minute + this.context.rotate(rad) + this.context.moveTo(0, 10) + this.context.strokeStyle = '#000000' + this.context.lineTo(0, -this.radius + 40) + this.context.stroke() + this.context.restore() + } + + // Draw the second hand + drawSecond(second: number) { + this.context.save() + this.context.beginPath() + this.context.lineWidth = 4 + this.context.lineCap = 'round' + let rad = 2 * Math.PI / 60 * second + this.context.rotate(rad) + this.context.moveTo(0, 10) + this.context.strokeStyle = '#0055FF' + this.context.lineTo(0, -this.radius + 18) + this.context.stroke() + this.context.restore() + } + + // Draw the center point + drawDot() { + this.context.save() + this.context.beginPath() + this.context.fillStyle = '#0055FF' + this.context.arc(0, 0, 4, 0, 2 * Math.PI, false) + this.context.fill() + this.context.restore() + } + + // Draw the time text below the dial + drawTime(time: string) { + this.context.save() + this.context.beginPath() + this.context.font = '60px' + this.context.textAlign = 'center' + this.context.textBaseline = 'middle' + this.context.fillStyle = '#000000' + this.context.fillText(time, 0, this.radius + 80) + this.context.restore() + } +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/calendar/Calendar.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/calendar/Calendar.ets new file mode 100644 index 0000000000000000000000000000000000000000..a19b54fd310b3e5e4f09844aa51e12e84454eaf9 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/calendar/Calendar.ets @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2022-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 { CalendarSetting } from './CalendarSetting' +import CalendarReminder from '../../util/CalendarReminder' +import PreferencesDataManager from '../../util/PreferencesDataManager' + +@Component +export struct ReminderCalendar { + @State isEdit: boolean = false + @State selectCalendar: number = 0 + @State calendarNames: string[] = [] + private title: Resource | undefined = undefined; + private calendarSetting: CustomDialogController = new CustomDialogController({ + builder: CalendarSetting({ selectIndex: this.selectCalendar }) + }) + + build() { + Column() { + Row() { + Text(this.title) + .fontSize(24) + .margin({ left: 8 }) + Blank() + Image($r('app.media.ic_public_add')) + .width(24) + .height(24) + .margin({ right: 8 }) + .id('addCalendar') + .onClick(() => { + DatePickerDialog.show({ + start: new Date(), + end: new Date('2100-12-31'), + showTime: true, + useMilitaryTime: true, + onDateAccept: async (value: Date) => { + await CalendarReminder.setCalendar(value) + if (CalendarReminder.calendarReminders.length !== 0) { + for (let i = 0; i < CalendarReminder.calendarReminders.length; i++) { + this.calendarNames[i] = CalendarReminder.calendarReminders[i].reminderName + } + } else { + this.calendarNames = [] + } + } + }) + }) + } + .height(56) + .padding(8) + .width('100%') + + List({ space: 8 }) { + ForEach(this.calendarNames, (item: string, index) => { + ListItem() { + Row() { + Text(item) + .fontSize(24) + Blank() + if(CalendarReminder.calendarReminders[index]){ + Toggle({ type: ToggleType.Switch, isOn: CalendarReminder.calendarReminders[index].isStart }) + .margin({ left: 8 }) + .id(`calendarSwitch${index}`) + .onChange(async (isOn: boolean) => { + await CalendarReminder.setToggle(isOn, index); + }) + } + } + .width('100%') + .borderRadius(24) + .backgroundColor(Color.White) + .padding({ left: 12, right: 12, top: 8, bottom: 8 }) + } + .editable(this.isEdit) + .id(`calendar${index}`) + .padding({ left: 12, right: 12 }) + .gesture( + GestureGroup(GestureMode.Parallel, + SwipeGesture({ direction: SwipeDirection.Horizontal }) + .onAction((event: GestureEvent) => { + this.isEdit = !this.isEdit; + this.deleteItem(index); + }), + TapGesture() + .onAction(async (event: GestureEvent) => { + this.selectCalendar = index; + CalendarReminder.calendarReminders[index].isStart = false; + await CalendarReminder.openDialog(this.calendarSetting, index); + }) + ) + ) + }) + } + .layoutWeight(1) + + Blank() + Divider() + .height(0.75) + .width('100%') + .alignSelf(ItemAlign.Baseline) + .color($r('app.color.tab_bar_divider')) + } + .width('100%') + .height('100%') + } + + deleteItem(index: number): boolean { + CalendarReminder.deleteCalendar(index).then(() => { + this.calendarNames = [] + if (CalendarReminder.calendarReminders.length !== 0) { + for (let i = 0; i < CalendarReminder.calendarReminders.length; i++) { + this.calendarNames[i] = CalendarReminder.calendarReminders[i].reminderName + } + } + this.isEdit = false + }) + return true + } + + aboutToAppear() { + PreferencesDataManager.getData('Calendar').then((result) => { + if (result !== undefined) { + CalendarReminder.calendarReminders = result + for (let i = 0; i < CalendarReminder.calendarReminders.length; i++) { + this.calendarNames[i] = CalendarReminder.calendarReminders[i].reminderName + } + } + }) + } +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/calendar/CalendarSetting.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/calendar/CalendarSetting.ets new file mode 100644 index 0000000000000000000000000000000000000000..620703b1d59d637af9aa4ac59c3cd50701e313a0 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/calendar/CalendarSetting.ets @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2022 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 CalendarsReminder from '../../util/CalendarReminder' +import PreferencesDataManager from '../../util/PreferencesDataManager' + +interface musicsType { + value: string, + src: string +} + +@CustomDialog +export struct CalendarSetting { + @State selectName: string = 'Demo' + @State calendarTime: string = '0:0' + private selectIndex: number = 0; + private controller: CustomDialogController + private musics: Array = [{ value: 'Demo', src: '/system/etc/demo.wav' }, + { value: 'Dynamic', src: '/system/etc/dynamic.wav' }]; + + build() { + Column() { + Row() { + Text($r('app.string.calendar_time')) + .fontSize(20) + Blank() + Text(this.calendarTime) + .fontSize(20) + .fontColor($r('app.color.button_color')) + .id(`calendarTime${this.selectIndex}`) + .onClick(() => { + TimePickerDialog.show({ + selected: new Date, + useMilitaryTime: true, + onAccept: (value: TimePickerResult) => { + CalendarsReminder.calendarReminders[this.selectIndex].reminderRequestCalendar!.dateTime.hour = value.hour; + CalendarsReminder.calendarReminders[this.selectIndex].reminderRequestCalendar!.dateTime.minute = value.minute; + let hour = value.hour! < 10 ? `0${value.hour}` : value.hour; + let minute = value.minute! < 10 ? `0${value.minute}` : value.minute; + this.calendarTime = `${hour}:${minute}` + } + }) + }) + } + .width('100%') + .margin({ top: 8, bottom: 8 }) + .padding({ left: 8, right: 8 }) + + Row() { + Text($r('app.string.is_vibrator')) + .fontSize(20) + Blank() + Toggle({ type: ToggleType.Switch, isOn: CalendarsReminder.calendarReminders[this.selectIndex].isVibrator }) + .margin({ left: 8 }) + .onChange((isOn: boolean) => { + CalendarsReminder.calendarReminders[this.selectIndex].isVibrator = isOn + }) + .id(`vibrationSwitch${this.selectIndex}`) + } + .width('100%') + .padding({ left: 8, right: 8 }) + + Row() { + Text($r('app.string.setting_ringtone')) + .fontSize(20) + Blank() + Select(this.musics) + .selected(0) + .value(this.selectName) + .padding({ left: 20, right: 20 }) + .font({ size: 20 }) + .optionFont({ size: 20 }) + .selectedOptionFont({ size: 20 }) + .id(`music${this.selectIndex}`) + .onSelect((index: number, value: string) => { + this.selectName = value + CalendarsReminder.calendarReminders[this.selectIndex].audioSrc = this.musics[index].src + }) + } + .width('100%') + .margin({ top: 4, bottom: 4 }) + .padding({ left: 8, right: 8 }) + + Row() { + Button($r('app.string.cancel')) + .fontSize(24) + .margin({ right: 12 }) + .onClick(() => { + this.controller.close() + }) + Button($r('app.string.confirm')) + .fontSize(24) + .margin({ left: 12 }) + .onClick(async () => { + CalendarsReminder.setToggle(CalendarsReminder.calendarReminders[this.selectIndex].isStart,this.selectIndex); + await PreferencesDataManager.putData('Calendar', CalendarsReminder.calendarReminders); + this.controller.close(); + }) + } + .width('100%') + .margin({ top: 8, bottom: 8 }) + .padding({ left: 8, right: 8 }) + .justifyContent(FlexAlign.Center) + } + .padding({ top: 12 }) + } + + aboutToAppear() { + // Read the data of the settings and display it + let hour = CalendarsReminder.calendarReminders[this.selectIndex].reminderRequestCalendar!.dateTime.hour; + let minute = CalendarsReminder.calendarReminders[this.selectIndex].reminderRequestCalendar!.dateTime.minute; + let dataTimeHour = hour < 10 ? `0${hour}` : hour; + let dateTimeMinute = minute < 10 ? `0${minute}` : minute; + this.calendarTime = `${dataTimeHour}:${dateTimeMinute}`; + this.selectName = CalendarsReminder.calendarReminders[this.selectIndex].audioSrc === '/system/etc/demo.wav' ? 'Demo' : 'Dynamic'; + } +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/timer/SelectTime.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/timer/SelectTime.ets new file mode 100644 index 0000000000000000000000000000000000000000..baf9e32e8f2c47f288938a0041171662565c601c --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/timer/SelectTime.ets @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022 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 Constant from '../../common/Constant' + +@Component +export struct SelectTime { + @Link hour: number + @Link minute: number + @Link second: number + + build() { + Column({ space: 15 }) { + Row() { + TextPicker({ range: this.pickerArrayGen(24) }) + .width(60) + .onChange((value: string | string[], index: number | number[]) => { + this.hour = index as number; + }) + Text(':') + .fontSize(24) + .fontFamily('HarmonyHeiTi') + .fontWeight(Constant.FONT_WEIGHT) + .margin({ left: 15, right: 15 }) + TextPicker({ range: this.pickerArrayGen(60) }) + .width(60) + .onChange((value: string | string[], index: number | number[]) => { + this.minute = index as number; + }) + Text(':') + .fontSize(24) + .fontFamily('HarmonyHeiTi') + .fontWeight(Constant.FONT_WEIGHT) + .margin({ left: 15, right: 15 }) + TextPicker({ range: this.pickerArrayGen(60) }) + .width(60) + .onChange((value: string | string[], index: number | number[]) => { + this.second = index as number; + }) + } + + Row() { + Text($r('app.string.countdown_hour')) + .fontSize(14) + .fontWeight(500) + .fontFamily('HarmonyHeiTi') + .fontColor($r('app.color.font_dark')) + Text($r('app.string.countdown_minute')) + .fontSize(14) + .fontWeight(500) + .fontFamily('HarmonyHeiTi') + .margin({ left: 82, right: 82 }) + .fontColor($r('app.color.font_dark')) + Text($r('app.string.countdown_second')) + .fontSize(14) + .fontWeight(500) + .fontFamily('HarmonyHeiTi') + .fontColor($r('app.color.font_dark')) + } + } + } + + pickerArrayGen(num: number) { + return Array.from({ length: num }, (_: number, i) => (i < 10) ? ('0' + i) : ('' + i)); + } +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/timer/Timer.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/timer/Timer.ets new file mode 100644 index 0000000000000000000000000000000000000000..69d72e453ae986fd2045de206821eefc27cb4552 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/pages/timer/Timer.ets @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2022-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 notificationManager from '@ohos.notificationManager'; +import reminderAgent from '@ohos.reminderAgentManager'; +import vibrator from '@ohos.vibrator'; +import AudioPlayer from '../../util/AudioPlayer'; +import Constant from '../../common//Constant'; +import Logger from '../../util/Logger'; +import { SelectTime } from './SelectTime'; +import { BusinessError } from '@ohos.base'; +import common from '@ohos.app.ability.common'; + +const TAG: string = 'CountDown'; + +@Component +export struct Timer { + @State timer: number = 0 + @State rotates: number = 0 + @State passSec: number = 0 + @State pickerHour: number = 0 + @State pickerMinute: number = 0 + @State pickerSecond: number = 0 + @State audioId: number = 0 + @State hoursTime: number = 0 + @State minuteTime: number = 0 + @State secondTime: number = 0 + @State vibratorId: number = 0 + @State reminderId: number = 0 + @State countInSec: number = 0 + @State progressVal: number = 0 + @State countdownTime: number = 0 + @State isRunning: boolean = false + @State isPausing: boolean = false + @State startImg: Resource = $r('app.media.ic_public_start') + @State resetImg: Resource = $r('app.media.ic_countdown_reset') + private title: Resource | undefined = undefined; + private settings: RenderingContextSettings = new RenderingContextSettings(true) + private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings) + private selectedTime: Date = new Date(); + private intervalId: number = 0; + private calendarTimerId: number = 0; + + aboutToAppear() { + this.intervalId = setInterval(() => { + this.getTime(); + }, Constant.SECONDS_MILLISECONDS); + } + + aboutToDisappear() { + clearInterval(this.intervalId); + } + + build() { + Column() { + Row() { + Text(this.title) + .fontSize(24) + .margin({ left: 8 }) + Blank() + } + .height(56) + .padding(8) + .width('100%') + + Column({ space: 20 }) { + Stack() { + Image($r('app.media.ic_countdown_clock')) + .width(280) + .height(280) + Progress({ value: this.progressVal, style: ProgressStyle.ScaleRing }) + .width(250) + .height(250) + .style({ strokeWidth: 10, scaleCount: 80, scaleWidth: 2 }) + Canvas(this.context) + .onReady(() => { + this.context.lineWidth = 8 + this.context.strokeStyle = '#f2400a' + this.context.beginPath() + this.context.moveTo(15, 0) + this.context.arc(15, undefined, 10, 3.14 * 1.5, 3.14 * 0.5) + this.context.lineTo(15, undefined) + this.context.arc(15, undefined, 10, 3.14 * 0.5, 3.14 * 1.5) + this.context.stroke() + }) + .width(10) + .height(250) + .position({ x: '48.5%', y: 15 }) + .animation({ curve: Curve.Linear }) + .rotate({ + x: 0, + y: 0, + z: 1, + angle: this.rotates, + centerX: '50%', + centerY: 125 + }) + Image($r('app.media.ic_countdown_seconds')) + .width('25%') + .height('92%') + .objectFit(ImageFit.Contain) + .rotate({ z: 1, angle: -this.rotates }) + } + .height(270) + + Column() { + Text(`${this.formatTime(this.hoursTime)}:${this.formatTime(this.minuteTime)}:${this.formatTime(this.secondTime)}`) + .fontSize(24) + .id('countDown') + .fontFamily('HarmonyHeiTi-Medium') + .fontColor($r('app.color.font_dark')) + if (this.isRunning) { + Blank() + .height(180) + } else { + SelectTime({ hour: $pickerHour, minute: $pickerMinute, second: $pickerSecond }) + } + Row() { + Image(this.resetImg) + .width(48) + .height(48) + .id('resetCalculagraph') + .margin({ right: 100 }) + .objectFit(ImageFit.Fill) + .onClick(async () => { + await this.reset(true) + }) + Image(this.startImg) + .width(48) + .height(48) + .id('startCalculagraph') + .onClick(async () => { + if (this.pickerHour + this.pickerMinute + this.pickerSecond == 0) { + return + } + if (!this.isRunning || this.isPausing) { + await this.start() + } else { + await this.pause() + } + }) + } + } + } + .alignItems(HorizontalAlign.Center) + + Blank() + Divider() + .height(0.75) + .width('100%') + .alignSelf(ItemAlign.Baseline) + .color($r('app.color.tab_bar_divider')) + } + .width('100%') + .height('100%') + } + + formatTime(num: number) { + if (num > 99 || num < 0) { + return '**' + } + return (num < 10) ? ('0' + num).toString() : num.toString() + } + + getTime() { + this.selectedTime = new Date(); + } + + async timerCountDown() { + this.secondTime-- + if (this.secondTime < 0) { + this.minuteTime-- + this.secondTime = Constant.TIME_COUNTDOWN + } + if (this.minuteTime < 0) { + this.minuteTime = Constant.TIME_COUNTDOWN + this.hoursTime-- + } + if (this.hoursTime < 0) { + await this.reset() + return + } + this.passSec++ + this.progressVal = 100 - this.passSec * 100 / this.countInSec + this.rotates = this.passSec * Constant.ANGLE / this.countInSec + } + + async start() { + if (!this.isPausing) { + this.hoursTime = this.pickerHour + this.minuteTime = this.pickerMinute + this.secondTime = this.pickerSecond + } + let context = getContext(this) as common.UIAbilityContext; + this.countInSec = this.pickerHour * Constant.HOUR_SECONDS + this.pickerMinute * Constant.MINUTES_SECONDS + this.pickerSecond + this.countdownTime = this.hoursTime * Constant.HOUR_SECONDS + this.minuteTime * Constant.MINUTES_SECONDS + this.secondTime + this.isRunning = true + this.isPausing = false + this.startImg = $r('app.media.ic_public_pause') + this.resetImg = $r('app.media.ic_public_reset') + this.timer = setInterval(() => { + this.timerCountDown(); + }, Constant.SECONDS_MILLISECONDS); + await this.handleDefaultDevice(context); + try { + this.vibratorId = setTimeout(() => { + vibrator.startVibration({ + type: 'time', + duration: Constant.VIBRATOR_DURATION + }, { + id: 0, + usage: 'alarm' + }) + .then(() => { + Logger.info(TAG, `Succeed in starting vibration`); + }, (error: BusinessError) => { + Logger.error(TAG, `Failed to start vibration. + code: ${JSON.stringify(error.code)}, message: ${JSON.stringify(error.message)}`); + }); + }, this.countdownTime * Constant.SECONDS_MILLISECONDS); + } catch (err) { + Logger.error(TAG, `Start vibration error occurred. + code: ${JSON.stringify(err.code)}, message: ${JSON.stringify(err.message)}`); + } + this.audioId = await AudioPlayer.getAudioID('/system/etc/demo.wav', this.countdownTime * Constant.SECONDS_MILLISECONDS); + } + + async handleDefaultDevice(context: common.UIAbilityContext) { + await reminderAgent.addNotificationSlot({ notificationType: notificationManager.SlotType.SERVICE_INFORMATION }); + // [Start timer_reminder] + let timer: reminderAgent.ReminderRequestTimer = { + reminderType: reminderAgent.ReminderType.REMINDER_TYPE_TIMER, + ringDuration: Constant.REMINDER_DURATION, + title: context.resourceManager.getStringSync($r('app.string.timer').id), + content: context.resourceManager.getStringSync($r('app.string.countdown_close').id), + wantAgent: { + pkgName: 'com.example.reminderagentmanager', + abilityName: 'EntryAbility' + }, + slotType: notificationManager.SlotType.CONTENT_INFORMATION, + triggerTimeInSeconds: this.countdownTime + }; + // [End timer_reminder] + this.reminderId = await reminderAgent.publishReminder(timer); + } + + async pause() { + clearInterval(this.timer); + clearTimeout(this.audioId); + clearTimeout(this.vibratorId); + this.isRunning = true; + this.isPausing = true; + this.startImg = $r('app.media.ic_public_start'); + await reminderAgent.cancelReminder(this.reminderId); + await vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME); + } + + async reset(isCancel?: boolean) { + clearInterval(this.timer); + clearTimeout(this.audioId); + clearTimeout(this.vibratorId); + this.isRunning = false; + this.isPausing = false; + this.progressVal = 0; + this.rotates = 0; + this.passSec = 0; + this.hoursTime = 0; + this.minuteTime = 0; + this.secondTime = 0; + this.pickerHour = 0; + this.pickerMinute = 0; + this.pickerSecond = 0; + this.startImg = $r('app.media.ic_public_start'); + this.resetImg = $r('app.media.ic_countdown_reset'); + if (isCancel) { + await reminderAgent.cancelReminder(this.reminderId); + } + await vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME); + } +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/AlarmClockReminder.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/AlarmClockReminder.ets new file mode 100644 index 0000000000000000000000000000000000000000..989d8f3796eb1bc73c8ceda96a243e134199a7a3 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/AlarmClockReminder.ets @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2022-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 notificationManager from '@ohos.notificationManager'; +import reminderAgent from '@ohos.reminderAgentManager'; +import vibrator from '@ohos.vibrator'; +import AudioPlayer from './AudioPlayer'; +import Constant from '../common/Constant'; +import Logger from './Logger'; +import PreferencesDataManager from './PreferencesDataManager'; +import { Reminder } from '../common/Reminder'; +import TimeConversion from './TimeConversion'; +import common from '@ohos.app.ability.common'; +import { BusinessError } from '@ohos.base'; +import { promptAction } from '@kit.ArkUI'; + +const TAG: string = 'AlarmClockReminder'; + +class AlarmClockReminder { + public alarmClockReminders: Reminder[] = [] + private date: Date = new Date(); + + async setAlarmReminder(time: TimePickerResult) { + let hour = time.hour! < 10 ? `0${time.hour}` : time.hour; + let minute = time.minute! < 10 ? `0${time.minute}` : time.minute; + let context = getContext(this) as common.UIAbilityContext; + let selectTime: string = `${hour}:${minute}` + let isExistName = this.alarmClockReminders.find(element => element.reminderName === selectTime) !== undefined + if (!isExistName) { + let reminder: Reminder = { + audioSrc: '', + audioTimeouts: 0, + isStart: false, + isVibrator: false, + reminderId: 0, + reminderName: '', + vibratorTimeouts: 0, + reminderRequestAlarm: undefined + } + await reminderAgent.addNotificationSlot({ + notificationType: notificationManager.SlotType.CONTENT_INFORMATION + }); + reminder.reminderName = selectTime + // [Start alarm_reminder] + let alarm: reminderAgent.ReminderRequestAlarm = { + reminderType: reminderAgent.ReminderType.REMINDER_TYPE_ALARM, + hour: time.hour!, + minute: time.minute!, + actionButton: + [ + { + title: context.resourceManager.getStringSync($r('app.string.alarm_clock_close').id), + type: reminderAgent.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE + }, + { + title: context.resourceManager.getStringSync($r('app.string.alarm_clock_postpone').id), + type: reminderAgent.ActionButtonType.ACTION_BUTTON_TYPE_SNOOZE + } + ], + slotType: notificationManager.SlotType.CONTENT_INFORMATION, + ringDuration: Constant.REMINDER_DURATION, + wantAgent: { + pkgName: 'com.example.reminderagentmanager', + abilityName: 'EntryAbility' + }, + title: context.resourceManager.getStringSync($r('app.string.alarm_clock').id), + content: context.resourceManager.getStringSync($r('app.string.alarm_clock_reach').id), + snoozeTimes: 0, + timeInterval: 0, + daysOfWeek: [] + } + // [End alarm_reminder] + Logger.info(TAG, `this alarm clock is ${JSON.stringify(alarm)}`) + reminder.reminderRequestAlarm = alarm + reminder.isStart = false + this.alarmClockReminders.push(reminder) + Logger.info(TAG, `setAlarmReminder this all alarmclock is ${JSON.stringify(this.alarmClockReminders)}`) + await PreferencesDataManager.putData('alarmClock', this.alarmClockReminders) + } else { + promptAction.showToast({ + message: context.resourceManager.getStringSync($r('app.string.alarm_clock_existence').id), + duration: Constant.PROMPT_DURATION + }) + } + } + + async setToggle(isOn: boolean, index: number) { + let hour = this.alarmClockReminders[index].reminderRequestAlarm!.hour; + let minute = this.alarmClockReminders[index].reminderRequestAlarm!.minute; + let selectTime: string = `${hour}:${minute}`; + let year = this.date.getFullYear(); + let month = this.date.getMonth() + 1; + let day = this.date.getDate(); + this.alarmClockReminders[index].isStart = isOn + if (isOn) { + await reminderAgent.addNotificationSlot( + { notificationType: notificationManager.SlotType.SOCIAL_COMMUNICATION }); + let reminderId = await reminderAgent.publishReminder(this.alarmClockReminders[index].reminderRequestAlarm!); + this.alarmClockReminders[index].reminderId = reminderId; + if (this.alarmClockReminders[index].audioSrc) { + let audioIndex: number = await AudioPlayer.getAudioID(this.alarmClockReminders[index].audioSrc, + TimeConversion.timeToMillisecond(this.alarmClockReminders[index].reminderRequestAlarm!.hour, + this.alarmClockReminders[index].reminderRequestAlarm!.minute) * Constant.SECONDS_MILLISECONDS); + this.alarmClockReminders[index].audioTimeouts = audioIndex + } + await PreferencesDataManager.putData('alarmClock', this.alarmClockReminders) + if (this.alarmClockReminders[index].isVibrator) { + let vibratorId: number = 0; + try { + vibratorId = setTimeout(() => { + vibrator.startVibration({ + type: 'time', + duration: Constant.VIBRATOR_DURATION + }, { + id: 0, + usage: 'alarm' + }) + .then(() => { + Logger.info(TAG, `succeed in starting vibration`); + }, (error: BusinessError) => { + Logger.error(TAG, `setToggle this vibrator is failed. + code: ${JSON.stringify(error.code)}, message: ${JSON.stringify(error.message)}`); + }); + }, TimeConversion.timeToMillisecond(this.alarmClockReminders[index].reminderRequestAlarm!.hour, + this.alarmClockReminders[index].reminderRequestAlarm!.minute) * Constant.SECONDS_MILLISECONDS); + } catch (err) { + Logger.error(TAG, `start vibration error occurred. + code: ${JSON.stringify(err.code)}, message: ${JSON.stringify(err.message)}`); + } + this.alarmClockReminders[index].vibratorTimeouts = vibratorId; + await PreferencesDataManager.putData('alarmClock', this.alarmClockReminders); + } else { + clearTimeout(this.alarmClockReminders[index].vibratorTimeouts); + await vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME); + } + } else { + clearTimeout(this.alarmClockReminders[index].vibratorTimeouts) + clearTimeout(this.alarmClockReminders[index].audioTimeouts) + await PreferencesDataManager.putData('alarmClock', this.alarmClockReminders) + await reminderAgent.cancelReminder(this.alarmClockReminders[index].reminderId); + await vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME); + } + } + + async openDialog(dialog: CustomDialogController, index: number) { + dialog.open(); + } + + async deleteAlarmReminder(index: number) { + try { + clearTimeout(this.alarmClockReminders[index].vibratorTimeouts) + clearTimeout(this.alarmClockReminders[index].audioTimeouts) + reminderAgent.cancelReminder(this.alarmClockReminders[index].reminderId).then(() => { + Logger.info(TAG, `deleteAlarmReminder cancelReminder is succeed`); + }).catch((err: BusinessError) => { + Logger.info(TAG, `deleteAlarmReminder cancelReminder is not exist err is ${JSON.stringify(err)}`); + }) + vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME).then(() => { + Logger.info(TAG, `deleteAlarmReminder stop vibrator is succeed`) + }).catch((err: BusinessError) => { + Logger.error(TAG, `deleteAlarmReminder vibrator is not exist err is ${JSON.stringify(err)}`) + }) + this.alarmClockReminders[index].isStart = false + this.alarmClockReminders[index].reminderName = '' + this.alarmClockReminders[index].vibratorTimeouts = 0 + this.alarmClockReminders[index].reminderRequestAlarm = undefined + } catch (err) { + Logger.info(TAG, `this cancel not exist err is ${JSON.stringify(err)}`) + } + this.alarmClockReminders.splice(index, 1) + Logger.info(TAG, `deleteAlarmReminder this all alarmclock is ${JSON.stringify(this.alarmClockReminders)}`) + PreferencesDataManager.putData('alarmClock', this.alarmClockReminders).then(() => { + Logger.info(TAG, `deleteAlarmReminder this put data is successed`) + }) + } +} + +export default new AlarmClockReminder() \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/AudioPlayer.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/AudioPlayer.ets new file mode 100644 index 0000000000000000000000000000000000000000..54ba36bf8f34118f449b8fd37cde078af0ea4020 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/AudioPlayer.ets @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022 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 fileIo from '@ohos.fileio' +import media from '@ohos.multimedia.media' +import Logger from './Logger' + +const AUDIO_TIME: number = 10000 +const TAG: string = 'AudioPlayer' + +export class AudioPlayer { + async getAudioID(musicSrc: string, delayTime: number) { + let audio: media.AudioPlayer = media.createAudioPlayer() + this.setAudio(audio) + let fdPath = 'fd://' + let fdValue = await fileIo.open(musicSrc) + fdPath = fdPath + '' + fdValue + let audioID: number = setTimeout(() => { + audio.src = fdPath // Set the src property and trigger the 'dataLoad' event callback + }, delayTime); + return audioID + } + + private setAudio(audio: media.AudioPlayer | undefined) { + audio!.on('dataLoad', () => { // Set the 'dataLoad' event callback, which is triggered after the src attribute is set successfully + Logger.info(TAG, 'audio set source success'); + audio!.play(); // Call the play method to start playing, triggering the 'play' event callback + }) + audio!.on('play', () => { // Set the 'play' event callback + Logger.info(TAG, 'audio play success'); + setTimeout(() => { + audio!.stop(); + }, AUDIO_TIME); + }) + audio!.on('stop', () => { // Set the 'stop' event callback + Logger.info(TAG, 'audio stop success'); + audio!.release(); // The audioPlayer resource is destroyed + audio = undefined; + }) + } +} + +export default new AudioPlayer() \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/CalendarReminder.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/CalendarReminder.ets new file mode 100644 index 0000000000000000000000000000000000000000..35c47409df5018e848ff6b5f58c42e1dbced9f32 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/CalendarReminder.ets @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2022-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 reminderAgent from '@ohos.reminderAgentManager'; +import vibrator from '@ohos.vibrator'; +import AudioPlayer from './AudioPlayer'; +import Constant from '../common/Constant'; +import Logger from './Logger'; +import PreferencesDataManager from './PreferencesDataManager'; +import { Reminder } from '../common/Reminder'; +import TimeConversion from './TimeConversion'; +import common from '@ohos.app.ability.common'; +import notificationManager from '@ohos.notificationManager'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { promptAction } from '@kit.ArkUI'; + +const TAG: string = 'CalendarReminder'; + +class CalendarReminder { + public calendarReminders: Reminder[] = []; + + setCalendarReminder() { + } + + async setCalendar(date: Date) { + let context = getContext(this) as common.UIAbilityContext; + let selectCalendar: string = `${date.getFullYear()}-${date.getUTCMonth() + 1}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}`; + let isExistName = this.calendarReminders.find(element => element.reminderName === selectCalendar) !== undefined; + if (!isExistName) { + let reminder: Reminder = { + audioSrc: '', + audioTimeouts: 0, + isStart: false, + isVibrator: false, + reminderId: 0, + reminderName: '', + vibratorTimeouts: 0, + reminderRequestCalendar: undefined + } + await reminderAgent.addNotificationSlot({ notificationType: notificationManager.SlotType.SERVICE_INFORMATION }); + reminder.reminderName = selectCalendar + // [Start calendar_reminder] + let calendar: reminderAgent.ReminderRequestCalendar = { + reminderType: reminderAgent.ReminderType.REMINDER_TYPE_CALENDAR, + dateTime: { + year: date.getFullYear(), + month: date.getUTCMonth() + 1, + day: date.getDate(), + hour: date.getHours(), + minute: date.getMinutes(), + }, + actionButton: + [{ + title: context.resourceManager.getStringSync($r('app.string.calendar_close').id), + type: reminderAgent.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE + }], + wantAgent: { pkgName: 'com.example.reminderagentmanager', abilityName: 'EntryAbility' }, + ringDuration: Constant.REMINDER_DURATION, + title: context.resourceManager.getStringSync($r('app.string.calendar').id), + content: context.resourceManager.getStringSync($r('app.string.calendar_reach').id), + slotType: notificationManager.SlotType.CONTENT_INFORMATION + } + // [End calendar_reminder] + Logger.info(TAG, `setCalendar this calendar is ${JSON.stringify(calendar)}}`); + reminder.reminderRequestCalendar = calendar + reminder.isStart = false + this.calendarReminders.push(reminder) + Logger.info(TAG, `setCalendar this all calendar is ${JSON.stringify(this.calendarReminders)}`); + await PreferencesDataManager.putData('Calendar', this.calendarReminders) + this.setCalendarReminder(); + } else { + promptAction.showToast({ + message: context.resourceManager.getStringSync($r('app.string.calendar_existence').id), + duration: Constant.PROMPT_DURATION + }) + } + } + + async setToggle(isOn: boolean, index: number) { + this.calendarReminders[index].isStart = isOn + if (isOn) { + await reminderAgent.addNotificationSlot({ notificationType: notificationManager.SlotType.SERVICE_INFORMATION }); + // [Start publish_reminder] + let reminderId: number = await reminderAgent.publishReminder( + this.calendarReminders[index].reminderRequestCalendar!); + this.calendarReminders[index].reminderId = reminderId; + // [End publish_reminder] + if (this.calendarReminders[index].audioSrc) { + let audioIndex: number = await AudioPlayer.getAudioID( + this.calendarReminders[index].audioSrc, TimeConversion.dateToMillisecond( + this.calendarReminders[index].reminderRequestCalendar!.dateTime.year, + this.calendarReminders[index].reminderRequestCalendar!.dateTime.month, + this.calendarReminders[index].reminderRequestCalendar!.dateTime.day, + this.calendarReminders[index].reminderRequestCalendar!.dateTime.hour, + this.calendarReminders[index].reminderRequestCalendar!.dateTime.minute) * Constant.SECONDS_MILLISECONDS); + this.calendarReminders[index].audioTimeouts = audioIndex; + } + await PreferencesDataManager.putData('Calendar', this.calendarReminders) + if (this.calendarReminders[index].isVibrator) { + let vibratorId: number = 0; + try { + vibratorId = setTimeout(() => { + vibrator.startVibration({ + type: 'time', + duration: Constant.VIBRATOR_DURATION, + }, { + id: 0, + usage: 'alarm' + }, (err) => { + if (err) { + Logger.error(TAG, `setToggle this vibrator is failed err is ${JSON.stringify(err)}`); + } else { + Logger.info(TAG, `setToggle this vibrator is successed`); + } + }) + }, TimeConversion.dateToMillisecond(this.calendarReminders[index].reminderRequestCalendar!.dateTime.year, + this.calendarReminders[index].reminderRequestCalendar!.dateTime.month, + this.calendarReminders[index].reminderRequestCalendar!.dateTime.day, + this.calendarReminders[index].reminderRequestCalendar!.dateTime.hour, + this.calendarReminders[index].reminderRequestCalendar!.dateTime.minute) * Constant.SECONDS_MILLISECONDS); + } catch (err) { + Logger.error(TAG, `setToggle this vibrator occurred. + code: ${JSON.stringify(err.code)}, message: ${JSON.stringify(err.message)}`); + } + this.calendarReminders[index].vibratorTimeouts = vibratorId + await PreferencesDataManager.putData('Calendar', this.calendarReminders) + } else { + clearTimeout(this.calendarReminders[index].vibratorTimeouts) + await vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME); + } + } else { + clearTimeout(this.calendarReminders[index].vibratorTimeouts) + clearTimeout(this.calendarReminders[index].audioTimeouts) + await PreferencesDataManager.putData('Calendar', this.calendarReminders); + // [Start cancel_reminder] + await reminderAgent.cancelReminder(this.calendarReminders[index].reminderId); + // [Start cancel_reminder] + await vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME); + } + } + + async openDialog(dialog: CustomDialogController, index: number) { + try { + await reminderAgent.cancelReminder(this.calendarReminders[index].reminderId); + } catch (err) { + Logger.error(TAG, `openDialog this cancelReminder is not exist,err is ${JSON.stringify(err)}`) + } + dialog.open() + } + + async deleteCalendar(index: number) { + try { + clearTimeout(this.calendarReminders[index].vibratorTimeouts) + clearTimeout(this.calendarReminders[index].audioTimeouts) + reminderAgent.cancelReminder(this.calendarReminders[index].reminderId).then(() => { + Logger.info(TAG, `deleteCalendar cancelReminder is succeed`); + }) + vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME).then(() => { + Logger.info(TAG, `deleteCalendar stop vibrator is succeed`) + }) + this.calendarReminders[index].isStart = false + this.calendarReminders[index].reminderName = '' + this.calendarReminders[index].vibratorTimeouts = 0 + this.calendarReminders[index].reminderRequestCalendar = undefined + } catch (err) { + Logger.info(TAG, `deleteCalendar this cancel not exist err is ${JSON.stringify(err)}`) + } + this.calendarReminders.splice(index, 1) + Logger.info(TAG, `deleteCalendar this all calendar is ${JSON.stringify(this.calendarReminders)}`) + PreferencesDataManager.putData('Calendar', this.calendarReminders).then(() => { + Logger.info(TAG, `deleteCalendar this put data is successed`) + }) + } +} + +export default new CalendarReminder() \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/Logger.ts b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/Logger.ts new file mode 100644 index 0000000000000000000000000000000000000000..f5b478e1b1e04ba4931ec09d20586c98566d8e14 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/Logger.ts @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 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 '@ohos.hilog' + +class Logger { + private domain: number + private prefix: string + private format: string = '%{public}s, %{public}s' + + constructor(prefix: string) { + this.prefix = prefix + this.domain = 0xFF00 + } + + debug(...args: any[]) { + hilog.debug(this.domain, this.prefix, this.format, args) + } + + info(...args: any[]) { + hilog.info(this.domain, this.prefix, this.format, args) + } + + warn(...args: any[]) { + hilog.warn(this.domain, this.prefix, this.format, args) + } + + error(...args: any[]) { + hilog.error(this.domain, this.prefix, this.format, args) + } +} + +export default new Logger('[Sample_ReminderAgentManager]') \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/PreferencesDataManager.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/PreferencesDataManager.ets new file mode 100644 index 0000000000000000000000000000000000000000..f964ed4c8517cc23a243cdc184f2ad40b2335de3 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/PreferencesDataManager.ets @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 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 data_preferences from '@ohos.data.preferences' +import Logger from './Logger' +import { Reminder } from '../common/Reminder' +import common from '@ohos.app.ability.common'; + +const TAG: string = 'Preferences' + +class PreferencesDataManager { + private context = getContext(this) as common.UIAbilityContext; + + async getData(key: string) { + let getValue: Reminder[] | undefined = undefined; + let preferences = await data_preferences.getPreferences(this.context, 'ReminderAgentManager') + if (await preferences.get(key, 'default')) { + try { + let result = await preferences.get(key, 'default') as string; + getValue = JSON.parse(result) + Logger.info(TAG, `this is ${JSON.stringify(getValue)}`) + } catch (err) { + Logger.error(TAG, `this getData err is ${JSON.stringify(err)} name is ${key}`) + } + } else { + Logger.info(TAG, `this abouttoappear is unexist`) + } + return getValue + } + + async putData(key: string, value: Reminder[]) { + let preferences = await data_preferences.getPreferences(this.context, 'ReminderAgentManager') + try { + await preferences.put(key, JSON.stringify(value)) + await preferences.flush() + } catch (err) { + Logger.error(TAG, `this perferences is failed, err is ${JSON.stringify(err)}`) + } + } +} + +export default new PreferencesDataManager() \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/TimeConversion.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/TimeConversion.ets new file mode 100644 index 0000000000000000000000000000000000000000..4b823f73b19aec0dda5c5f8588df99c161af6dd7 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/ets/util/TimeConversion.ets @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022-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 Logger from './Logger' + +const TAG: string = 'TimeConversion' +const HOUR_SECONDS: number = 3600 +const DAY_SECONDS: number = 86400 +const MINUTES_SECONDS: number = 60 +const YEAR_SECONDS: number = 31536000 +const MONTH_SECONDS: number = 2592000 + +class TimeConversion { + // Converts the time units obtained in the time selection component to milliseconds + timeToMillisecond(hour: number, minute: number) { + let nowTime: Date = new Date + let nowAllTime: number = nowTime.getHours() * HOUR_SECONDS + nowTime.getMinutes() * + MINUTES_SECONDS + nowTime.getSeconds() + let selectAllTime: number = (hour * HOUR_SECONDS + minute * MINUTES_SECONDS) + let delayTime: number = selectAllTime - nowAllTime >= 0 ? selectAllTime - nowAllTime : + DAY_SECONDS - (nowAllTime - selectAllTime) + Logger.info(TAG, `this vibratorTime is ${delayTime}`) + return (delayTime - 2) + } + + // Converts the time units obtained in the date selection component to milliseconds + dateToMillisecond(year: number, month: number, day: number, hour: number, minute: number) { + let nowTime: Date = new Date; + let nowAllTime: number = nowTime.getFullYear() * YEAR_SECONDS + (nowTime.getMonth() + 1) * MONTH_SECONDS + + nowTime.getDate() * DAY_SECONDS + nowTime.getHours() * HOUR_SECONDS + nowTime.getMinutes() * MINUTES_SECONDS + + nowTime.getSeconds(); + let selectAllTime: number = year * YEAR_SECONDS + month * MONTH_SECONDS + day * DAY_SECONDS + hour * HOUR_SECONDS + + minute * MINUTES_SECONDS; + let delayTime: number = selectAllTime - nowAllTime; + Logger.info(TAG, `this vibratorTime is ${delayTime}`); + return delayTime; + } +} + +export default new TimeConversion() \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/module.json5 b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4cda2e21f7408f4e90e499553bcadc40b5ece419 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/module.json5 @@ -0,0 +1,97 @@ +/* + * 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. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "requestPermissions": [ + { + "name": "ohos.permission.PUBLISH_AGENT_REMINDER", + "reason": "$string:permission_reason", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "inuse" + } + }, + { + "name": "ohos.permission.VIBRATE", + "reason": "$string:permission_vibrate", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "inuse" + } + }, + { + "name": "ohos.permission.READ_MEDIA", + "reason": "$string:permission_media", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "inuse" + } + }, + ], + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "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/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/element/color.json b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..eedaf3adacea1e90a5bfab1893ef9ca9248eb1ba --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/element/color.json @@ -0,0 +1,36 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + }, + { + "name": "white", + "value": "#FFFFFF" + }, + { + "name": "tab_bar_select", + "value": "#007DFF" + }, + { + "name": "tab_bar_unselect", + "value": "#66182431" + }, + { + "name": "tab_bar_divider", + "value": "#33182431" + }, + { + "name": "background_shallow_grey", + "value": "#F1F3F5" + }, + { + "name": "button_color", + "value": "#007DFF" + }, + { + "name": "font_dark", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/element/float.json b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/element/string.json b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..6a5fad716eebfe6964473f012be0e61c771e4120 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/element/string.json @@ -0,0 +1,160 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "Create a scheduled reminder with countdown, calendar, alarm" + }, + { + "name": "EntryAbility_desc", + "value": "SystemCapability.Notification.ReminderAgent" + }, + { + "name": "EntryAbility_label", + "value": "Background Agent Reminder" + }, + { + "name": "permission_reason", + "value": "Allow the app to use background agent reminders" + }, + { + "name": "permission_vibrate", + "value": "Allows the application to control motor vibration" + }, + { + "name": "permission_media", + "value": "Allows the app to read media file information from the user's external storage" + }, + { + "name": "permission_read_calendar", + "value": "Allow the app to read calendar information" + }, + { + "name": "permission_write_calendar", + "value": "Allow the app to add, remove, or change calendar events" + }, + { + "name": "setting", + "value": "Settings" + }, + { + "name": "delete", + "value": "Delete" + }, + { + "name": "confirm", + "value": "Confirm" + }, + { + "name": "cancel", + "value": "Cancel" + }, + { + "name": "alarm_clock", + "value": "Alarm Clock" + }, + { + "name": "alarm_clock_close", + "value": "Turn off alarm" + }, + { + "name": "alarm_clock_postpone", + "value": "Snooze alarm" + }, + { + "name": "alarm_clock_reach", + "value": "Alarm time has arrived" + }, + { + "name": "alarm_clock_existence", + "value": "Alarm clock already exists" + }, + { + "name": "alarm_clock_one", + "value": "One" + }, + { + "name": "alarm_clock_two", + "value": "Two" + }, + { + "name": "alarm_clock_three", + "value": "Three" + }, + { + "name": "alarm_clock_four", + "value": "Four" + }, + { + "name": "alarm_clock_five", + "value": "Five" + }, + { + "name": "alarm_clock_six", + "value": "Six" + }, + { + "name": "alarm_clock_seven", + "value": "Seven" + }, + { + "name": "alarm_clock_remind_day", + "value": "Set reminder days" + }, + { + "name": "alarm_clock_snooze", + "value": "Set the number of intervals" + }, + { + "name": "alarm_clock_interval", + "value": "Set interval duration" + }, + { + "name": "calendar", + "value": "Calendar" + }, + { + "name": "calendar_close", + "value": "Turn off calendar reminders" + }, + { + "name": "calendar_reach", + "value": "Calendar reminder time is up" + }, + { + "name": "calendar_existence", + "value": "Calendar reminder already exists" + }, + { + "name": "calendar_time", + "value": "Set reminder time" + }, + { + "name": "timer", + "value": "Timer" + }, + { + "name": "countdown_close", + "value": "Countdown has ended" + }, + { + "name": "countdown_hour", + "value": "Hour" + }, + { + "name": "countdown_minute", + "value": "Points" + }, + { + "name": "countdown_second", + "value": "Seconds" + }, + { + "name": "is_vibrator", + "value": "Set vibration" + }, + { + "name": "setting_ringtone", + "value": "Set ringtone" + } + ] +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/background.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/background.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/foreground.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/foreground.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_countdown_clock.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_countdown_clock.png new file mode 100644 index 0000000000000000000000000000000000000000..c1d466058e834f434dd3e7b6b7d0ebaaa3c327d9 Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_countdown_clock.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_countdown_reset.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_countdown_reset.png new file mode 100644 index 0000000000000000000000000000000000000000..006653449621791c35f71c5ffad88fc9bec1675f Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_countdown_reset.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_countdown_seconds.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_countdown_seconds.png new file mode 100644 index 0000000000000000000000000000000000000000..a8d99c8c3c766d54ceb49ac850e0c6712576b101 Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_countdown_seconds.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_add.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_add.png new file mode 100644 index 0000000000000000000000000000000000000000..c464f1472a9aa8ce0fe782d65336005f0d0fce1b Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_add.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_calendar.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_calendar.png new file mode 100644 index 0000000000000000000000000000000000000000..8f1fe805513faedea19b6d64c6c20ad14290edce Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_calendar.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_calendar_filled.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_calendar_filled.png new file mode 100644 index 0000000000000000000000000000000000000000..c0e06ad5d138ae79b8d77fa86c605c82d34256d7 Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_calendar_filled.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_clock.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_clock.png new file mode 100644 index 0000000000000000000000000000000000000000..75fd0318ee7d71740eed6363541f0fa64c9744ce Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_clock.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_clock_filled.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_clock_filled.png new file mode 100644 index 0000000000000000000000000000000000000000..b57c94ef621a9dc0260d67ba8b20040f122bd80d Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_clock_filled.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_pause.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_pause.png new file mode 100644 index 0000000000000000000000000000000000000000..a09e36d443ac4853853d9236d66c0ac3f3466b88 Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_pause.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_reset.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_reset.png new file mode 100644 index 0000000000000000000000000000000000000000..09324de3d466f6bca8245a9adb3bae33a5a974fa Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_reset.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_start.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_start.png new file mode 100644 index 0000000000000000000000000000000000000000..ddaaed69c71c6334495fe67d03f059a60d8f4e5c Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_start.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_timer.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_timer.png new file mode 100644 index 0000000000000000000000000000000000000000..151e9d8962157f240aa16917982db3c1a6caeafd Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_timer.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_timer_filled.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_timer_filled.png new file mode 100644 index 0000000000000000000000000000000000000000..bb84138a5c63aed82bee480714913b2b36d3162d Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/ic_public_timer_filled.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/icon.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/icon.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/layered_image.json b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/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/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/startIcon.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/media/startIcon.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/profile/backup_config.json b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/profile/main_pages.json b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/dark/element/color.json b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/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/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/zh_CN/element/string.json b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..735664d65588eefa7cc2393b2e4fde34567237fc --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,160 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "使用闹钟、日历、计时器创建定时提醒" + }, + { + "name": "EntryAbility_desc", + "value": "SystemCapability.Notification.ReminderAgent" + }, + { + "name": "EntryAbility_label", + "value": "后台代理提醒" + }, + { + "name": "permission_reason", + "value": "允许该应用使用后台代理提醒" + }, + { + "name": "permission_vibrate", + "value": "允许应用控制马达振动" + }, + { + "name": "permission_media", + "value": "允许应用读取用户外部存储中的媒体文件信息" + }, + { + "name": "permission_read_calendar", + "value": "允许应用读取日历信息" + }, + { + "name": "permission_write_calendar", + "value": "允许应用添加、移除或更改日历活动" + }, + { + "name": "setting", + "value": "设置" + }, + { + "name": "delete", + "value": "删除" + }, + { + "name": "confirm", + "value": "确认" + }, + { + "name": "cancel", + "value": "取消" + }, + { + "name": "alarm_clock", + "value": "闹钟" + }, + { + "name": "alarm_clock_close", + "value": "关闭闹钟" + }, + { + "name": "alarm_clock_postpone", + "value": "推迟闹钟" + }, + { + "name": "alarm_clock_reach", + "value": "闹钟时间已到" + }, + { + "name": "alarm_clock_existence", + "value": "闹钟已存在" + }, + { + "name": "alarm_clock_one", + "value": "一" + }, + { + "name": "alarm_clock_two", + "value": "二" + }, + { + "name": "alarm_clock_three", + "value": "三" + }, + { + "name": "alarm_clock_four", + "value": "四" + }, + { + "name": "alarm_clock_five", + "value": "五" + }, + { + "name": "alarm_clock_six", + "value": "六" + }, + { + "name": "alarm_clock_seven", + "value": "七" + }, + { + "name": "alarm_clock_remind_day", + "value": "设置提醒天数" + }, + { + "name": "alarm_clock_snooze", + "value": "设置间隔次数" + }, + { + "name": "alarm_clock_interval", + "value": "设置间隔时长" + }, + { + "name": "calendar", + "value": "日历" + }, + { + "name": "calendar_close", + "value": "关闭日历提醒" + }, + { + "name": "calendar_reach", + "value": "日历提醒时间到了" + }, + { + "name": "calendar_existence", + "value": "日历提醒已存在" + }, + { + "name": "calendar_time", + "value": "设置提醒时间" + }, + { + "name": "timer", + "value": "计时器" + }, + { + "name": "countdown_close", + "value": "计时器已结束" + }, + { + "name": "countdown_hour", + "value": "时" + }, + { + "name": "countdown_minute", + "value": "分" + }, + { + "name": "countdown_second", + "value": "秒" + }, + { + "name": "is_vibrator", + "value": "是否设置震动" + }, + { + "name": "setting_ringtone", + "value": "设置铃声" + } + ] +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/mock/mock-config.json5 b/BackGroundTasksKit/ReminderAgentManager/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * 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. + */ + +{ +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000000000000000000000000000000000000..13f3712e7b1ee891bb5dee9917cface15fc4a547 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2023 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 '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s it', + '-s level', '-s testType', '-s size', '-s timeout', + '-s dryRun' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams = `${targetParams} ${key} ${parameters[key]}` + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + var debug = abilityDelegatorArguments.parameters['-D'] + if (debug == 'true') + { + cmd += ' -D' + } + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd); + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/test/Ability.test.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..c1cb009085956549c0e1e1d3f1b65aaa41542c06 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2023-2024 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 { describe, it, expect } from '@ohos/hypium'; +import { Driver, ON, Component } from '@ohos.UiTest'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import data_preferences from '@ohos.data.preferences' +import reminderAgent from '@ohos.reminderAgentManager'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import Logger from '../util/Logger'; + +interface Reminder { + audioSrc: string, + audioTimeouts: number, + isStart: boolean, + isVibrator: boolean, + reminderName: string, + reminderId: number, + vibratorTimeouts: number, + reminderRequestAlarm?: reminderAgent.ReminderRequestAlarm, + reminderRequestCalendar?: reminderAgent.ReminderRequestCalendar, +} + +interface timerType { + reminderType: reminderAgent.ReminderType; + triggerTimeInSeconds: number; +} + +const BUNDLE = 'reminderAgentManagerTest_'; +const TAG = 'ReminderAgentAppTestPage'; +let abilityDelegatorRegistry = AbilityDelegatorRegistry.getAbilityDelegator(); +let uiAbility: UIAbility = new UIAbility(); + +async function getResourceString(resource: Resource): Promise { + let manage = abilityDelegatorRegistry.getAppContext().resourceManager; + let text = await manage.getStringValue(resource); + return text; +} + +// 获取存储数据 +async function getPerferenceData(key: string) { + let preferences = await data_preferences.getPreferences(uiAbility.context, 'ReminderAgentManager'); + let getValue = []; + if (await preferences.get(key, 'default')) { + try { + let result = await preferences.get(key, 'default'); + getValue = JSON.parse(result as string); + } catch (err) { + Logger.error(TAG, `this getData err is ${JSON.stringify(err)}`); + } + } else { + Logger.info(TAG, `this abouttoappear is unexist`); + } + return getValue; +} + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // 打开应用 + it('StartAbility_001', 0, async (done: Function) => { + Logger.info(TAG, 'StartAbility start') + abilityDelegatorRegistry.startAbility({ + bundleName: "ohos.samples.reminderagentmanager", + abilityName: "MainAbility" + }, (err) => { + Logger.info(TAG, `_startAbility get err ${JSON.stringify(err)}`); + done(); + Logger.info(TAG, '_startAbility end'); + }); + + let monitor: AbilityDelegatorRegistry.AbilityMonitor = { + abilityName: 'MainAbility', + onAbilityCreate: () => { + Logger.info(TAG, 'onAbilityCreateCallback'); + } + } + uiAbility = await abilityDelegatorRegistry.waitAbilityMonitor(monitor); + Logger.info(TAG, 'StartAbility end') + done(); + }) + /** + * 获取通知使能 + */ + it('RequestEnableNotification_001', 0, async (done: Function) => { + Logger.info(TAG, BUNDLE + 'RequestEnableNotification begin'); + let driver: Driver = Driver.create(); + await driver.delayMs(3000); + await driver.assertComponentExist(ON.text(await getResourceString(($r('app.string.agree'))))); + let agreeNotication: Component = await driver.findComponent(ON.text(await getResourceString(($r('app.string.agree'))))); + await driver.delayMs(1000); + await agreeNotication.click(); + await driver.delayMs(1000); + // 校验是否使能成功 + let timer: timerType = { + reminderType: reminderAgent.ReminderType.REMINDER_TYPE_TIMER, + triggerTimeInSeconds: 10 + } + let reminderId = await reminderAgent.publishReminder(timer); + if (!reminderId) { + Logger.info(TAG, 'RequestEnableNotification failed'); + expect().assertFail(); + } + Logger.info(TAG, BUNDLE + 'RequestEnableNotification end'); + done(); + }) + + /** + * 设置日历,用例只支持RK3568 + */ + it('setCalendar_001', 0, async (done: Function) => { + Logger.info(TAG, BUNDLE + 'createCalendar begin'); + let driver: Driver = Driver.create(); + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text(await getResourceString(($r('app.string.calendar'))))); + let calendarTab: Component = await driver.findComponent(ON.text(await getResourceString(($r('app.string.calendar'))))); + await driver.delayMs(1000); + await calendarTab.click(); + await driver.delayMs(1000); + // 新建一个日历 + await driver.assertComponentExist(ON.id('addCalendar')); + let addCalendar: Component = await driver.findComponent(ON.id('addCalendar')); + await driver.delayMs(1000); + await addCalendar.click(); + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text(await getResourceString(($r('app.string.determine'))))); + let confirm: Component = await driver.findComponent(ON.text(await getResourceString(($r('app.string.determine'))))); + await driver.delayMs(1000); + await confirm.click(); + await driver.delayMs(1000); + // 开启开关 + await driver.assertComponentExist(ON.id('calendarSwitch0')); + let calendarSwitch: Component = await driver.findComponent(ON.id('calendarSwitch0')); + await driver.delayMs(1000); + await calendarSwitch.click(); + await driver.delayMs(3000); + // 获取日历数据 + let calenderData: Reminder[] = await getPerferenceData('Calendar'); + let lastReminderName: string = calenderData[calenderData.length-1].reminderName; + // 删除日历 + await driver.delayMs(1000); + // 坐标基于rk3568 + await driver.swipe(473, 197, 373, 197, 800); + await driver.delayMs(1000); + // 校验删除功能 + let calenderDataDel: Reminder[] = await getPerferenceData('Calendar'); + if (calenderDataDel !== undefined) { + let isExistName = calenderDataDel.find(element => element.reminderName === lastReminderName) !== undefined; + if (isExistName) { + expect().assertFail(); + } else { + Logger.info(TAG, 'mst success') + } + } + // 再次新建一个日历 + await driver.delayMs(1000); + await addCalendar.click(); + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text(await getResourceString(($r('app.string.determine'))))); + let confirmBtn: Component = await driver.findComponent(ON.text(await getResourceString(($r('app.string.determine'))))); + await confirmBtn.click(); + await driver.delayMs(1000); + // 打开日历并设置时间 + await driver.assertComponentExist(ON.id('calendar0')); + let calendarComp: Component = await driver.findComponent(ON.id('calendar0')); + await driver.delayMs(1000); + await calendarComp.click(); + await driver.delayMs(1000); + await driver.assertComponentExist(ON.id('calendarTime0')); + let calendarTime: Component = await driver.findComponent(ON.id('calendarTime0')); + await driver.delayMs(1000); + await calendarTime.click(); + await driver.delayMs(1000); + let date = new Date; + // 坐标基于rk3568 + if (date.getMinutes() >= 57) { + await driver.swipe(188, 934, 188, 850, 600); + await driver.delayMs(1000); + } + await driver.swipe(534, 934, 534, 850, 600); + await driver.delayMs(1000); + await driver.swipe(534, 934, 534, 850, 600); + await driver.delayMs(1000); + await driver.swipe(534, 934, 534, 850, 600); + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text(await getResourceString(($r('app.string.determine'))))); + let timeConfirm: Component = await driver.findComponent(ON.text(await getResourceString(($r('app.string.determine'))))); + await driver.delayMs(1000); + await timeConfirm.click(); + await driver.delayMs(1000); + // 打开震动 + await driver.assertComponentExist(ON.id('vibrationSwitch0')); + let vibrationSwitch: Component = await driver.findComponent(ON.id('vibrationSwitch0')); + await driver.delayMs(1000); + await vibrationSwitch.click(); + await driver.delayMs(1000); + // 选择音乐 + await driver.assertComponentExist(ON.id('music0')); + let selectMusic: Component = await driver.findComponent(ON.id('music0')); + await driver.delayMs(1000); + await selectMusic.click(); + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Demo')); + let music: Component = await driver.findComponent(ON.text('Demo')); + await driver.delayMs(1000); + await music.click(); + + await driver.delayMs(1000); + // 完成配置点击确定 + await driver.assertComponentExist(ON.text(await getResourceString(($r('app.string.confirm'))))); + let calendarConfirm: Component = await driver.findComponent(ON.text(await getResourceString(($r('app.string.confirm'))))); + await driver.delayMs(1000); + await calendarConfirm.click(); + await driver.delayMs(1000); + // 开启开关 + await driver.assertComponentExist(ON.id('calendarSwitch0')); + let currentCalendarSwitch: Component = await driver.findComponent(ON.id('calendarSwitch0')); + await driver.delayMs(1000); + await currentCalendarSwitch.click(); + //验证是否在设置的时间之后收到通知 + await driver.delayMs(180000); + // 坐标基于rk3568 + await driver.swipe(180, 0, 180, 50, 600); + await driver.delayMs(1000); + let calendar: Component = await driver.findComponent(ON.text(await getResourceString(($r('app.string.calendar'))))) + await driver.delayMs(1000); + if (!calendar) { + Logger.info(TAG, 'No calendar notifications'); + // 坐标基于rk3568 + await driver.click(207, 1245); + await driver.delayMs(1000); + expect().assertFail(); + } else { + await driver.delayMs(1000); + // 坐标基于rk3568 + await driver.click(207, 1245); + await driver.delayMs(1000); + } + Logger.info(TAG, BUNDLE + 'set end'); + done(); + }); + + /** + * 设置闹钟,用例只支持RK3568 + */ + it('setClock_001', 0, async (done: Function) => { + Logger.info(TAG, BUNDLE + 'setClock_001 begin'); + let driver: Driver = Driver.create(); + await driver.delayMs(5000); + // 点击闹钟 + await driver.assertComponentExist(ON.text(await getResourceString(($r('app.string.alarm_clock'))))); + let clockTab: Component = await driver.findComponent(ON.text(await getResourceString(($r('app.string.alarm_clock'))))); + await driver.delayMs(1000); + await clockTab.click(); + await driver.delayMs(1000); + // 添加时钟并设置时间 + await driver.assertComponentExist(ON.id('addClock')); + let addClock: Component = await driver.findComponent(ON.id('addClock')); + await driver.delayMs(1000); + await addClock.click(); + await driver.delayMs(1000); + // 坐标基于rk3568 + await driver.swipe(522, 934, 522, 850, 600); + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text(await getResourceString($r('app.string.determine')))); + let confirm: Component = await driver.findComponent(ON.text(await getResourceString(($r('app.string.determine'))))); + await driver.delayMs(1000); + await confirm.click(); + await driver.delayMs(1000); + // 打开闹钟开关 + await driver.assertComponentExist(ON.id(`clockSwitch0`)); + let clockSwitch: Component = await driver.findComponent(ON.id(`clockSwitch0`)); + await driver.delayMs(1000); + await clockSwitch.click(); + await driver.delayMs(1000); + // 获取闹钟数据 + let clockData: Reminder[] = await getPerferenceData('alarmClock'); + let lastReminderName: string = clockData[clockData.length-1].reminderName; + // 删除闹钟 + await driver.delayMs(1000); + // 坐标基于rk3568 + await driver.swipe(473, 806, 373, 806, 600); + await driver.delayMs(4000); + // 校验删除 + let clockDataDel: Reminder[] = await getPerferenceData('alarmClock'); + if (clockDataDel !== undefined) { + let isExistName = clockDataDel.find(element => element.reminderName === lastReminderName) !== undefined; + if (isExistName) { + Logger.info(TAG, 'Deleting failed'); + expect().assertFail(); + } else { + Logger.info(TAG, 'Deleting success'); + } + } + // 再次新建一个闹钟 + await addClock.click(); + await driver.delayMs(1000); + let date = new Date; + if (date.getMinutes() >= 56) { + await driver.swipe(188, 934, 188, 850, 600); + await driver.delayMs(1000); + } + // 坐标基于rk3568 + await driver.swipe(522, 934, 522, 850, 600); + await driver.delayMs(1000); + await driver.swipe(522, 934, 522, 850, 600); + await driver.delayMs(1000); + await driver.swipe(522, 934, 522, 850, 600); + await driver.delayMs(1000); + await driver.swipe(522, 934, 522, 850, 600); + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text(await getResourceString($r('app.string.determine')))); + let confirmBtn: Component = await driver.findComponent(ON.text(await getResourceString($r('app.string.determine')))); + await driver.delayMs(1000); + await confirmBtn.click(); + await driver.delayMs(1000); + // 点击时钟,默认点击第一个 + await driver.assertComponentExist(ON.id('clock0')); + let clock: Component = await driver.findComponent(ON.id('clock0')); + await clock.click(); + await driver.delayMs(1000); + // 设置提醒天数默认设置为全周 + for (let i = 0; i < 7; i++) { + await driver.assertComponentExist(ON.id(`day0${i}`)); + let reminderDays: Component = await driver.findComponent(ON.id(`day0${i}`)); + await reminderDays.click(); + } + // 增加间隔次数 + let intervalAdd: Component[] = await driver.findComponents(ON.text('+')); + let intervalDel: Component[] = await driver.findComponents(ON.text('-')); + await driver.assertComponentExist(ON.id('timeCounter')); + let addIntervalTime: Component = intervalAdd[0]; + for (let i = 0; i < 2; i++) { + await addIntervalTime.click(); + } + // 减少间隔次数 + let delIntervalTime: Component = intervalDel[0]; + for (let i = 0; i < 1; i++) { + await delIntervalTime.click(); + } + // 增加间隙 + let addIntervalDuration: Component = intervalAdd[1]; + for (let i = 0; i < 2; i++) { + await addIntervalDuration.click(); + } + // 减少间隔次数 + let delIntervalDuration: Component = intervalDel[1]; + for (let i = 0; i < 1; i++) { + await delIntervalDuration.click(); + } + // 开启震动 + await driver.assertComponentExist(ON.id('vibrationSwitch0')); + let vibrationSwitch: Component = await driver.findComponent(ON.id('vibrationSwitch0')); + await driver.delayMs(1000); + await vibrationSwitch.click(); + // 选择震动音乐 + await driver.assertComponentExist(ON.id('selectMusic0')); + let selectMusic: Component = await driver.findComponent(ON.id('selectMusic0')); + await driver.delayMs(1000); + await selectMusic.click(); + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Demo')); + let music: Component = await driver.findComponent(ON.text('Demo')); + await driver.delayMs(1000); + await music.click(); + await driver.delayMs(1000); + // 完成配置点击确定 + await driver.assertComponentExist(ON.text(await getResourceString(($r('app.string.confirm'))))); + let clockConfirm: Component = await driver.findComponent(ON.text(await getResourceString(($r('app.string.confirm'))))); + await driver.delayMs(1000); + await clockConfirm.click(); + await driver.delayMs(1000); + await driver.assertComponentExist(ON.id(`clockSwitch0`)); + let currentClockSwitch: Component = await driver.findComponent(ON.id(`clockSwitch0`)); + await driver.delayMs(1000); + await currentClockSwitch.click(); + //验证是否在设置的时间之后收到通知 + await driver.delayMs(180000); + // 坐标基于rk3568 + await driver.swipe(180, 0, 180, 50, 600); + await driver.delayMs(1000); + if (!await driver.findComponent(ON.text(await getResourceString($r('app.string.alarm_clock'))))) { + Logger.info(TAG, 'No alarm notifications'); + // 坐标基于rk3568 + await driver.click(207, 1245); + await driver.delayMs(1000); + expect().assertFail(); + } else { + await driver.delayMs(1000); + // 坐标基于rk3568 + await driver.click(207, 1245); + await driver.delayMs(1000); + } + Logger.info(TAG, BUNDLE + 'setClock_001 end'); + done(); + }); + + // 设置计时器,用例只支持RK3568 + it('setCalculagraph_001', 0, async (done: Function) => { + Logger.info(TAG, BUNDLE + 'calculagraph begin'); + let driver: Driver = Driver.create(); + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text(await getResourceString(($r('app.string.timer'))))); + let calculagraphTab: Component = await driver.findComponent(ON.text(await getResourceString(($r('app.string.timer'))))); + await driver.delayMs(1000); + await calculagraphTab.click(); + await driver.delayMs(1000); + // 设置计时器时间 + for (let i = 0; i < 6; i++) { + // 坐标基于rk3568 + await driver.swipe(505, 793, 505, 740, 600); + await driver.delayMs(1000); + } + // 启动计时器 + await driver.assertComponentExist(ON.id('countDown')); + let countDown: Component = await driver.findComponent(ON.id('countDown')); + await driver.assertComponentExist(ON.id('startCalculagraph')); + let startCalculagraph: Component = await driver.findComponent(ON.id('startCalculagraph')); + await driver.delayMs(1000); + await startCalculagraph.click(); + await driver.delayMs(1000); + let timeTime: string = await countDown.getText(); + //验证是否在设置的时间之后收到通知 + await driver.delayMs(9000); + // 坐标基于rk3568 + await driver.swipe(180, 0, 180, 50, 600); + await driver.delayMs(1000); + if (!await driver.findComponent(ON.text(await getResourceString(($r('app.string.timer')))))) { + Logger.info(TAG, 'No calendar notifications'); + // 坐标基于rk3568 + await driver.click(207, 1245); + await driver.delayMs(1000); + expect().assertFail(); + } else { + await driver.delayMs(1000); + // 坐标基于rk3568 + await driver.click(207, 1245); + await driver.delayMs(1000); + } + // 再次设置计时器时间 + for (let i = 0; i < 6; i++) { + // 坐标基于rk3568 + await driver.swipe(505, 793, 505, 740, 600); + await driver.delayMs(1000); + } + await driver.delayMs(1000); + await startCalculagraph.click(); + await driver.delayMs(1000); + timeTime = await countDown.getText(); + await driver.delayMs(1000); + // 暂停 + await startCalculagraph.click(); + await driver.delayMs(1000); + // 重置计时器 + await driver.assertComponentExist(ON.id('resetCalculagraph')); + let resetCalculagraph: Component = await driver.findComponent(ON.id('resetCalculagraph')); + await driver.delayMs(1000); + await resetCalculagraph.click(); + await driver.delayMs(1000); + timeTime = await countDown.getText(); + await driver.delayMs(1000); + if (timeTime !== '00:00:00') { + expect().assertFail(); + } + await driver.delayMs(1000); + Logger.info(TAG, BUNDLE + 'calculagraph end'); + done(); + }); + }) +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/test/List.test.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..5f84f51baa35bb0267b7ea277a127967a9c685f0 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023-2024 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 abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/testability/TestAbility.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/testability/TestAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..79f85dd45de7090eca1802f8e73d3a18c702cf43 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023-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 '@ohos.hilog'; +import UIAbility from '@ohos.app.ability.UIAbility' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' +import { Hypium } from '@ohos/hypium' +import testsuite from '../test/List.test' +import Window from '@ohos.window' +import { AbilityConstant, Want } from '@kit.AbilityKit'; + +export default class TestAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? ''); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + let abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments(); + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + onDestroy() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage: Window.WindowStage) { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); + windowStage.loadContent('testability/pages/Index', (err, data) => { + if (err.code) { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.ERROR); + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/testability/pages/Index.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..392e701ad007dbeee15d2757c28bc0d9c79cc5d1 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 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 '@ohos.hilog'; + +@Entry +@Component +struct Index { + aboutToAppear() { + hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear'); + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/util/Logger.ts b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/util/Logger.ts new file mode 100644 index 0000000000000000000000000000000000000000..2cf5710f6279b4c4e533ed0f608ede3f9978a2a3 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/ets/util/Logger.ts @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 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 '@ohos.hilog'; + +// 日志对应的领域标识,范围是0x0~0xFFFF。 +const DOMAIN: number = 0xF811; + +class Logger { + private prefix: string; + private format: string = '%{public}s, %{public}s'; + + constructor(prefix: string) { + this.prefix = prefix; + } + + debug(...args: string[]): void { + hilog.debug(DOMAIN, this.prefix, this.format, args); + } + + info(...args: string[]): void { + hilog.info(DOMAIN, this.prefix, this.format, args); + } + + warn(...args: string[]): void { + hilog.warn(DOMAIN, this.prefix, this.format, args); + } + + error(...args: string[]): void { + hilog.error(DOMAIN, this.prefix, this.format, args); + } +} + +export default new Logger('[Sample_ReminderAgentManager]'); \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/module.json5 b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..357e92a61a4e220a620dcf99696383710bcc1e42 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/module.json5 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023-2024 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. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "visible": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/resources/base/element/color.json b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/resources/base/element/string.json b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..6aa896b96cc72f5c2697c910a96d0c69fc35e7a8 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,40 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + }, + { + "name": "confirm", + "value": "confirm" + }, + { + "name": "determine", + "value": "determine" + }, + { + "name": "alarm_clock", + "value": "alarm_clock" + }, + { + "name": "calendar", + "value": "calendar" + }, + { + "name": "timer", + "value": "timer" + }, + { + "name": "agree", + "value": "agree" + } + ] +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/resources/base/media/icon.png b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/resources/base/media/icon.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/resources/base/profile/test_pages.json b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/resources/base/profile/test_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..b7e7343cacb32ce982a45e76daad86e435e054fe --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/ohosTest/resources/base/profile/test_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "testability/pages/Index" + ] +} diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/test/List.test.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * 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 localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/entry/src/test/LocalUnit.test.ets b/BackGroundTasksKit/ReminderAgentManager/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * 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 { 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/BackGroundTasksKit/ReminderAgentManager/hvigor/hvigor-config.json5 b/BackGroundTasksKit/ReminderAgentManager/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..72e199c997f119f067902487d02ba7b80fbb1f0f --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/hvigor/hvigor-config.json5 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023-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. + */ + +{ + "modelVersion": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | 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 */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "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*/ + } +} diff --git a/BackGroundTasksKit/ReminderAgentManager/hvigorfile.ts b/BackGroundTasksKit/ReminderAgentManager/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..e3340f07e45ddc5dcadbb87012668555def2e6e0 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * 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 { 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. */ +} \ No newline at end of file diff --git a/BackGroundTasksKit/ReminderAgentManager/oh-package.json5 b/BackGroundTasksKit/ReminderAgentManager/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..dccfe9c3e43735bca57735f5573345a62c54f9fa --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/oh-package.json5 @@ -0,0 +1,25 @@ +/* +* Copyright (C) 2023-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. +*/ + +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.24", + "@ohos/hamock": "1.0.0" + } +} diff --git a/BackGroundTasksKit/ReminderAgentManager/ohosTest.md b/BackGroundTasksKit/ReminderAgentManager/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..30ce95097fda3a90c29f598c31f33286e7657f82 --- /dev/null +++ b/BackGroundTasksKit/ReminderAgentManager/ohosTest.md @@ -0,0 +1,23 @@ +# ReminderAgentManager 测试用例归档 + +## 用例表 + +|测试功能|预置条件|输入|预期输出|测试结果| +|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------| +|拉起应用| 由于对于时间要求比较严谨,此应用需要保证在每小时的1-50分钟之内进行调试| |成功拉起应用|Pass| +|主页按钮点击| 位于主页| 点击创建闹钟提醒|生成一个闹钟数据|Pass| +|主页滑动| 位于主页| 将闹钟数据向左滑动| 删除对应的闹钟 |Pass| +|主页按钮点击| 位于主页| 点击闹钟数据| 显示配置弹窗|Pass| +|主页按钮点击| 位于主页| 点击闹钟配置属性|闹钟属性配置成功|Pass| +|主页滑动| 位于主页| 在主页指定位置向下滑动| 显示闹钟提醒通知 |Pass| +|主页按钮点击| 位于主页| 点击日历|切换到日历|Pass| +|主页按钮点击| 位于主页| 点击创建日历提醒|生成一个日历数据|Pass| +|主页滑动| 位于主页| 将日历数据向左滑动| 删除对应的日历 |Pass| +|主页按钮点击| 位于主页| 点击日历数据| 显示配置弹窗|Pass| +|主页按钮点击| 位于主页| 点击日历配置属性|日历属性配置成功|Pass| +|主页滑动| 位于主页| 在主页指定位置向下滑动| 显示日历提醒 |Pass| +|主页按钮点击| 位于主页| 点击计时器|切换到计时器|Pass| +|主页按钮点击| 位于主页| 点击计时器文本、配置倒计时间|倒计时文本为设置的时间|Pass| +|主页按钮点击| 位于主页| 点击start| 启动倒计时 |Pass| +|主页滑动| 位于主页| 在主页指定位置向下滑动| 显示计时器提醒|Pass| +|主页按钮点击| 位于主页| 点击reset|计时器文本以及canvas初始化|Pass| diff --git a/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/alarm_clock_en.png b/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/alarm_clock_en.png new file mode 100644 index 0000000000000000000000000000000000000000..8019fafa88f9c4b10df7fc0116516a468c236890 Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/alarm_clock_en.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/alarm_clock_zh.png b/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/alarm_clock_zh.png new file mode 100644 index 0000000000000000000000000000000000000000..4c0d95d39df09f4bb08226cc1007b15879c2fcaa Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/alarm_clock_zh.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/calendar_en.png b/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/calendar_en.png new file mode 100644 index 0000000000000000000000000000000000000000..9130f97913c29c81e1ae6dcff66c7e83e7f6682d Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/calendar_en.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/calendar_zh.png b/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/calendar_zh.png new file mode 100644 index 0000000000000000000000000000000000000000..ed5984a54f4c89899f18ee7b3b9faaae86296005 Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/calendar_zh.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/timer_en.png b/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/timer_en.png new file mode 100644 index 0000000000000000000000000000000000000000..91d1c7c0504f7e89e0ba5baf1b07fa35be0a8f81 Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/timer_en.png differ diff --git a/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/timer_zh.png b/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/timer_zh.png new file mode 100644 index 0000000000000000000000000000000000000000..a712ad523f79344034d6ad639e42a0097e4809d5 Binary files /dev/null and b/BackGroundTasksKit/ReminderAgentManager/screenshots/devices/timer_zh.png differ