Flutter 推送通知实现详解
简介
推送通知是移动应用的重要功能,可以让用户及时获取重要信息。本文介绍如何在 Flutter 中实现推送通知功能。
基本配置
添加依赖
yaml
dependencies:
firebase_core: ^2.15.1
firebase_messaging: ^14.6.7
flutter_local_notifications: ^15.1.1
初始化 Firebase
dart
Future<void> initFirebase() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
// 获取 FCM Token
final fcmToken = await FirebaseMessaging.instance.getToken();
print('FCM Token: $fcmToken');
}
配置通知权限
dart
Future<void> requestNotificationPermission() async {
final messaging = FirebaseMessaging.instance;
NotificationSettings settings = await messaging.requestPermission(
alert: true,
badge: true,
sound: true,
);
print('Notification permission status: ${settings.authorizationStatus}');
}
本地通知
初始化本地通知
dart
class NotificationService {
static final NotificationService _instance = NotificationService._internal();
factory NotificationService() => _instance;
final FlutterLocalNotificationsPlugin _notifications =
FlutterLocalNotificationsPlugin();
NotificationService._internal();
Future<void> init() async {
const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
const iosSettings = DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
const settings = InitializationSettings(
android: androidSettings,
iOS: iosSettings,
);
await _notifications.initialize(
settings,
onDidReceiveNotificationResponse: _onNotificationTapped,
);
}
void _onNotificationTapped(NotificationResponse response) {
// 处理通知点击事件
}
Future<void> showNotification({
required String title,
required String body,
String? payload,
}) async {
const androidDetails = AndroidNotificationDetails(
'default_channel',
'Default Channel',
importance: Importance.high,
priority: Priority.high,
);
const iosDetails = DarwinNotificationDetails(
presentAlert: true,
presentBadge: true,
presentSound: true,
);
const details = NotificationDetails(
android: androidDetails,
iOS: iosDetails,
);
await _notifications.show(
0,
title,
body,
details,
payload: payload,
);
}
}
远程推送
处理后台消息
dart
Future<void> _firebaseMessagingBackgroundHandler(
RemoteMessage message,
) async {
await Firebase.initializeApp();
print('Handling background message: ${message.messageId}');
// 显示本地通知
await NotificationService().showNotification(
title: message.notification?.title ?? '',
body: message.notification?.body ?? '',
payload: message.data.toString(),
);
}
处理前台消息
dart
void _handleForegroundMessage() {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Got a message whilst in the foreground!');
print('Message data: ${message.data}');
if (message.notification != null) {
print('Message also contained a notification:');
print('Title: ${message.notification?.title}');
print('Body: ${message.notification?.body}');
NotificationService().showNotification(
title: message.notification?.title ?? '',
body: message.notification?.body ?? '',
payload: message.data.toString(),
);
}
});
}
完整示例
dart
class PushNotificationDemo extends StatefulWidget {
@override
_PushNotificationDemoState createState() => _PushNotificationDemoState();
}
class _PushNotificationDemoState extends State<PushNotificationDemo> {
final notificationService = NotificationService();
String? _fcmToken;
List<String> _notifications = [];
@override
void initState() {
super.initState();
_initPushNotifications();
}
Future<void> _initPushNotifications() async {
// 初始化 Firebase
await Firebase.initializeApp();
// 初始化本地通知
await notificationService.init();
// 请求通知权限
await requestNotificationPermission();
// 获取 FCM Token
final token = await FirebaseMessaging.instance.getToken();
setState(() {
_fcmToken = token;
});
// 监听 Token 刷新
FirebaseMessaging.instance.onTokenRefresh.listen((token) {
setState(() {
_fcmToken = token;
});
});
// 处理后台消息
FirebaseMessaging.onBackgroundMessage(
_firebaseMessagingBackgroundHandler,
);
// 处理前台消息
FirebaseMessaging.onMessage.listen((message) {
setState(() {
_notifications.add(
'${message.notification?.title}: ${message.notification?.body}',
);
});
notificationService.showNotification(
title: message.notification?.title ?? '',
body: message.notification?.body ?? '',
);
});
// 处理通知点击
FirebaseMessaging.onMessageOpenedApp.listen((message) {
print('Message clicked!');
// 处理通知点击事件
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Push Notifications'),
),
body: ListView(
padding: EdgeInsets.all(16),
children: [
Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'FCM Token:',
style: TextStyle(fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Text(_fcmToken ?? 'Loading...'),
],
),
),
),
SizedBox(height: 16),
Text(
'Notifications:',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
..._notifications.map((notification) => Card(
child: ListTile(
title: Text(notification),
),
)).toList(),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
notificationService.showNotification(
title: 'Test Notification',
body: 'This is a test local notification',
);
},
child: Icon(Icons.notifications),
),
);
}
}
最佳实践
- 合理处理通知权限
- 实现通知分类
- 处理通知点击事件
- 管理通知角标
- 实现通知持久化
注意事项
- 平台差异处理
- Token 管理
- 通知限制
- 后台消息处理
- 电池优化影响
总结
推送通知是提升用户活跃度的重要功能。通过合理使用 Firebase Cloud Messaging 和本地通知,可以实现完整的推送通知功能。注意在实现过程中要考虑平台差异和性能优化。