HarmonyOS Developer 开发指导

丶龙八夷
发布于 2023-3-31 16:38
浏览
0收藏

后台代理提醒概述

为保障用户体验,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。

开发步骤

  1. 申请ohos.permission.PUBLISH_AGENT_REMINDER权限,配置方式请参阅​​访问控制授权申请指导​​。
  2. 导入模块。

import reminderAgentManager from '@ohos.reminderAgentManager';
import NotificationManager from '@ohos.notificationManager';
  1. 定义目标提醒代理。开发者根据实际需要,选择定义如下类型的提醒。
  • 定义倒计时实例。

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类型
}
  1. 发布相应的提醒代理。代理发布后,应用即可使用后台代理提醒功能。

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);
}

以闹钟为例,运行效果如下图所示。

HarmonyOS Developer 开发指导-鸿蒙开发者社区

  1. 若需要删除提醒任务,可以通过调用​​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服务运作机制

HarmonyOS Developer 开发指导-鸿蒙开发者社区

  • 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设备进行数据传输。开发示例如下:

  1. 获取设备列表。

// 导入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,
              }
            ]
          }
        ]
      }
    ]
  }
]
*/
  1. 获取设备操作权限。

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);
});
  1. 打开Device设备。

// 打开设备,获取数据传输通道。
let pipe = usb.connectDevice(deviceList[0]);
/*
 打开对应接口,在设备信息(deviceList)中选取对应的interface。
interface1为设备配置中的一个接口。
*/
usb.claimInterface(pipe, interface1, true); 
  1. 数据传输。

/*
 读取数据,在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));
});
  1. 释放接口,关闭设备。

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传感器

HarmonyOS Developer 开发指导-鸿蒙开发者社区

  • Sensor API:提供传感器的基础API,主要包含查询传感器列表,订阅/取消传感器的数据、执行控制命令等,简化应用开发。
  • Sensor Framework:主要实现传感器的订阅管理,数据通道的创建、销毁、订阅与取消订阅,实现与SensorService的通信。
  • Sensor Service:主要实现HD_IDL层数据接收、解析、分发,前后台的策略管控,对该设备Sensor的管理,Sensor权限管控等。
  • HDF层:对不同的FIFO、频率进行策略选择,以及适配不同设备。

约束与限制

  1. 针对下面所列传感器,开发者需要请求响应的权限,才能获取到相应传感器的数据。

传感器

权限名

敏感级别

权限描述

加速度传感器,加速度未校准传感器,线性加速度传感器

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

允许读取健康数据

  1. 传感器数据订阅和取消订阅接口成对调用,当不再需要订阅传感器数据时,开发者需要调用取消订阅接口停止数据上报。

传感器开发指导

场景介绍

当设备需要获取传感器数据时,可以使用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

注销传感器数据的监听

开发步骤

  1. 获取设备上传感器的数据前,需要检查是否已经配置请求相应的权限。
    系统提供的传感器权限有:
  • ohos.permission.ACCELEROMETER
  • ohos.permission.GYROSCOPE
  • ohos.permission.ACTIVITY_MOTION
  • ohos.permission.READ_HEALTH_DATA

具体配置方式请参考​​权限申请声明​​。

  1. 以下场景以加速度传感器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);// 获取数据成功
});

HarmonyOS Developer 开发指导-鸿蒙开发者社区

  1. 注销传感器数据监听。

import sensor from "@ohos.sensor";
sensor.off(sensor.SensorId.ACCELEROMETER);

HarmonyOS Developer 开发指导-鸿蒙开发者社区

  1. 获取一次传感器数据变化。

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);// 获取数据成功
});

HarmonyOS Developer 开发指导-鸿蒙开发者社区

若接口调用不成功,建议使用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);
}




文章转载自:​​https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/sensor-guidelines-0000001478341041-V3​

标签
已于2023-3-31 16:38:44修改
收藏
回复
举报
回复