HarmonyOS Developer 开发指导
后台代理提醒概述
为保障用户体验,HarmonyOS对后台应用进程进行了有序治理,应用程序不能随意驻留在后台,同时应用后台行为受到严格管理,防止恶意应用行为。但对于某些退居后台或已退出的应用,可能需要在指定的时刻,向用户发送一些业务提醒通知。例如购物类应用,希望在指定时间点提醒用户有优惠活动。为满足此类业务诉求,HarmonyOS提供后台代理提醒功能,在应用退居后台或退出后,计时和提醒通知功能被系统后台代理接管。
后台代理提醒业务类型:
- 倒计时类:基于倒计时的提醒功能,适用于短时的计时提醒业务。
- 日历类:基于日历的提醒功能,适用于较长时间的提醒业务。
- 闹钟类:基于时钟的提醒功能,适用于闹钟相关业务。
后台代理提醒开发指导
接口说明
后台代理提醒功能主要提供后台提醒通知发布接口,开发者可调用这些接口创建定时提醒,包括倒计时、日历、闹钟三种提醒类型。reminderAgentManager封装了发布、取消提醒通知的方法。
表1 reminderAgentManager主要接口
接口名 | 描述 |
publishReminder(reminderReq: ReminderRequest, callback: AsyncCallback<number>): void publishReminder(reminderReq: ReminderRequest): Promise<number> | 发布一个定时提醒类通知。 - 单个应用有效的提醒个数最多支持30个(不包括已经超时,即后续不会再提醒的提醒实例)。 - 整个系统有效的提醒个数最多支持2000个(不包括已经超时,即后续不会再提醒的提醒实例)。 |
cancelReminder(reminderId: number, callback: AsyncCallback<void>): void cancelReminder(reminderId: number): Promise<void> | 取消一个指定的提醒类通知(reminderId从publishReminder的返回值获取)。 |
getValidReminders(callback: AsyncCallback<Array<ReminderRequest>>): void getValidReminders(): Promise<Array<ReminderRequest>> | 获取当前应用设置的所有有效的提醒。 |
cancelAllReminders(callback: AsyncCallback<void>): void cancelAllReminders(): Promise<void> | 取消当前应用设置的所有提醒。 |
addNotificationSlot(slot: NotificationSlot, callback: AsyncCallback<void>): void addNotificationSlot(slot: NotificationSlot): Promise<void> | 注册一个提醒类需要使用的NotificationSlot。 |
removeNotificationSlot(slotType: notification.SlotType, callback: AsyncCallback<void>): void removeNotificationSlot(slotType: notification.SlotType): Promise<void> | 删除指定类型的NotificationSlot。 |
开发步骤
- 申请ohos.permission.PUBLISH_AGENT_REMINDER权限,配置方式请参阅访问控制授权申请指导。
- 导入模块。
import reminderAgentManager from '@ohos.reminderAgentManager';
import NotificationManager from '@ohos.notificationManager';
- 定义目标提醒代理。开发者根据实际需要,选择定义如下类型的提醒。
- 定义倒计时实例。
let targetReminderAgent: reminderAgentManager.ReminderRequestTimer = {
reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_TIMER, // 提醒类型为倒计时类型
triggerTimeInSeconds: 10,
actionButton: [ // 设置弹出的提醒通知信息上显示的按钮类型和标题,支持“关闭”和“延迟”两种类型,其中“延迟”按钮类型需要与snoozeTimes和timeInterval参数结合使用
{
title: 'close',
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE
}
],
wantAgent: { // 点击提醒通知后跳转的目标UIAbility信息
pkgName: 'com.example.myapplication',
abilityName: 'EntryAbility'
},
maxScreenWantAgent: { // 全屏显示提醒到达时自动拉起的目标Ability信息
pkgName: 'com.example.myapplication',
abilityName: 'EntryAbility'
},
title: 'this is title', // 指明提醒标题
content: 'this is content', // 指明提醒内容
expiredContent: 'this reminder has expired', // 指明提醒过期后需要显示的内容
notificationId: 100, // 指明提醒使用的通知的ID号,相同ID号的提醒会覆盖
slotType: NotificationManager.SlotType.SOCIAL_COMMUNICATION // 指明提醒的Slot类型
}
- 定义日历实例。
let targetReminderAgent: reminderAgentManager.ReminderRequestCalendar = {
reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_CALENDAR, // 提醒类型为日历类型
dateTime: { // 指明提醒的目标时间
year: 2023,
month: 7,
day: 30,
hour: 11,
minute: 14,
second: 30
},
repeatMonths: [1], // 指明重复提醒的月份
repeatDays: [1], // 指明重复提醒的日期
actionButton: [ // 设置弹出的提醒通知信息上显示的按钮类型和标题,支持“关闭”和“延迟”两种类型,其中“延迟”按钮类型需要与snoozeTimes和timeInterval参数结合使用
{
title: 'close',
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE
},
{
title: 'snooze',
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_SNOOZE
},
],
wantAgent: { // 点击提醒通知后跳转的目标UIAbility信息
pkgName: 'com.example.myapplication',
abilityName: 'EntryAbility'
},
maxScreenWantAgent: { // 点击提醒通知后跳转的目标UIAbility信息
pkgName: 'com.example.myapplication',
abilityName: 'EntryAbility'
},
ringDuration: 5, // 指明响铃时长(单位:秒)
snoozeTimes: 2, // 指明延迟提醒次数
timeInterval: 5, // 执行延迟提醒间隔(单位:秒)
title: 'this is title', // 指明提醒标题
content: 'this is content', // 指明提醒内容
expiredContent: 'this reminder has expired', // 指明提醒过期后需要显示的内容
snoozeContent: 'remind later', // 指明延迟提醒时需要显示的内容
notificationId: 100, // 指明提醒使用的通知的ID号,相同ID号的提醒会覆盖
slotType: NotificationManager.SlotType.SOCIAL_COMMUNICATION // 指明提醒的Slot类型
}
- 定义闹钟实例。
let targetReminderAgent: reminderAgentManager.ReminderRequestAlarm = {
reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_ALARM, // 提醒类型为闹钟类型
hour: 23, // 指明提醒的目标时刻
minute: 9, // 指明提醒的目标分钟
daysOfWeek: [2], // 指明每周哪几天需要重复提醒
actionButton: [ // 设置弹出的提醒通知信息上显示的按钮类型和标题,支持“关闭”和“延迟”两种类型,其中“延迟”按钮类型需要与snoozeTimes和timeInterval参数结合使用
{
title: 'close',
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE
},
{
title: 'snooze',
type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_SNOOZE
},
],
wantAgent: { // 点击提醒通知后跳转的目标UIAbility信息
pkgName: 'com.example.myapplication',
abilityName: 'EntryAbility'
},
maxScreenWantAgent: { // 点击提醒通知后跳转的目标UIAbility信息
pkgName: 'com.example.myapplication',
abilityName: 'EntryAbility'
},
ringDuration: 5, // 指明响铃时长(单位:秒)
snoozeTimes: 2, // 指明延迟提醒次数
timeInterval: 5, // 执行延迟提醒间隔(单位:秒)
title: 'this is title', // 指明提醒标题
content: 'this is content', // 指明提醒内容
expiredContent: 'this reminder has expired', // 指明提醒过期后需要显示的内容
snoozeContent: 'remind later', // 指明延迟提醒时需要显示的内容
notificationId: 99, // 指明提醒使用的通知的ID号,相同ID号的提醒会覆盖
slotType: NotificationManager.SlotType.SOCIAL_COMMUNICATION // 指明提醒的Slot类型
}
- 发布相应的提醒代理。代理发布后,应用即可使用后台代理提醒功能。
try {
reminderAgentManager.publishReminder(targetReminderAgent).then(res => {
console.info('publishReminder promise reminderId: ' + res);
let reminderId: number = res;
// ...
}).catch(err => {
console.info('publishReminder err code: ' + err.code + ' message:' + err.message);
})
} catch (error) {
console.info('publishReminder code: ' + error.code + ' message:' + error.message);
}
以闹钟为例,运行效果如下图所示。
- 若需要删除提醒任务,可以通过调用reminderAgentManager.cancelReminder()方法来实现。
let reminderId = 0; // reminderId的值从发布提醒代理成功之后的回调中获得
try {
reminderAgentManager.cancelReminder(reminderId).then(() => {
console.log("cancelReminder promise");
}).catch(err => {
console.log("promise err code: " + err.code + ", message:" + err.message);
});
} catch (error) {
console.log("cancelReminder code: " + error.code + ", message: " + error.message);
};
USB服务开发概述
基本概念
USB服务是应用访问底层的一种设备抽象概念。开发者根据提供的USB API,可以获取设备列表、控制设备访问权限、以及与连接的设备进行数据传输、控制命令传输等。
运作机制
USB服务系统包含USB API、USB Service、USB HAL。
图1 USB服务运作机制
- USB API:提供USB的基础API,主要包含查询USB设备列表、批量数据传输、控制命令传输、权限控制等。
- USB Service:主要实现HAL层数据的接收、解析、分发,前后台的策略管控以及对设备的管理等。
- USB HAL层:提供给用户态可直接调用的驱动能力接口。
USB服务开发指导
场景介绍
Host模式下,可以获取到已经连接的USB设备列表,并根据需要打开和关闭设备、控制设备权限、进行数据传输等。
接口说明
USB服务主要提供的功能有:查询USB设备列表、批量数据传输、控制命令传输、权限控制等。
USB类开放能力如下,具体请查阅API参考文档。
表1 USB类的开放能力接口
接口名 | 描述 |
hasRight(deviceName: string): boolean | 判断是否有权访问该设备。 |
requestRight(deviceName: string): Promise<boolean> | 请求软件包的临时权限以访问设备。 |
connectDevice(device: USBDevice): Readonly<USBDevicePipe> | 根据getDevices()返回的设备信息打开USB设备。 |
getDevices(): Array<Readonly<USBDevice>> | 获取接入主设备的USB设备列表。 如果没有设备接入,那么将会返回一个空的列表。 |
setConfiguration(pipe: USBDevicePipe, config: USBConfig): number | 设置设备的配置。 |
setInterface(pipe: USBDevicePipe, iface: USBInterface): number | 设置设备的接口。 |
claimInterface(pipe: USBDevicePipe, iface: USBInterface,force?: boolean): number | 注册通信接口。 |
bulkTransfer(pipe: USBDevicePipe, endpoint: USBEndpoint, buffer: Uint8Array, timeout?: number): Promise<number> | 批量传输。 |
closePipe(pipe: USBDevicePipe): number | 关闭设备消息控制通道。 |
releaseInterface(pipe: USBDevicePipe, iface: USBInterface): number | 释放注册过的通信接口。 |
getFileDescriptor(pipe: USBDevicePipe): number | 获取文件描述符。 |
getRawDescriptor(pipe: USBDevicePipe): Uint8Array | 获取原始的USB描述符。 |
controlTransfer(pipe: USBDevicePipe, contrlparam: USBControlParams, timeout?: number): Promise<number> | 控制传输。 |
开发步骤
USB设备可作为Host设备连接Device设备进行数据传输。开发示例如下:
- 获取设备列表。
// 导入USB接口api包。
import usb from '@ohos.usbV9';
// 获取设备列表。
let deviceList = usb.getDevices();
/*
deviceList结构示例
[
{
name: "1-1",
serial: "",
manufacturerName: "",
productName: "",
version: "",
vendorId: 7531,
productId: 2,
clazz: 9,
subclass: 0,
protocol: 1,
devAddress: 1,
busNum: 1,
configs: [
{
id: 1,
attributes: 224,
isRemoteWakeup: true,
isSelfPowered: true,
maxPower: 0,
name: "1-1",
interfaces: [
{
id: 0,
protocol: 0,
clazz: 9,
subclass: 0,
alternateSetting: 0,
name: "1-1",
endpoints: [
{
address: 129,
attributes: 3,
interval: 12,
maxPacketSize: 4,
direction: 128,
number: 1,
type: 3,
interfaceId: 0,
}
]
}
]
}
]
}
]
*/
- 获取设备操作权限。
let deviceName = deviceList[0].name;
// 申请操作指定的device的操作权限。
usb.requestRight(deviceName).then(hasRight => {
console.info("usb device request right result: " + hasRight);
}).catch(error => {
console.info("usb device request right failed : " + error);
});
- 打开Device设备。
// 打开设备,获取数据传输通道。
let pipe = usb.connectDevice(deviceList[0]);
/*
打开对应接口,在设备信息(deviceList)中选取对应的interface。
interface1为设备配置中的一个接口。
*/
usb.claimInterface(pipe, interface1, true);
- 数据传输。
/*
读取数据,在device信息中选取对应数据接收的endpoint来做数据传输
(endpoint.direction == 0x80);dataUint8Array是要读取的数据,类型为Uint8Array。
*/
usb.bulkTransfer(pipe, inEndpoint, dataUint8Array, 15000).then(dataLength => {
if (dataLength >= 0) {
console.info("usb readData result Length : " + dataLength);
let resultStr = this.ab2str(dataUint8Array); // uint8数据转string。
console.info("usb readData buffer : " + resultStr);
} else {
console.info("usb readData failed : " + dataLength);
}
}).catch(error => {
console.info("usb readData error : " + JSON.stringify(error));
});
// 发送数据,在device信息中选取对应数据发送的endpoint来做数据传输。(endpoint.direction == 0)
usb.bulkTransfer(pipe, endpoint, dataUint8Array, 15000).then(dataLength => {
if (dataLength >= 0) {
console.info("usb writeData result write length : " + dataLength);
} else {
console.info("writeData failed");
}
}).catch(error => {
console.info("usb writeData error : " + JSON.stringify(error));
});
- 释放接口,关闭设备。
usb.releaseInterface(pipe, interface1);
usb.closePipe(pipe);
传感器开发概述
HarmonyOS系统传感器是应用访问底层硬件传感器的一种设备抽象概念。开发者根据传感器提供的Sensor接口,可以查询设备上的传感器,订阅传感器数据,并根据传感器数据定制相应的算法开发各类应用,比如指南针、运动健康、游戏等。
传感器类型 | 描述 | 说明 | 主要用途 |
ACCELEROMETER | 加速度传感器 | 测量三个物理轴(x、y 和 z)上,施加在设备上的加速度(包括重力加速度),单位 : m/s² | 检测运动状态 |
ACCELEROMETER_UNCALIBRATED | 未校准加速度传感器 | 测量三个物理轴(x、y 和 z)上,施加在设备上的未校准的加速度(包括重力加速度),单位 : m/s² | 检测加速度偏差估值 |
LINEAR_ACCELERATION | 线性加速度传感器 | 测量三个物理轴(x、y 和 z)上,施加在设备上的线性加速度(不包括重力加速度),单位 : m/s² | 检测每个单轴方向上的线性加速度 |
GRAVITY | 重力传感器 | 测量三个物理轴(x、y 和 z)上,施加在设备上的重力加速度,单位 : m/s² | 测量重力大小 |
GYROSCOPE | 陀螺仪传感器 | 测量三个物理轴(x、y 和 z)上,设备的旋转角速度,单位 : rad/s | 测量旋转的角速度 |
GYROSCOPE_UNCALIBRATED | 未校准陀螺仪传感器 | 测量三个物理轴(x、y 和 z)上,设备的未校准旋转角速度,单位 : rad/s | 测量旋转的角速度及偏差估值 |
SIGNIFICANT_MOTION | 大幅度动作传感器 | 测量三个物理轴(x、y 和 z)上,设备是否存在大幅度运动;如果取值为1则代表存在大幅度运动,取值为0则代表没有大幅度运动 | 用于检测设备是否存在大幅度运动 |
PEDOMETER_DETECTION | 计步器检测传感器 | 检测用户的计步动作;如果取值为1则代表用户产生了计步行走的动作;取值为0则代表用户没有发生运动 | 用于检测用户是否有计步的动作 |
PEDOMETER | 计步器传感器 | 统计用户的行走步数 | 用于提供用户行走的步数数据 |
AMBIENT_TEMPERATURE | 环境温度传感器 | 测量环境温度,单位 : 摄氏度 (°C) | 测量环境温度 |
MAGNETIC_FIELD | 磁场传感器 | 测量三个物理轴向(x、y、z)上,环境地磁场,单位 : μT | 创建指南针 |
MAGNETIC_FIELD_UNCALIBRATED | 未校准磁场传感器 | 测量三个物理轴向(x、y、z)上,未校准环境地磁场,单位 : μT | 测量地磁偏差估值 |
HUMIDITY | 湿度传感器 | 测量环境的相对湿度,以百分比 (%) 表示 | 监测露点、绝对湿度和相对湿度 |
BAROMETER | 气压计传感器 | 测量环境气压,单位 : hPa 或 mbar | 测量环境气压 |
ORIENTATION | 方向传感器 | 测量设备围绕所有三个物理轴(x、y、z)旋转的角度值,单位:rad | 用于提供屏幕旋转的3个角度值 |
ROTATION_VECTOR | 旋转矢量传感器 | 测量设备旋转矢量,复合传感器:由加速度传感器、磁场传感器、陀螺仪传感器合成 | 检测设备相对于东北天坐标系的方向 |
PROXIMITY | 接近光传感器 | 测量可见物体相对于设备显示屏的接近或远离状态 | 通话中设备相对人的位置 |
AMBIENT_LIGHT | 环境光传感器 | 测量设备周围光线强度,单位:lux | 自动调节屏幕亮度,检测屏幕上方是否有遮挡 |
HEART_RATE | 心率传感器 | 测量用户的心率数值 | 用于提供用户的心率健康数据 |
WEAR_DETECTION | 佩戴检测传感器 | 检测用户是否佩戴 | 用于检测用户是否佩戴智能穿戴 |
HALL | 霍尔传感器 | 测量设备周围是否存在磁力吸引 | 设备的皮套模式 |
运作机制
HarmonyOS传感器包含如下四个模块:Sensor API、Sensor Framework、Sensor Service和HDF层。
图1 HarmonyOS传感器
- Sensor API:提供传感器的基础API,主要包含查询传感器列表,订阅/取消传感器的数据、执行控制命令等,简化应用开发。
- Sensor Framework:主要实现传感器的订阅管理,数据通道的创建、销毁、订阅与取消订阅,实现与SensorService的通信。
- Sensor Service:主要实现HD_IDL层数据接收、解析、分发,前后台的策略管控,对该设备Sensor的管理,Sensor权限管控等。
- HDF层:对不同的FIFO、频率进行策略选择,以及适配不同设备。
约束与限制
- 针对下面所列传感器,开发者需要请求响应的权限,才能获取到相应传感器的数据。
传感器 | 权限名 | 敏感级别 | 权限描述 |
加速度传感器,加速度未校准传感器,线性加速度传感器 | ohos.permission.ACCELEROMETER | system_grant | 允许订阅Motion组对应的加速度传感器的数据 |
陀螺仪传感器,陀螺仪未校准传感器 | ohos.permission.GYROSCOPE | system_grant | 允许订阅Motion组对应的陀螺仪传感器的数据 |
计步器 | ohos.permission.ACTIVITY_MOTION | user_grant | 允许订阅运动状态 |
心率计 | ohos.permission.READ_HEALTH_DATA | user_grant | 允许读取健康数据 |
- 传感器数据订阅和取消订阅接口成对调用,当不再需要订阅传感器数据时,开发者需要调用取消订阅接口停止数据上报。
传感器开发指导
场景介绍
当设备需要获取传感器数据时,可以使用sensor模块,例如:通过订阅方向传感器数据感知用户设备当前的朝向,通过订阅计步传感器数据统计用户的步数等。
详细的接口介绍请参考Sensor接口。
接口说明
模块 | 接口名 | 描述 |
ohos.sensor | sensor.on(sensorId, callback:AsyncCallback<Response>): void | 持续监听传感器数据变化 |
ohos.sensor | sensor.once(sensorId, callback:AsyncCallback<Response>): void | 获取一次传感器数据变化 |
ohos.sensor | sensor.off(sensorId, callback?:AsyncCallback<void>): void | 注销传感器数据的监听 |
开发步骤
- 获取设备上传感器的数据前,需要检查是否已经配置请求相应的权限。
系统提供的传感器权限有:
- ohos.permission.ACCELEROMETER
- ohos.permission.GYROSCOPE
- ohos.permission.ACTIVITY_MOTION
- ohos.permission.READ_HEALTH_DATA
具体配置方式请参考权限申请声明。
- 以下场景以加速度传感器ACCELEROMETER为例。展示持续监听传感器接口的调用结果。
import sensor from "@ohos.sensor";
sensor.on(sensor.SensorId.ACCELEROMETER, function(data){
console.info("Data obtained successfully. x: " + data.x + "y: " + data.y + "z: " + data.z);// 获取数据成功
});
- 注销传感器数据监听。
import sensor from "@ohos.sensor";
sensor.off(sensor.SensorId.ACCELEROMETER);
- 获取一次传感器数据变化。
import sensor from "@ohos.sensor";
sensor.once(sensor.SensorId.ACCELEROMETER, function(data) {
console.info("Data obtained successfully. x: " + data.x + "y: " + data.y + "z: " + data.z);// 获取数据成功
});
若接口调用不成功,建议使用try/catch语句捕获代码中可能出现的错误信息。例如:
import sensor from "@ohos.sensor";
try {
sensor.once(sensor.SensorId.ACCELEROMETER, function(data) {
console.info("Data obtained successfully. x: " + data.x + "y: " + data.y + "z: " + data.z);// 获取数据成功
});
} catch (error) {
console.error("Get sensor data error. data:" + error.data, " msg:", error.message);
}