Appearance
推送通知
1. 推送通知简介
推送通知是移动应用中非常重要的功能,它允许应用在后台向用户发送消息,即使应用没有被打开。推送通知可以用于:
- 提醒用户新消息或更新
- 发送重要的系统通知
- 推广活动和促销信息
- 提醒用户完成未完成的操作
- 提供个性化的内容推荐
在 React Native 中,实现推送通知通常有两种方式:
- 本地通知:由应用本身触发,不需要服务器
- 远程推送通知:由服务器发送,通过苹果的 APNs (Apple Push Notification service) 或 Google 的 FCM (Firebase Cloud Messaging)
2. 本地通知
2.1 安装依赖
我们可以使用 @react-native-community/push-notification-ios 和 react-native-push-notification 库来实现本地通知:
bash
npm install @react-native-community/push-notification-ios react-native-push-notification
# 或
npx expo install @react-native-community/push-notification-ios2.2 配置
iOS 配置
- 在
ios/Podfile中添加:
ruby
pod 'PushNotificationIOS', :path => '../node_modules/@react-native-community/push-notification-ios'运行
pod install在
AppDelegate.m中添加推送通知相关代码
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 ...>
<receiver
android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<action android:name="com.google.android.gcm.intent.RETRY" />
<action android:name="com.dieam.reactnativepushnotification.notification.RECEIVED" />
<action android:name="com.dieam.reactnativepushnotification.notification.OPEN" />
<action android:name="com.dieam.reactnativepushnotification.notification.DELETE" />
</intent-filter>
</receiver>
<service
android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>- 在
android/app/build.gradle中添加:
txt
dependencies {
// ...
implementation 'com.google.firebase:firebase-messaging:21.1.0'
}2.3 基本使用
javascript
import React, { useEffect } from 'react';
import { View, Button, Platform } from 'react-native';
import PushNotification from 'react-native-push-notification';
const App = () => {
// 配置推送通知
useEffect(() => {
// 配置推送通知
PushNotification.configure({
// 当应用在前台时收到通知
onNotification: function(notification) {
console.log('NOTIFICATION:', notification);
// 处理通知点击
if (notification.userInteraction) {
console.log('用户点击了通知');
}
},
// 仅 iOS: 本地通知权限
requestPermissions: Platform.OS === 'ios',
});
}, []);
// 发送本地通知
const sendLocalNotification = () => {
PushNotification.localNotification({
title: '测试通知',
message: '这是一条本地通知',
bigText: '这是通知的详细内容',
subText: '副标题',
color: '#FF0000',
vibrate: true,
vibration: 300,
playSound: true,
soundName: 'default',
actions: ['查看', '关闭'],
});
};
// 发送延迟通知
const scheduleNotification = () => {
PushNotification.localNotificationSchedule({
title: '延迟通知',
message: '5秒后发送的通知',
date: new Date(Date.now() + 5 * 1000),
repeatType: 'day', // 每天重复
});
};
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Button title="发送本地通知" onPress={sendLocalNotification} />
<Button title="发送延迟通知" onPress={scheduleNotification} />
</View>
);
};
export default App;3. 远程推送通知
3.1 使用 Firebase Cloud Messaging (FCM)
3.1.1 安装依赖
bash
npm install @react-native-firebase/app @react-native-firebase/messaging
# 或
npx expo install @react-native-firebase/app @react-native-firebase/messaging3.1.2 配置 Firebase
- 登录 Firebase 控制台
- 创建一个新项目
- 为 iOS 和 Android 添加应用
- 下载配置文件:
- iOS:
GoogleService-Info.plist - Android:
google-services.json
- iOS:
3.1.3 集成配置
iOS 配置
- 将
GoogleService-Info.plist添加到ios/目录 - 在
Podfile中添加:
ruby
pod 'Firebase/Messaging'运行
pod install在
AppDelegate.m中添加:
objective-c
@import Firebase;
// 在 didFinishLaunchingWithOptions 方法中
[FIRApp configure];- 在 Xcode 中启用推送通知:
- 打开项目 -> Capabilities -> Push Notifications -> 启用
Android 配置
将
google-services.json添加到android/app/目录在
android/build.gradle中添加:
txt
buildscript {
dependencies {
// ...
classpath 'com.google.gms:google-services:4.3.10'
}
}- 在
android/app/build.gradle末尾添加:
txt
apply plugin: 'com.google.gms.google-services'3.2 基本使用
javascript
import React, { useEffect } from 'react';
import { View, Text } from 'react-native';
import messaging from '@react-native-firebase/messaging';
const App = () => {
useEffect(() => {
// 请求通知权限
const requestPermission = async () => {
const authStatus = await messaging().requestPermission();
const enabled = authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
console.log('通知权限已授予');
}
};
requestPermission();
// 获取设备令牌
messaging().getToken().then(token => {
console.log('设备令牌:', token);
// 将令牌发送到服务器
});
// 监听前台通知
const unsubscribe = messaging().onMessage(async remoteMessage => {
console.log('收到前台通知:', remoteMessage);
});
// 监听通知点击
messaging().onNotificationOpenedApp(remoteMessage => {
console.log('用户点击了通知:', remoteMessage);
});
// 检查应用是否通过点击通知打开
messaging().getInitialNotification().then(remoteMessage => {
if (remoteMessage) {
console.log('应用通过通知打开:', remoteMessage);
}
});
return unsubscribe;
}, []);
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>推送通知示例</Text>
</View>
);
};
export default App;4. 高级配置
4.1 通知渠道(Android)
Android 8.0+ 要求为通知设置渠道:
javascript
import PushNotification from 'react-native-push-notification';
// 创建通知渠道
if (Platform.OS === 'android') {
PushNotification.createChannel(
{
channelId: 'default-channel-id',
channelName: '默认通知渠道',
channelDescription: '默认的通知渠道',
importance: 4,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
},
(created) => console.log(`通知渠道创建结果: ${created}`)
);
}
// 使用渠道发送通知
PushNotification.localNotification({
channelId: 'default-channel-id',
title: '测试通知',
message: '这是一条带有渠道的通知',
});4.2 通知样式
javascript
// 大图样式
PushNotification.localNotification({
title: '图片通知',
message: '这是一条带有图片的通知',
bigPictureUrl: 'https://example.com/image.jpg',
bigLargeIconUrl: 'https://example.com/icon.jpg',
largeIconUrl: 'https://example.com/icon.jpg',
});
// 列表样式
PushNotification.localNotification({
title: '列表通知',
message: '这是一条列表通知',
bigText: '项目 1\n项目 2\n项目 3',
});4.3 通知分组
javascript
// 分组通知
PushNotification.localNotification({
title: '分组通知 1',
message: '这是分组通知的第一条',
group: 'group-1',
groupSummary: true,
});
PushNotification.localNotification({
title: '分组通知 2',
message: '这是分组通知的第二条',
group: 'group-1',
});5. 实际应用场景
5.1 消息通知
javascript
// 收到新消息时发送通知
const sendMessageNotification = (sender, message) => {
PushNotification.localNotification({
title: `新消息来自 ${sender}`,
message: message,
soundName: 'default',
vibrate: true,
});
};5.2 提醒通知
javascript
// 日程提醒
const scheduleReminder = (title, time) => {
PushNotification.localNotificationSchedule({
title: '日程提醒',
message: title,
date: time,
repeatType: 'none',
});
};5.3 促销通知
javascript
// 促销活动通知
const sendPromotionNotification = (offer) => {
PushNotification.localNotification({
title: '限时优惠',
message: offer,
actions: ['查看详情', '忽略'],
vibrate: true,
soundName: 'default',
});
};6. 最佳实践
权限处理:
- 仅在必要时请求通知权限
- 解释为什么需要通知权限
- 提供设置选项让用户控制通知
通知内容:
- 保持通知简洁明了
- 提供有价值的信息
- 避免发送过多通知
用户体验:
- 为不同类型的通知使用不同的声音和振动模式
- 提供通知操作按钮
- 确保通知在不同设备上显示一致
性能考虑:
- 避免在通知中包含过多数据
- 合理安排通知的发送时间
- 清理不再需要的通知
安全考虑:
- 不要在通知中包含敏感信息
- 验证通知的来源
- 保护设备令牌
7. 常见问题与解决方案
7.1 通知不显示
问题:发送通知后,设备上没有显示通知
解决方案:
- 检查应用是否有通知权限
- 检查通知渠道配置(Android 8.0+)
- 检查设备的通知设置
- 检查应用是否在前台运行
7.2 远程通知接收失败
问题:服务器发送的远程通知没有收到
解决方案:
- 检查设备令牌是否正确
- 检查 Firebase 配置是否正确
- 检查网络连接
- 检查通知 payload 格式是否正确
7.3 通知点击不响应
问题:点击通知后没有触发相应的操作
解决方案:
- 确保正确实现了通知点击监听器
- 检查应用的导航逻辑
- 确保应用能够处理通知数据
7.4 通知重复显示
问题:通知重复显示或多次触发
解决方案:
- 检查通知 ID 是否唯一
- 确保没有重复调用发送通知的方法
- 检查服务器是否重复发送通知
8. 扩展阅读
- React Native Push Notification 文档
- Firebase Cloud Messaging 文档
- Apple Push Notification Service 文档
- Android 通知文档
9. 完整示例
javascript
// App.js
import React, { useEffect, useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import PushNotification from 'react-native-push-notification';
import messaging from '@react-native-firebase/messaging';
const App = () => {
const [notificationToken, setNotificationToken] = useState('');
const [lastNotification, setLastNotification] = useState(null);
useEffect(() => {
// 配置本地通知
PushNotification.configure({
onNotification: function(notification) {
console.log('NOTIFICATION:', notification);
setLastNotification(notification);
},
requestPermissions: true,
});
// 配置 Android 通知渠道
if (Platform.OS === 'android') {
PushNotification.createChannel(
{
channelId: 'default',
channelName: '默认通知',
channelDescription: '默认通知渠道',
importance: 4,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
},
(created) => console.log(`通知渠道创建: ${created}`)
);
}
// 获取 FCM 令牌
const getToken = async () => {
try {
const token = await messaging().getToken();
setNotificationToken(token);
console.log('FCM 令牌:', token);
} catch (error) {
console.error('获取令牌失败:', error);
}
};
getToken();
// 监听前台通知
const unsubscribe = messaging().onMessage(async remoteMessage => {
console.log('收到前台通知:', remoteMessage);
setLastNotification(remoteMessage);
});
return unsubscribe;
}, []);
const sendLocalNotification = () => {
PushNotification.localNotification({
channelId: 'default',
title: '本地通知',
message: '这是一条本地通知',
bigText: '这是通知的详细内容,点击查看更多',
subText: '来自 React Native',
color: '#FF0000',
vibrate: true,
vibration: 300,
playSound: true,
soundName: 'default',
actions: ['查看', '关闭'],
});
};
const scheduleNotification = () => {
PushNotification.localNotificationSchedule({
channelId: 'default',
title: '定时通知',
message: '这是一条 10 秒后发送的通知',
date: new Date(Date.now() + 10 * 1000),
});
};
return (
<View style={styles.container}>
<Text style={styles.title}>推送通知示例</Text>
<Text style={styles.subtitle}>FCM 令牌:</Text>
<Text style={styles.token}>{notificationToken || '获取中...'}</Text>
<Text style={styles.subtitle}>最近的通知:</Text>
<Text style={styles.notification}>
{lastNotification ? JSON.stringify(lastNotification, null, 2) : '暂无通知'}
</Text>
<View style={styles.buttons}>
<Button title="发送本地通知" onPress={sendLocalNotification} />
<Button title="发送定时通知" onPress={scheduleNotification} />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#f5f5f5',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 20,
textAlign: 'center',
},
subtitle: {
fontSize: 16,
fontWeight: 'bold',
marginTop: 20,
marginBottom: 10,
},
token: {
fontSize: 14,
backgroundColor: '#fff',
padding: 10,
borderRadius: 5,
marginBottom: 10,
},
notification: {
fontSize: 14,
backgroundColor: '#fff',
padding: 10,
borderRadius: 5,
marginBottom: 20,
height: 150,
overflow: 'scroll',
},
buttons: {
flexDirection: 'row',
justifyContent: 'space-around',
marginTop: 20,
},
});
export default App;这个示例展示了如何实现本地通知和远程推送通知,包括通知权限请求、令牌获取、通知发送和接收等功能。
