主要功能: 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证书配置 - [ ] 后端推送接口开发
7.6 KiB
7.6 KiB
Flutter前端推送通知集成方案
技术选型
推送服务选择
考虑到国内环境,推荐使用 极光推送 (JPush) 或 个推 (Getui)
优势:
- 国内推送到达率高
- 支持iOS和Android
- 提供完善的Flutter SDK
- 免费版本足够使用
集成步骤
1. 添加依赖
dependencies:
# 极光推送
jpush_flutter: ^2.5.0
# 本地通知
flutter_local_notifications: ^16.0.0
# 权限管理
permission_handler: ^11.0.0
2. Android配置
android/app/build.gradle:
android {
defaultConfig {
manifestPlaceholders = [
JPUSH_PKGNAME: applicationId,
JPUSH_APPKEY: "你的APPKEY",
JPUSH_CHANNEL: "developer-default"
]
}
}
android/app/src/main/AndroidManifest.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:
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
4. 初始化推送
lib/services/push_service.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中初始化
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化推送服务
await PushService().init();
runApp(const MyApp());
}
6. 登录后设置别名
// 用户登录成功后
await PushService().setAlias(userId);
// 用户退出登录后
await PushService().deleteAlias();
后端推送接口
后端需要提供推送接口:
@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. 充值审批通知
{
"title": "充值审批通过",
"body": "您的充值订单已审批通过,金额: 100 USDT",
"extras": {
"type": "order",
"orderNo": "F20260324001"
}
}
2. 提现审批通知
{
"title": "提现审批完成",
"body": "您的提现申请已处理,金额: 100 USDT",
"extras": {
"type": "order",
"orderNo": "F20260324002"
}
}
3. 资产变动通知
{
"title": "资产变动",
"body": "您的账户余额发生变动",
"extras": {
"type": "asset",
"userId": "123"
}
}
测试
1. 测试推送
// 在开发环境中测试
await PushService()._showLocalNotification(
'测试标题',
'测试内容',
{'type': 'test'},
);
2. 测试极光推送
- 在极光推送控制台发送测试推送
- 检查应用是否收到推送
注意事项
- 权限申请: Android需要申请通知权限
- iOS证书: 需要配置APNs证书
- 测试环境: 开发时使用开发环境
- 生产环境: 上线前切换到生产环境
- 用户隐私: 首次启动时请求推送权限
成本估算
- 极光推送免费版:每月100万条推送
- 对于中小规模应用完全够用
- 如需更多,可以升级付费版本
集成时间: 预计2-3小时 难度: 中等 维护成本: 低