推送通知 #
一、通知类型 #
1.1 本地通知 vs 远程通知 #
| 类型 | 触发方式 | 适用场景 |
|---|---|---|
| 本地通知 | 应用内触发 | 提醒、闹钟、定时任务 |
| 远程通知 | 服务器推送 | 即时消息、营销推送 |
二、本地通知 #
2.1 安装 #
bash
npm install @capacitor/local-notifications
npx cap sync
2.2 权限配置 #
iOS (Info.plist):
xml
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
Android (AndroidManifest.xml):
xml
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
2.3 基本使用 #
typescript
import { LocalNotifications, ScheduleOptions, LocalNotificationSchema } from '@capacitor/local-notifications';
// 请求权限
async function requestPermission() {
const result = await LocalNotifications.requestPermissions();
return result.display === 'granted';
}
// 发送简单通知
async function sendNotification() {
await LocalNotifications.schedule({
notifications: [
{
title: '通知标题',
body: '这是通知内容',
id: 1,
schedule: { at: new Date(Date.now() + 1000) },
sound: undefined,
attachments: undefined,
actionTypeId: '',
extra: null
}
]
});
}
2.4 延迟通知 #
typescript
// 延迟5秒发送
async function scheduleDelayedNotification() {
await LocalNotifications.schedule({
notifications: [
{
title: '延迟通知',
body: '这是延迟5秒的通知',
id: 2,
schedule: {
at: new Date(Date.now() + 5000)
}
}
]
});
}
// 定时通知
async function scheduleTimedNotification() {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow.setHours(9, 0, 0, 0);
await LocalNotifications.schedule({
notifications: [
{
title: '每日提醒',
body: '早上好!新的一天开始了',
id: 3,
schedule: { at: tomorrow }
}
]
});
}
2.5 重复通知 #
typescript
// 每分钟重复
async function scheduleRepeatingNotification() {
await LocalNotifications.schedule({
notifications: [
{
title: '重复通知',
body: '每分钟提醒一次',
id: 4,
schedule: {
every: 'minute',
count: 10 // 重复10次
}
}
]
});
}
// 每天重复
async function scheduleDailyNotification() {
await LocalNotifications.schedule({
notifications: [
{
title: '每日提醒',
body: '每天早上9点提醒',
id: 5,
schedule: {
every: 'day',
on: {
hour: 9,
minute: 0
}
}
}
]
});
}
2.6 通知操作 #
typescript
// 取消通知
async function cancelNotification(id: number) {
await LocalNotifications.cancel({
notifications: [{ id }]
});
}
// 取消所有通知
async function cancelAllNotifications() {
const pending = await LocalNotifications.getPending();
const ids = pending.notifications.map(n => ({ id: n.id }));
if (ids.length > 0) {
await LocalNotifications.cancel({ notifications: ids });
}
}
// 获取待发送通知
async function getPendingNotifications() {
const pending = await LocalNotifications.getPending();
return pending.notifications;
}
2.7 通知监听 #
typescript
// 监听通知点击
await LocalNotifications.addListener('localNotificationReceived', (notification) => {
console.log('Notification received:', notification);
});
// 监听通知点击动作
await LocalNotifications.addListener('localNotificationActionPerformed', (action) => {
console.log('Action performed:', action);
// 根据通知ID执行不同操作
const notificationId = action.notification.id;
const extra = action.notification.extra;
// 跳转到特定页面
handleNotificationAction(notificationId, extra);
});
2.8 带操作的通知 #
typescript
// 注册通知类型
async function registerActionTypes() {
await LocalNotifications.registerActionTypes({
types: [
{
id: 'CHAT_MESSAGE',
actions: [
{
id: 'VIEW',
title: '查看'
},
{
id: 'REPLY',
title: '回复',
input: true
},
{
id: 'IGNORE',
title: '忽略',
destructive: true
}
]
}
]
});
}
// 发送带操作的通知
async function sendChatNotification() {
await LocalNotifications.schedule({
notifications: [
{
title: '新消息',
body: 'John: 你好!',
id: 10,
actionTypeId: 'CHAT_MESSAGE',
extra: {
chatId: 'chat_123',
userId: 'user_456'
}
}
]
});
}
三、远程推送通知 #
3.1 安装 #
bash
npm install @capacitor/push-notifications
npx cap sync
3.2 iOS配置 #
创建APNs证书 #
- 登录Apple Developer
- 创建APNs证书或APNs Key (.p8)
- 配置App ID启用Push Notifications
配置Xcode #
swift
// ios/App/App/AppDelegate.swift
import UIKit
import Capacitor
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// 注册远程通知
UNUserNotificationCenter.current().requestAuthorization(
options: [.alert, .sound, .badge]
) { granted, error in
if granted {
DispatchQueue.main.async {
application.registerForRemoteNotifications()
}
}
}
return true
}
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// 将deviceToken发送到服务器
}
func application(_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Failed to register for remote notifications: \(error)")
}
}
3.3 Android配置 #
Firebase配置 #
- 创建Firebase项目
- 添加Android应用
- 下载google-services.json
- 放到
android/app/目录
build.gradle配置 #
groovy
// android/build.gradle
buildscript {
dependencies {
classpath 'com.google.gms:google-services:4.3.15'
}
}
// android/app/build.gradle
apply plugin: 'com.google.gms.google-services'
dependencies {
implementation 'com.google.firebase:firebase-messaging:23.1.0'
}
3.4 基本使用 #
typescript
import { PushNotifications } from '@capacitor/push-notifications';
// 注册推送
async function registerPush() {
// 请求权限
const result = await PushNotifications.requestPermissions();
if (result.receive === 'granted') {
// 注册
await PushNotifications.register();
}
}
// 监听注册成功
await PushNotifications.addListener('registration', (token) => {
console.log('Push registration success, token:', token.value);
// 将token发送到服务器
sendTokenToServer(token.value);
});
// 监听注册失败
await PushNotifications.addListener('registrationError', (error) => {
console.error('Push registration error:', error);
});
// 监听推送接收
await PushNotifications.addListener('pushNotificationReceived', (notification) => {
console.log('Push received:', notification);
});
// 监听推送点击
await PushNotifications.addListener('pushNotificationActionPerformed', (action) => {
console.log('Push action performed:', action);
// 处理点击事件
handlePushAction(action.notification.data);
});
3.5 获取Token #
typescript
// 获取FCM/APNs Token
async function getPushToken() {
const result = await PushNotifications.register();
return result;
}
// 获取已注册的Token
async function checkToken() {
const { value } = await PushNotifications.getToken();
return value;
}
四、通知服务封装 #
4.1 通知服务类 #
typescript
// src/services/notification.service.ts
import { LocalNotifications, LocalNotificationSchema } from '@capacitor/local-notifications';
import { PushNotifications, PushNotificationToken } from '@capacitor/push-notifications';
import { Capacitor } from '@capacitor/core';
type NotificationCallback = (data: any) => void;
class NotificationService {
private callbacks: Map<string, NotificationCallback[]> = new Map();
private pushToken: string | null = null;
async init(): Promise<void> {
// 初始化本地通知
await this.initLocalNotifications();
// 初始化远程推送(仅原生平台)
if (Capacitor.isNativePlatform()) {
await this.initPushNotifications();
}
}
private async initLocalNotifications(): Promise<void> {
// 请求权限
const result = await LocalNotifications.requestPermissions();
if (result.display !== 'granted') {
console.warn('Local notification permission not granted');
return;
}
// 注册操作类型
await LocalNotifications.registerActionTypes({
types: [
{
id: 'DEFAULT',
actions: [
{ id: 'OPEN', title: '打开' },
{ id: 'DISMISS', title: '关闭' }
]
}
]
});
// 监听事件
await LocalNotifications.addListener(
'localNotificationActionPerformed',
this.handleLocalAction.bind(this)
);
}
private async initPushNotifications(): Promise<void> {
const result = await PushNotifications.requestPermissions();
if (result.receive !== 'granted') {
console.warn('Push notification permission not granted');
return;
}
await PushNotifications.register();
await PushNotifications.addListener('registration', (token) => {
this.pushToken = token.value;
console.log('Push token:', token.value);
});
await PushNotifications.addListener('registrationError', (error) => {
console.error('Push registration error:', error);
});
await PushNotifications.addListener(
'pushNotificationActionPerformed',
this.handlePushAction.bind(this)
);
}
// 发送本地通知
async schedule(notification: Omit<LocalNotificationSchema, 'id'> & { id?: number }) {
await LocalNotifications.schedule({
notifications: [
{
id: notification.id || Date.now(),
title: notification.title,
body: notification.body,
schedule: notification.schedule,
extra: notification.extra,
actionTypeId: notification.actionTypeId || 'DEFAULT'
}
]
});
}
// 立即发送
async show(title: string, body: string, extra?: any) {
await this.schedule({
title,
body,
extra,
schedule: { at: new Date(Date.now() + 100) }
});
}
// 取消通知
async cancel(id: number) {
await LocalNotifications.cancel({
notifications: [{ id }]
});
}
// 订阅通知事件
on(event: string, callback: NotificationCallback): () => void {
if (!this.callbacks.has(event)) {
this.callbacks.set(event, []);
}
this.callbacks.get(event)!.push(callback);
return () => {
const callbacks = this.callbacks.get(event);
if (callbacks) {
const index = callbacks.indexOf(callback);
if (index > -1) {
callbacks.splice(index, 1);
}
}
};
}
private handleLocalAction(action: any) {
const { notificationId, actionId, inputValue } = action;
const extra = action.notification.extra;
this.emit('localAction', {
notificationId,
actionId,
inputValue,
extra
});
}
private handlePushAction(action: any) {
const data = action.notification.data;
this.emit('pushAction', data);
}
private emit(event: string, data: any) {
const callbacks = this.callbacks.get(event);
if (callbacks) {
callbacks.forEach(cb => cb(data));
}
}
getPushToken(): string | null {
return this.pushToken;
}
}
export const notificationService = new NotificationService();
4.2 使用示例 #
typescript
// 初始化
await notificationService.init();
// 订阅事件
notificationService.on('localAction', (data) => {
console.log('Local action:', data);
});
notificationService.on('pushAction', (data) => {
console.log('Push action:', data);
});
// 发送通知
await notificationService.show('新消息', '您有一条新消息', {
type: 'chat',
chatId: '123'
});
// 获取推送Token
const token = notificationService.getPushToken();
五、服务器端推送 #
5.1 Firebase Cloud Messaging #
javascript
// Node.js服务器示例
const admin = require('firebase-admin');
// 初始化
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
// 发送推送
async function sendPush(token, title, body, data) {
const message = {
token,
notification: {
title,
body
},
data
};
const response = await admin.messaging().send(message);
console.log('Successfully sent message:', response);
}
// 发送到主题
async function sendToTopic(topic, title, body) {
const message = {
topic,
notification: {
title,
body
}
};
await admin.messaging().send(message);
}
5.2 APNs推送 #
javascript
// Node.js APNs示例
const apn = require('apn');
const options = {
token: {
key: 'path/to/AuthKey.p8',
keyId: 'KEY_ID',
teamId: 'TEAM_ID'
},
production: false
};
const apnProvider = new apn.Provider(options);
async function sendAPNs(deviceToken, title, body, data) {
const notification = new apn.Notification();
notification.alert = {
title,
body
};
notification.topic = 'com.example.app';
notification.payload = data;
const result = await apnProvider.send(notification, deviceToken);
console.log(result);
}
六、总结 #
6.1 核心功能 #
| 功能 | 插件 |
|---|---|
| 本地通知 | @capacitor/local-notifications |
| 远程推送 | @capacitor/push-notifications |
6.2 下一步 #
了解推送通知后,让我们学习 设备信息!
最后更新:2026-03-28