Skip to content

通知系统(Notification)

1. 通知系统架构

通知系统架构:
┌─────────────────────────────────────────────┐
│  应用层                                     │
│  └── 构建 Notification                      │
├─────────────────────────────────────────────┤
│  Notification Manager                        │
│  ├── 通知渠道管理                            │
│  ├── 通知分类/优先级                         │
│  └── 通知聚合/折叠                           │
├─────────────────────────────────────────────┤
│  Notification Service                        │
│  ├── 状态栏通知(StatusBar)                  │
│  ├── 横幅通知(Banner)                      │
│  ├── 锁屏通知                                │
│  └── 媒体通知                                │
├─────────────────────────────────────────────┤
│  分发层                                      │
│  ├── 本地通知(推送)                        │
│  └── 远程通知(Push Kit)                    │
└─────────────────────────────────────────────┘

2. 通知类型

类型说明展示位置
普通通知文本+图片+按钮状态栏 + 通知抽屉
横幅通知弹窗式通知,自动消失屏幕顶部浮动
大通知可展开的详细通知状态栏 + 通知抽屉
媒体通知音乐播放控制媒体中心
进度通知显示下载/上传进度状态栏
远程通知通过 Push Kit 推送状态栏 + 通知抽屉
表单通知卡片式通知(Form)桌面/锁屏

3. 通知构建与发送

3.1 本地通知

arkts
import { notification } from '@kit.BasicServicesKit';

// 1. 创建通知渠道(Android 10+ 必需)
const channelId = 'my_channel';
const channel: notification.NotificationChannel = {
  name: '重要通知',
  channelDescription: '用于重要事件的通知渠道',
  importance: notification.Importance.IMPORTANCE_HIGH, // 高重要性
  enableLights: true,
  lightColor: '#FF0000',
  lockscreenVisibility: notification.LockscreenVisibility.VISIBILITY_PUBLIC,
};

// 创建通知渠道
await notification.createNotificationChannel(channelId, channel);

// 2. 构建通知内容
const template: notification.NotificationContent = {
  normal: {
    title: '新消息',
    text: '您有一条新消息,点击查看',
    extraInfo: 'extra info',
    normalExtracInfo: {
      clickIntent: {
        parameters: {
          url: 'https://example.com'
        }
      },
      action: notification.Action.ACTION_TYPE_CLICK,
    }
  },
  large: {
    title: '新消息详情',
    largePicPath: '/data/user/0/com.example/files/image.jpg',
    largeText: '这是一条很长的通知内容,用于展示详细信息。'
  }
};

// 3. 创建并发送通知
const request: notification.Request = {
  content: template,
  id: 1001,
  channelId: channelId,
  normal: {
    advancedNormalContent: {
      clickIntent: {
        parameters: { url: 'https://example.com' },
        action: notification.Action.ACTION_TYPE_CLICK
      }
    }
  }
};

await notification.publishNotification(request);

3.2 横幅通知(Banner)

arkts
import { banner } from '@kit.BasicServicesKit';

// 创建横幅通知
const bannerRequest: banner.Request = {
  bannerType: banner.BannerType.NORMAL,
  template: {
    title: '提示',
    text: '这是一条横幅通知'
  },
  action: {
    clickIntent: {
      parameters: { type: 'banner_click' },
      action: banner.Action.ACTION_TYPE_CLICK
    }
  }
};

const bannerId = await banner.publish(bannerRequest);

// 自动消失(3 秒后)
setTimeout(async () => {
  await banner.cancel(bannerId);
}, 3000);

3.3 进度通知

arkts
import { notification } from '@kit.BasicServicesKit';

// 进度通知(下载/上传)
const progressRequest: notification.Request = {
  content: {
    normal: {
      title: '文件下载中',
      text: '正在下载...',
      normalExtracInfo: {
        clickIntent: {
          parameters: { url: 'detail' },
          action: notification.Action.ACTION_TYPE_CLICK
        }
      }
    }
  },
  id: 2001,
  channelId: 'download_channel',
  normal: {
    progress: {
      max: 100,
      current: 50,
      style: notification.ProgressStyle.PROGRESS_STYLE_INDETERMINATE
    }
  }
};

// 更新进度
const updateRequest: notification.Request = {
  content: progressRequest.content,
  id: progressRequest.id,
  channelId: progressRequest.channelId,
  normal: {
    progress: {
      max: 100,
      current: 75, // 更新进度
      style: notification.ProgressStyle.PROGRESS_STYLE_NORMAL
    }
  }
};

await notification.updateNotification(updateRequest);

4. 通知渠道管理

4.1 渠道概念

通知渠道(Notification Channel):
├── 应用可以创建多个渠道,每个渠道代表一类通知
├── 用户可以独立设置每个渠道的行为
├── 渠道一旦创建,只能修改不可见性(重要性和可关闭性)
├── 不同渠道可以有不同的重要性级别
└── 用户关闭渠道后,该渠道通知不再展示

4.2 渠道配置

arkts
import { notification } from '@kit.BasicServicesKit';

// 重要性级别(从高到低)
const IMPORTANCE_LEVELS = {
  MAX:       notification.Importance.MAX,     // 震动 + 响铃 + 横幅
  HIGH:      notification.Importance.HIGH,    // 响铃 + 横幅
  NORMAL:    notification.Importance.NORMAL,  // 横幅
  LOW:       notification.Importance.LOW,     // 仅状态栏
  MIN:       notification.Importance.MIN,     // 不展示(仅通知抽屉)
};

// 创建多个渠道
const channels: notification.NotificationChannel[] = [
  {
    name: '消息通知',
    channelDescription: '消息相关通知',
    importance: notification.Importance.HIGH,
    enableVibration: true,
    lockscreenVisibility: notification.LockscreenVisibility.VISIBILITY_PUBLIC,
  },
  {
    name: '系统通知',
    channelDescription: '系统相关通知',
    importance: notification.Importance.NORMAL,
    lockscreenVisibility: notification.LockscreenVisibility.VISIBILITY_PRIVATE,
  },
  {
    name: '推广通知',
    channelDescription: '营销推广通知',
    importance: notification.Importance.LOW,
    lockscreenVisibility: notification.LockscreenVisibility.VISIBILITY_SECRET,
  }
];

for (const channel of channels) {
  await notification.createNotificationChannel('channel_' + channel.name, channel);
}

5. 远程通知(Push Kit)

5.1 Push Kit 架构

Push Kit 推送流程:
┌──────────┐     ┌──────────┐     ┌──────────┐     ┌──────────┐
│ 服务端    │─────│ Agconnect │─────│ 推送服务  │─────│ 设备端   │
│  (APNs)  │     │ (AGC)    │     │ (HMS/Push)│     │ (App)    │
└──────────┘     └──────────┘     └──────────┘     └──────────┘
     │                │                │                │
     └──────── 云端消息通道 ──────────────┘

5.2 Push Kit 配置

arkts
// 1. 在 module.json5 中声明权限
{
  "reqPermissions": [
    {
      "name": "ohos.permission.INTERNET"
    }
  ]
}

// 2. 初始化 Push Kit
import { push } from '@kit.PushKit';

async function initPush() {
  // 获取推送 Token
  const token = await push.getToken();
  console.log('Push Token: ' + token);

  // 监听 Token 刷新
  push.on('token', (newToken: string) => {
    console.log('Token refreshed: ' + newToken);
  });

  // 监听消息(App 在前台时)
  push.on('message', (msg: push.PushMessage) => {
    if (msg.data) {
      console.log('Push data: ' + msg.data);
      // 收到前台推送,可显示本地通知
    }
  });
}

// 3. 处理通知点击
push.on('click', (msg: push.PushMessage) => {
  // 用户点击通知,执行对应操作
  router.pushUrl({
    url: 'pages/Detail',
    params: { data: msg.data }
  });
});

5.3 通知消息处理

arkts
// 消息处理策略
enum PushMessageHandler {
  // 1. 自动展示(默认)
  // 不需要额外代码,系统自动展示通知

  // 2. 自定义处理(前台消息)
  onMessage(msg: push.PushMessage) {
    // 根据消息类型做不同处理
    switch (msg.type) {
      case 'message':
        showLocalNotification(msg);
        break;
      case 'command':
        handleCommand(msg.data);
        break;
      case 'silent':
        // 静默消息,不展示通知,只更新数据
        updateData(msg.data);
        break;
    }
  },
}

6. 通知与 Android 对比

维度Android鸿蒙
通知构建Notification.Buildernotification.NotificationBuilder
通知渠道NotificationChannelNotificationChannel
横幅通知原生支持Banner API
远程推送FCM / 厂商 PushPush Kit (AGC)
通知点击PendingIntentclickIntent (Want)
大通知setStyle(Notif.BigText)large 属性
进度通知setProgress()normal.progress
通知渠道创建代码创建(不可删除)代码创建(仅可不可见)

7. 🎯 面试高频考点

Q1: 鸿蒙通知系统的工作原理?

答要点

  • 通知通过 Notification Manager 管理,分为本地通知和远程通知
  • 本地通知通过 notification.publishNotification() 发送
  • 远程通知通过 Push Kit 实现,通过云端(AGC)推送
  • 通知渠道是 Android 10+ 的概念,鸿蒙同样采用
  • 用户可在设置中管理每个渠道的展示行为
  • 通知可包含点击 Intent,跳转到指定页面

Q2: Push Kit 与 FCM 的区别?

答要点

  • Push Kit 是鸿蒙生态的推送服务,通过 AGC(AppGallery Connect)
  • FCM 是 Google 的推送服务,鸿蒙 NEXT 不再支持 GMS/FCM
  • Push Kit 支持国内网络环境,FCM 在国内不可用
  • Push Kit 的 Token 通过 AGC SDK 获取,FCM 通过 Firebase SDK
  • Push Kit 支持消息类型:消息/指令/静默

Q3: 如何实现通知的自定义样式?

答要点

  • 通过 NotificationTemplate 定义样式(normal/large/banner)
  • 使用 large 属性实现大通知(大图/长文本)
  • 使用 Banner API 实现横幅通知
  • 使用 action 属性添加通知内按钮
  • 使用 clickIntent 实现点击跳转
  • 通过 importance 控制通知的重要性级别

💡 面试提示:重点掌握 通知渠道本地/远程通知区别Push Kit 推送流程。对比 Android 的 Notification 体系。