React Native推送通知 #
概述 #
推送通知是移动应用的重要功能,用于向用户发送消息提醒。本章节介绍如何在 React Native 中实现本地通知和远程推送。
权限配置 #
iOS 配置 #
- 在 Apple Developer 中启用 Push Notifications 能力
- 在 Xcode 中启用 Push Notifications
- 在
ios/MyApp/Info.plist中添加:
xml
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
Android 配置 #
在 android/app/src/main/AndroidManifest.xml 中添加:
xml
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application ...>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_notification" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/notification_color" />
</application>
notifee #
推荐的通知库,支持 iOS 和 Android。
安装 #
bash
npm install @notifee/react-native
cd ios && pod install
基本使用 #
tsx
import notifee, {AndroidImportance} from '@notifee/react-native';
import React, {useState} from 'react';
import {View, Button, StyleSheet} from 'react-native';
const NotificationExample = () => {
const requestPermission = async () => {
const settings = await notifee.requestPermission();
console.log('Permission settings:', settings);
};
const displayNotification = async () => {
await notifee.displayNotification({
title: '通知标题',
body: '这是通知内容',
android: {
channelId: 'default',
importance: AndroidImportance.HIGH,
pressAction: {
id: 'default',
},
},
});
};
return (
<View style={styles.container}>
<Button title="请求权限" onPress={requestPermission} />
<Button title="发送通知" onPress={displayNotification} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
gap: 16,
},
});
export default NotificationExample;
创建通知渠道(Android) #
tsx
import notifee, {AndroidImportance, AndroidVisibility} from '@notifee/react-native';
const createChannels = async () => {
await notifee.createChannel({
id: 'default',
name: '默认通知',
importance: AndroidImportance.HIGH,
visibility: AndroidVisibility.PUBLIC,
});
await notifee.createChannel({
id: 'messages',
name: '消息通知',
importance: AndroidImportance.HIGH,
vibration: true,
sound: 'default',
});
await notifee.createChannel({
id: 'silent',
name: '静默通知',
importance: AndroidImportance.LOW,
sound: undefined,
});
};
带图片的通知 #
tsx
const displayImageNotification = async () => {
await notifee.displayNotification({
title: '图片通知',
body: '这是一条带图片的通知',
android: {
channelId: 'default',
largeIcon: 'https://example.com/image.png',
style: {
type: AndroidStyle.BIGPICTURE,
picture: 'https://example.com/big-image.png',
},
},
ios: {
attachments: [
{
url: 'https://example.com/image.png',
},
],
},
});
};
带操作的通知 #
tsx
const displayActionNotification = async () => {
await notifee.displayNotification({
title: '新消息',
body: '您有一条新消息',
android: {
channelId: 'messages',
actions: [
{
title: '回复',
pressAction: {
id: 'reply',
},
input: true,
},
{
title: '标记已读',
pressAction: {
id: 'mark-read',
},
},
],
},
});
};
监听通知事件 #
tsx
import notifee, {EventType, Event} from '@notifee/react-native';
import {useEffect} from 'react';
const NotificationHandler = () => {
useEffect(() => {
const unsubscribe = notifee.onForegroundEvent(({type, detail}) => {
switch (type) {
case EventType.DISMISSED:
console.log('用户关闭了通知');
break;
case EventType.PRESS:
console.log('用户点击了通知', detail.notification);
break;
case EventType.ACTION_PRESS:
console.log('用户点击了操作按钮', detail.pressAction);
break;
}
});
return unsubscribe;
}, []);
useEffect(() => {
notifee.onBackgroundEvent(async ({type, detail}) => {
if (type === EventType.PRESS) {
console.log('后台点击通知', detail.notification);
}
});
}, []);
return null;
};
定时通知 #
tsx
import notifee, {TimestampTrigger, TriggerType} from '@notifee/react-native';
const scheduleNotification = async () => {
const trigger: TimestampTrigger = {
type: TriggerType.TIMESTAMP,
timestamp: Date.now() + 5000, // 5秒后
};
await notifee.createTriggerNotification(
{
title: '定时通知',
body: '这是5秒后的定时通知',
android: {
channelId: 'default',
},
},
trigger,
);
};
const scheduleRepeatNotification = async () => {
const trigger: TimestampTrigger = {
type: TriggerType.TIMESTAMP,
timestamp: Date.now() + 60000,
repeatFrequency: RepeatFrequency.HOURLY,
};
await notifee.createTriggerNotification(
{
title: '重复通知',
body: '每小时提醒一次',
android: {
channelId: 'default',
},
},
trigger,
);
};
Firebase Cloud Messaging (FCM) #
用于远程推送通知。
安装 #
bash
npm install @react-native-firebase/app @react-native-firebase/messaging
cd ios && pod install
配置 Firebase #
- 在 Firebase Console 创建项目
- 添加 iOS 和 Android 应用
- 下载配置文件:
- iOS:
GoogleService-Info.plist放入ios/目录 - Android:
google-services.json放入android/app/目录
- iOS:
Android 配置 #
在 android/build.gradle 中添加:
gradle
dependencies {
classpath 'com.google.gms:google-services:4.3.15'
}
在 android/app/build.gradle 中添加:
gradle
apply plugin: 'com.google.gms.google-services'
获取 FCM Token #
tsx
import messaging from '@react-native-firebase/messaging';
import {useEffect, useState} from 'react';
const FCMExample = () => {
const [fcmToken, setFcmToken] = useState<string | null>(null);
useEffect(() => {
const getToken = async () => {
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
const token = await messaging().getToken();
setFcmToken(token);
console.log('FCM Token:', token);
}
};
getToken();
const unsubscribe = messaging().onTokenRefresh(token => {
setFcmToken(token);
console.log('Token refreshed:', token);
});
return unsubscribe;
}, []);
return (
<View>
<Text>FCM Token: {fcmToken}</Text>
</View>
);
};
监听消息 #
tsx
import messaging from '@react-native-firebase/messaging';
import {useEffect} from 'react';
const MessageHandler = () => {
useEffect(() => {
const unsubscribe = messaging().onMessage(async remoteMessage => {
console.log('前台收到消息:', remoteMessage);
await notifee.displayNotification({
title: remoteMessage.notification?.title,
body: remoteMessage.notification?.body,
android: {
channelId: 'default',
},
});
});
return unsubscribe;
}, []);
useEffect(() => {
messaging().onNotificationOpenedApp(remoteMessage => {
console.log('后台打开应用:', remoteMessage);
});
messaging()
.getInitialNotification()
.then(remoteMessage => {
if (remoteMessage) {
console.log('退出状态打开应用:', remoteMessage);
}
});
}, []);
useEffect(() => {
messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log('后台收到消息:', remoteMessage);
});
}, []);
return null;
};
订阅主题 #
tsx
const subscribeToTopic = async (topic: string) => {
await messaging().subscribeToTopic(topic);
console.log(`已订阅主题: ${topic}`);
};
const unsubscribeFromTopic = async (topic: string) => {
await messaging().unsubscribeFromTopic(topic);
console.log(`已取消订阅主题: ${topic}`);
};
// 使用示例
await subscribeToTopic('news');
await subscribeToTopic('sports');
完整示例 #
tsx
import React, {useEffect, useState} from 'react';
import {
View,
Text,
Button,
StyleSheet,
Alert,
ScrollView,
} from 'react-native';
import notifee, {
AndroidImportance,
EventType,
TimestampTrigger,
TriggerType,
} from '@notifee/react-native';
import messaging from '@react-native-firebase/messaging';
const NotificationService = () => {
const [fcmToken, setFcmToken] = useState<string | null>(null);
useEffect(() => {
initNotifications();
setupListeners();
}, []);
const initNotifications = async () => {
await notifee.createChannel({
id: 'default',
name: '默认通知',
importance: AndroidImportance.HIGH,
});
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
const token = await messaging().getToken();
setFcmToken(token);
}
};
const setupListeners = () => {
notifee.onForegroundEvent(({type, detail}) => {
handleNotificationEvent(type, detail);
});
notifee.onBackgroundEvent(async ({type, detail}) => {
handleNotificationEvent(type, detail);
});
messaging().onMessage(async remoteMessage => {
await notifee.displayNotification({
title: remoteMessage.notification?.title,
body: remoteMessage.notification?.body,
android: {channelId: 'default'},
});
});
messaging().onNotificationOpenedApp(remoteMessage => {
handleDeepLink(remoteMessage.data);
});
};
const handleNotificationEvent = (type: EventType, detail: any) => {
switch (type) {
case EventType.PRESS:
console.log('通知被点击', detail.notification);
break;
case EventType.ACTION_PRESS:
console.log('操作按钮被点击', detail.pressAction);
break;
}
};
const handleDeepLink = (data: any) => {
if (data?.screen) {
// 导航到指定页面
console.log('Navigate to:', data.screen);
}
};
const sendLocalNotification = async () => {
await notifee.displayNotification({
title: '本地通知',
body: '这是一条本地通知',
android: {
channelId: 'default',
importance: AndroidImportance.HIGH,
},
});
};
const scheduleNotification = async () => {
const trigger: TimestampTrigger = {
type: TriggerType.TIMESTAMP,
timestamp: Date.now() + 5000,
};
await notifee.createTriggerNotification(
{
title: '定时通知',
body: '5秒后的提醒',
android: {channelId: 'default'},
},
trigger,
);
Alert.alert('成功', '已设置5秒后的通知');
};
const cancelAllNotifications = async () => {
await notifee.cancelAllNotifications();
Alert.alert('成功', '已取消所有通知');
};
return (
<ScrollView style={styles.container}>
<Text style={styles.title}>推送通知服务</Text>
<View style={styles.section}>
<Text style={styles.label}>FCM Token:</Text>
<Text style={styles.token}>{fcmToken || '获取中...'}</Text>
</View>
<View style={styles.buttons}>
<Button
title="发送本地通知"
onPress={sendLocalNotification}
/>
<Button
title="设置定时通知"
onPress={scheduleNotification}
/>
<Button
title="取消所有通知"
onPress={cancelAllNotifications}
color="#FF3B30"
/>
</View>
</ScrollView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
padding: 16,
},
title: {
fontSize: 24,
fontWeight: 'bold',
textAlign: 'center',
marginBottom: 24,
},
section: {
backgroundColor: '#fff',
borderRadius: 8,
padding: 16,
marginBottom: 16,
},
label: {
fontSize: 14,
color: '#666',
marginBottom: 8,
},
token: {
fontSize: 12,
color: '#333',
fontFamily: 'monospace',
},
buttons: {
gap: 12,
},
});
export default NotificationService;
总结 #
推送通知要点:
- notifee:推荐的通知库,功能丰富
- 通知渠道:Android 需要创建渠道
- 通知事件:监听用户交互
- 定时通知:支持延迟和重复
- FCM:远程推送通知
- 主题订阅:群发消息
继续学习 原生模块,了解如何与原生代码交互。
最后更新:2026-03-28