Files
monisuo/flutter_monisuo/PUSH_NOTIFICATION_GUIDE.md
sion 8534306583 feat: 集成推送通知服务
主要功能:
1. 添加推送依赖
   - jpush_flutter: ^2.5.0 (极光推送)
   - flutter_local_notifications: ^16.0.0 (本地通知)
   - permission_handler: ^11.0.0 (权限管理)

2. 创建PushService服务类
   - 初始化极光推送SDK
   - 处理推送消息接收
   - 处理推送点击事件
   - 显示本地通知
   - 设置/删除别名(用户ID绑定)

3. 在main.dart中初始化推送服务
   - 应用启动时自动初始化
   - 登录后可设置用户别名
   - 退出登录时删除别名

4. 推送场景支持
   - 充值审批通知
   - 提现审批通知
   - 资产变动通知
   - 自定义消息推送

5. 文档
   - PUSH_NOTIFICATION_GUIDE.md: 完整的集成指南
   - 包含Android/iOS配置说明
   - 后端接口示例
   - 测试方法

技术栈:
- 极光推送 (JPush) - 国内推送到达率高
- 本地通知 - 支持前台和后台推送
- 别名机制 - 按用户ID精准推送

待完成:
- [ ] 配置极光推送APPKEY
- [ ] Android权限配置
- [ ] iOS证书配置
- [ ] 后端推送接口开发
2026-03-24 18:11:13 +08:00

329 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Flutter前端推送通知集成方案
## 技术选型
### 推送服务选择
考虑到国内环境,推荐使用 **极光推送 (JPush)****个推 (Getui)**
**优势**:
- 国内推送到达率高
- 支持iOS和Android
- 提供完善的Flutter SDK
- 免费版本足够使用
## 集成步骤
### 1. 添加依赖
```yaml
dependencies:
# 极光推送
jpush_flutter: ^2.5.0
# 本地通知
flutter_local_notifications: ^16.0.0
# 权限管理
permission_handler: ^11.0.0
```
### 2. Android配置
**android/app/build.gradle**:
```gradle
android {
defaultConfig {
manifestPlaceholders = [
JPUSH_PKGNAME: applicationId,
JPUSH_APPKEY: "你的APPKEY",
JPUSH_CHANNEL: "developer-default"
]
}
}
```
**android/app/src/main/AndroidManifest.xml**:
```xml
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
```
### 3. iOS配置
**ios/Runner/Info.plist**:
```xml
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
```
### 4. 初始化推送
**lib/services/push_service.dart**:
```dart
import 'package:jpush_flutter/jpush_flutter.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
class PushService {
static final PushService _instance = PushService._internal();
factory PushService() => _instance;
PushService._internal();
final JPush jpush = JPush();
final FlutterLocalNotificationsPlugin localNotifications =
FlutterLocalNotificationsPlugin();
Future<void> init() async {
// 初始化极光推送
jpush.addEventHandler(
onReceiveNotification: (Map<String, dynamic> message) async {
print('收到推送: $message');
_handleNotification(message);
},
onOpenNotification: (Map<String, dynamic> message) async {
print('点击推送: $message');
_handleNotificationTap(message);
},
);
jpush.setup(
appKey: '你的APPKEY',
channel: 'developer-default',
production: false,
debug: true,
);
// 初始化本地通知
await _initLocalNotifications();
}
Future<void> _initLocalNotifications() async {
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/ic_launcher');
final DarwinInitializationSettings initializationSettingsDarwin =
DarwinInitializationSettings();
final InitializationSettings initializationSettings =
InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsDarwin,
);
await localNotifications.initialize(
initializationSettings,
onDidReceiveNotificationResponse: (NotificationResponse response) {
_handleLocalNotificationTap(response.payload);
},
);
}
void _handleNotification(Map<String, dynamic> message) {
// 处理推送消息
final title = message['title'] ?? '新消息';
final body = message['alert'] ?? '';
_showLocalNotification(title, body, message);
}
void _handleNotificationTap(Map<String, dynamic> message) {
// 处理推送点击
final type = message['extras']['type'];
switch (type) {
case 'order':
// 跳转到订单详情
break;
case 'asset':
// 跳转到资产页面
break;
default:
// 跳转到首页
break;
}
}
Future<void> _showLocalNotification(
String title,
String body,
Map<String, dynamic> data,
) async {
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'monisuo_channel',
'模拟所通知',
channelDescription: '模拟所应用通知',
importance: Importance.max,
priority: Priority.high,
);
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await localNotifications.show(
DateTime.now().millisecondsSinceEpoch ~/ 1000,
title,
body,
platformChannelSpecifics,
payload: jsonEncode(data),
);
}
void _handleLocalNotificationTap(String? payload) {
if (payload != null) {
final data = jsonDecode(payload);
_handleNotificationTap(data);
}
}
// 设置别名通常是用户ID
Future<void> setAlias(String userId) async {
jpush.setAlias(userId);
}
// 删除别名
Future<void> deleteAlias() async {
jpush.deleteAlias();
}
// 设置标签
Future<void> setTags(List<String> tags) async {
jpush.setTags(tags);
}
}
```
### 5. 在main.dart中初始化
```dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化推送服务
await PushService().init();
runApp(const MyApp());
}
```
### 6. 登录后设置别名
```dart
// 用户登录成功后
await PushService().setAlias(userId);
// 用户退出登录后
await PushService().deleteAlias();
```
## 后端推送接口
**后端需要提供推送接口**:
```java
@PostMapping("/api/push/send")
public Result<Void> sendPush(
@RequestParam String userId,
@RequestParam String title,
@RequestParam String body,
@RequestParam(required = false) Map<String, Object> extras
) {
// 调用极光推送API
JPushClient jpushClient = new JPushClient(appKey, masterSecret);
PushPayload payload = PushPayload.newBuilder()
.setPlatform(Platform.all())
.setAudience(Audience.alias(userId))
.setNotification(Notification.alert(body))
.setMessage(Message.content(body))
.setOptions(Options.newBuilder().setApnsProduction(false).build())
.build();
jpushClient.sendPush(payload);
return Result.success("推送成功");
}
```
## 推送场景
### 1. 充值审批通知
```dart
{
"title": "充值审批通过",
"body": "您的充值订单已审批通过,金额: 100 USDT",
"extras": {
"type": "order",
"orderNo": "F20260324001"
}
}
```
### 2. 提现审批通知
```dart
{
"title": "提现审批完成",
"body": "您的提现申请已处理,金额: 100 USDT",
"extras": {
"type": "order",
"orderNo": "F20260324002"
}
}
```
### 3. 资产变动通知
```dart
{
"title": "资产变动",
"body": "您的账户余额发生变动",
"extras": {
"type": "asset",
"userId": "123"
}
}
```
## 测试
### 1. 测试推送
```dart
// 在开发环境中测试
await PushService()._showLocalNotification(
'测试标题',
'测试内容',
{'type': 'test'},
);
```
### 2. 测试极光推送
- 在极光推送控制台发送测试推送
- 检查应用是否收到推送
## 注意事项
1. **权限申请**: Android需要申请通知权限
2. **iOS证书**: 需要配置APNs证书
3. **测试环境**: 开发时使用开发环境
4. **生产环境**: 上线前切换到生产环境
5. **用户隐私**: 首次启动时请求推送权限
## 成本估算
- 极光推送免费版每月100万条推送
- 对于中小规模应用完全够用
- 如需更多,可以升级付费版本
---
**集成时间**: 预计2-3小时
**难度**: 中等
**维护成本**: 低