I found a solution.
You have to go to Xcode => Runner => Build Settings and put "Allow Non-modular Includes In Framework Modules" to "yes"
I found a solution.
You have to go to Xcode => Runner => Build Settings and put "Allow Non-modular Includes In Framework Modules" to "yes"
收到!你遇到了一個常見的 Flutter 推播通知問題:在 Android 裝置上收到訊息,但沒有顯示通知。這通常是因為訊息在應用程式前景執行時,預設不會顯示視覺化的通知。
D/FLTFireMsgReceiver
),但預設不會自動顯示為系統通知。你需要額外設定才能讓前景通知也顯示出來。D/FLTFireMsgReceiver(31072): broadcast received for message
表示 Firebase 的接收器已經收到了推播訊息。然而,你沒有看到通知,這通常是因為以下原因:FirebaseMessaging.onMessage.listen()
這個監聽器傳遞給你的 Flutter 程式碼,讓你可以在 App 內自訂處理方式(例如顯示一個 App 內部的提示)。flutter_local_notifications
套件,並在 FirebaseMessaging.onMessage.listen()
的回調函數中觸發本地通知。firebase_messaging
版本問題 ⬆️: 有些舊版本的 firebase_messaging
套件可能存在 Bug,影響了通知的處理。檢查一下你使用的版本,並參考 GitHub 上的相關 Issues(你提供的連結中有提到版本 8.0.0-dev.9
的問題)。getToken()
的影響 🔑: 如 GitHub Issue #6011 所述,有時候在收到訊息前先呼叫 FirebaseMessaging.instance.getToken()
會意外地觸發 onMessage
的監聽器。這可能是一個 Bug 或是一個繞過問題的技巧,但最好還是尋求更標準的解決方案。main()
函數或 initState
),請求使用者允許接收通知。firebase_messaging
套件的 requestPermission()
方法:import 'package:firebase_messaging/firebase_messaging.dart';
Future<void> requestNotificationPermissions() async {
FirebaseMessaging messaging = FirebaseMessaging.instance;
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
print('User granted permission: ${settings.authorizationStatus}');
}
// 在你的 main() 或 initState() 中呼叫
// await requestNotificationPermissions();
flutter_local_notifications
套件來顯示通知。FirebaseMessaging.onMessage.listen()
的回調中,使用 flutter_local_notifications
來建立和顯示一個本地通知。flutter_local_notifications
套件
在你的 pubspec.yaml
中添加:dependencies:
flutter:
sdk: flutter
firebase_core: ^x.x.x # 請使用你專案的 firebase_core 版本
firebase_messaging: ^x.x.x # 請使用你專案的 firebase_messaging 版本
flutter_local_notifications: ^x.x.x # 添加此套件
flutter pub get
。flutter_local_notifications
並在 onMessage
中使用
在你的 main.dart
或一個專門的服務類別中:import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
// 在 Android 上,需要設定通知通道
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print("Handling a background message: ${message.messageId}");
// 在背景處理訊息時,如果需要顯示通知,也需要使用 flutter_local_notifications
// 但通常背景訊息是處理資料,而非顯示通知
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(); // 初始化 Firebase
// 初始化 flutter_local_notifications
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/ic_launcher'); // 你的 Android app icon
const InitializationSettings initializationSettings =
InitializationSettings(android: initializationSettingsAndroid);
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: (NotificationResponse notificationResponse) async {
// 處理使用者點擊通知的邏輯
print('Notification tapped: ${notificationResponse.payload}');
},
);
// 設定前景訊息監聽器
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Got a message whilst in the foreground!');
print('Message data: ${message.data}');
RemoteNotification? notification = message.notification;
if (notification != null) {
// 在前景時顯示本地通知
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
const NotificationDetails(
android: AndroidNotificationDetails(
'high_priority_channel_id', // 這必須與 AndroidManifest.xml 中的 channel ID 一致
'High Priority Notifications',
channelDescription: 'This channel is used for important notifications.',
importance: Importance.high,
priority: Priority.high,
showWhen: false,
// 你可以在這裡設定 icon, sound 等
// icon: '@mipmap/ic_launcher',
),
),
payload: message.data.toString(), // 可以傳遞額外的資料
);
}
});
// 設定背景訊息處理器
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(const MyApp());
}
// 全域變數,用於初始化 flutter_local_notifications
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
requestNotificationPermissions(); // 在 initState 中請求權限
// 也可以在這裡訂閱 topic 或獲取 token
FirebaseMessaging.instance.getToken().then((String? token) {
print("FCM Token: $token");
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Firebase Messaging Demo'),
),
body: const Center(
child: Text('App is running'),
),
);
}
}
android/app/src/main/AndroidManifest.xml
中有正確的設定,特別是關於通知通道的宣告。high_priority_channel_id
,請確保你的 Manifest 中有對應的通道宣告(或者讓 flutter_local_notifications
在第一次顯示時自動建立)。AndroidManifest.xml
區塊:<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.your_app_name">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <!-- For Android 13+ -->
<application
android:label="your_app_name"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="high_priority_channel_id"/> <!-- 預設通知通道 -->
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!-- Add this service for Firebase Messaging -->
<service
android:name="com.google.firebase.messaging.FirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
POST_NOTIFICATIONS
權限。firebase_messaging
版本和更新 🔄:8.0.0-dev.9
,建議升級到最新的穩定版本。flutter pub outdated
查看是否有過期的套件,然後更新 firebase_messaging
和 firebase_core
。onMessage
回調中加入 flutter_local_notifications
來手動顯示通知,並確保你已經請求了必要的權限。 👍