鸿蒙多功能工具箱开发实战(三十)-推送通知与消息处理

AI7小时前发布 beixibaobao
3 0 0

鸿蒙多功能工具箱开发实战(三十)-推送通知与消息处理

前言

推送通知是保持用户活跃度的重要手段。本文将讲解HarmonyOS应用的推送通知实现和消息处理机制。

一、通知基础

1.1 通知权限配置

module.json5 中添加权限:

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.NOTIFICATION_CONTROLLER"
      }
    ]
  }
}

1.2 通知服务封装

import notification from '@ohos.notification'
import notificationManager from '@ohos.notificationManager'
import wantAgent from '@ohos.app.ability.wantAgent'
export class NotificationService {
  private static instance: NotificationService
  private constructor() {}
  static getInstance(): NotificationService {
    if (!NotificationService.instance) {
      NotificationService.instance = new NotificationService()
    }
    return NotificationService.instance
  }
  /**
   * 发送本地通知
   */
  async showNotification(params: {
    title: string
    content: string
    icon?: Resource
    clickAction?: () => void
  }): Promise<void> {
    // 创建WantAgent用于点击跳转
    let wantAgentInfo: wantAgent.WantAgentInfo = {
      wants: [
        {
          bundleName: 'com.example.harmonytoolbox',
          abilityName: 'EntryAbility'
        }
      ],
      requestCode: 0,
      operationType: wantAgent.OperationType.START_ABILITY,
      wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
    }
    const agent = await wantAgent.getWantAgent(wantAgentInfo)
    // 构建通知内容
    const notificationRequest: notification.NotificationRequest = {
      id: Date.now(),
      content: {
        contentType: notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
        normal: {
          title: params.title,
          text: params.content
        }
      },
      wantAgent: agent
    }
    // 发布通知
    await notificationManager.publish(notificationRequest)
  }
  /**
   * 发送带图片的通知
   */
  async showImageNotification(params: {
    title: string
    content: string
    image: Resource
  }): Promise<void> {
    const notificationRequest: notification.NotificationRequest = {
      id: Date.now(),
      content: {
        contentType: notification.ContentType.NOTIFICATION_CONTENT_PICTURE,
        picture: {
          title: params.title,
          text: params.content,
          picture: params.image
        }
      }
    }
    await notificationManager.publish(notificationRequest)
  }
  /**
   * 取消通知
   */
  async cancel(notificationId: number): Promise<void> {
    await notificationManager.cancel(notificationId)
  }
  /**
   * 取消所有通知
   */
  async cancelAll(): Promise<void> {
    await notificationManager.cancelAll()
  }
}

二、定时通知

2.1 定时提醒

import reminderAgentManager from '@ohos.reminderAgentManager'
export class ReminderService {
  /**
   * 设置每日提醒
   */
  static async setDailyReminder(params: {
    hour: number
    minute: number
    title: string
    content: string
  }): Promise<number> {
    const reminderRequest: reminderAgentManager.ReminderRequestCalendar = {
      reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_CALENDAR,
      dateTime: {
        year: 0,  // 0表示重复
        month: 0,
        day: 0,
        hour: params.hour,
        minute: params.minute
      },
      repeatMonths: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
      repeatDays: [1, 2, 3, 4, 5, 6, 7],  // 每天重复
      title: params.title,
      content: params.content
    }
    return await reminderAgentManager.publishReminder(reminderRequest)
  }
  /**
   * 设置一次性提醒
   */
  static async setOneTimeReminder(params: {
    timestamp: number
    title: string
    content: string
  }): Promise<number> {
    const date = new Date(params.timestamp)
    const reminderRequest: reminderAgentManager.ReminderRequestCalendar = {
      reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_CALENDAR,
      dateTime: {
        year: date.getFullYear(),
        month: date.getMonth() + 1,
        day: date.getDate(),
        hour: date.getHours(),
        minute: date.getMinutes()
      },
      title: params.title,
      content: params.content
    }
    return await reminderAgentManager.publishReminder(reminderRequest)
  }
  /**
   * 取消提醒
   */
  static async cancelReminder(reminderId: number): Promise<void> {
    await reminderAgentManager.cancelReminder(reminderId)
  }
  /**
   * 获取所有有效提醒
   */
  static async getAllValidReminders(): Promise<Array<reminderAgentManager.ReminderRequest>> {
    return await reminderAgentManager.getValidReminders()
  }
}

三、推送消息处理

3.1 推送消息接收

import pushService from '@ohos.pushService'
export class PushMessageHandler {
  private static instance: PushMessageHandler
  static getInstance(): PushMessageHandler {
    if (!PushMessageHandler.instance) {
      PushMessageHandler.instance = new PushMessageHandler()
    }
    return PushMessageHandler.instance
  }
  /**
   * 初始化推送
   */
  async init(): Promise<void> {
    // 注册推送服务
    await this.registerPush()
    // 监听推送消息
    this.listenPushMessage()
  }
  /**
   * 注册推送
   */
  private async registerPush(): Promise<string> {
    try {
      const pushToken = await pushService.getToken()
      console.info('Push token:', pushToken)
      // 上报token到服务器
      await this.reportToken(pushToken)
      return pushToken
    } catch (e) {
      console.error('Register push failed:', e)
      throw e
    }
  }
  /**
   * 监听推送消息
   */
  private listenPushMessage(): void {
    pushService.on('pushMessage', (message) => {
      this.handlePushMessage(message)
    })
  }
  /**
   * 处理推送消息
   */
  private handlePushMessage(message: any): void {
    console.info('Received push message:', message)
    // 解析消息内容
    const { type, data } = message
    switch (type) {
      case 'notification':
        this.showNotificationFromPush(data)
        break
      case 'update':
        this.handleUpdateMessage(data)
        break
      case 'promotion':
        this.handlePromotionMessage(data)
        break
      default:
        console.warn('Unknown message type:', type)
    }
  }
  private async showNotificationFromPush(data: any): Promise<void> {
    await NotificationService.getInstance().showNotification({
      title: data.title,
      content: data.content
    })
  }
  private handleUpdateMessage(data: any): void {
    // 处理更新消息
  }
  private handlePromotionMessage(data: any): void {
    // 处理推广消息
  }
  private async reportToken(token: string): Promise<void> {
    const http = HttpService.getInstance()
    await http.post('https://api.example.com/push/register', { token })
  }
}

3.2 消息分类处理

export interface PushMessage {
  id: string
  type: 'notification' | 'update' | 'promotion' | 'system'
  title: string
  content: string
  data?: Record<string, any>
  timestamp: number
  read: boolean
}
export class MessageManager {
  private static messages: PushMessage[] = []
  /**
   * 添加消息
   */
  static addMessage(message: PushMessage): void {
    this.messages.unshift(message)
    this.saveMessages()
  }
  /**
   * 获取消息列表
   */
  static getMessages(type?: string): PushMessage[] {
    if (type) {
      return this.messages.filter(m => m.type === type)
    }
    return this.messages
  }
  /**
   * 获取未读数量
   */
  static getUnreadCount(): number {
    return this.messages.filter(m => !m.read).length
  }
  /**
   * 标记已读
   */
  static markAsRead(messageId: string): void {
    const message = this.messages.find(m => m.id === messageId)
    if (message) {
      message.read = true
      this.saveMessages()
    }
  }
  /**
   * 全部标记已读
   */
  static markAllAsRead(): void {
    this.messages.forEach(m => m.read = true)
    this.saveMessages()
  }
  /**
   * 删除消息
   */
  static deleteMessage(messageId: string): void {
    this.messages = this.messages.filter(m => m.id !== messageId)
    this.saveMessages()
  }
  private static async saveMessages(): Promise<void> {
    const prefs = await PreferencesService.getInstance()
    await prefs.put('push_messages', JSON.stringify(this.messages))
  }
  static async loadMessages(): Promise<void> {
    const prefs = await PreferencesService.getInstance()
    const data = await prefs.get('push_messages', '[]') as string
    this.messages = JSON.parse(data)
  }
}

四、消息中心界面

@Entry
@Component
struct MessageCenterPage {
  @State messages: PushMessage[] = []
  @State currentType: string = 'all'
  async aboutToAppear() {
    await MessageManager.loadMessages()
    this.messages = MessageManager.getMessages()
  }
  build() {
    Column() {
      NavBar({ title: '消息中心' })
      // 类型筛选
      Row() {
        this.TypeTab('全部', 'all')
        this.TypeTab('通知', 'notification')
        this.TypeTab('系统', 'system')
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceAround)
      // 消息列表
      List() {
        ForEach(this.getFilteredMessages(), (message: PushMessage) => {
          ListItem() {
            this.MessageItem(message)
          }
        })
      }
      .width('100%')
      .layoutWeight(1)
    }
  }
  @Builder
  TypeTab(label: string, type: string) {
    Text(label)
      .fontSize(14)
      .fontColor(this.currentType === type ? '#4A90E2' : '#999999')
      .onClick(() => {
        this.currentType = type
      })
  }
  @Builder
  MessageItem(message: PushMessage) {
    Row() {
      // 未读标记
      if (!message.read) {
        Circle()
          .width(8)
          .height(8)
          .fill('#E74C3C')
      }
      Column() {
        Text(message.title)
          .fontSize(16)
          .fontWeight(message.read ? FontWeight.Normal : FontWeight.Bold)
        Text(message.content)
          .fontSize(12)
          .fontColor('#999999')
          .margin({ top: 4 })
          .maxLines(2)
        Text(this.formatTime(message.timestamp))
          .fontSize(10)
          .fontColor('#CCCCCC')
          .margin({ top: 4 })
      }
      .layoutWeight(1)
      .alignItems(HorizontalAlign.Start)
      .margin({ left: 8 })
    }
    .width('100%')
    .padding(16)
    .onClick(() => {
      MessageManager.markAsRead(message.id)
      this.messages = [...MessageManager.getMessages()]
    })
  }
  private getFilteredMessages(): PushMessage[] {
    if (this.currentType === 'all') {
      return this.messages
    }
    return this.messages.filter(m => m.type === this.currentType)
  }
  private formatTime(timestamp: number): string {
    const date = new Date(timestamp)
    return `${date.getMonth() + 1}/${date.getDate()}${date.getHours()}:${date.getMinutes()}`
  }
}

五、高级推送功能

5.1 推送流程图

服务端推送

Push Kit接收

应用处理

应用在前台?

直接显示

系统通知

用户交互

5.2 富媒体通知

class RichNotification {
  static async show(data: RichNotificationData) {
    await notificationManager.publish({
      id: data.id,
      title: data.title,
      text: data.text,
      largeIcon: data.image,  // 大图
      additionalText: data.summary
    })
  }
}

5.3 通知渠道

// 创建通知渠道
async function createChannel() {
  await notificationManager.addSlot({
    type: notificationManager.SlotType.SOCIAL_COMMUNICATION,
    level: notificationManager.SlotLevel.LEVEL_HIGH,
    desc: '重要消息通知'
  })
}

图 1 实时金价页面订阅提醒

在这里插入图片描述

六、小结

本文详细讲解了推送通知:

  1. ✅ 通知服务封装
  2. ✅ 定时提醒
  3. ✅ 推送消息处理
  4. ✅ 消息分类管理
  5. ✅ 消息中心界面
  6. ✅ 富媒体通知
  7. ✅ 通知渠道

系列文章导航
下期预告:鸿蒙多功能工具箱开发实战(三十一)-小组件开发

© 版权声明

相关文章