嗨,我正在尝试在前台收到通知时实现自定义铃声,铃声播放正常,停止正常,但是当应用程序在后台时,铃声正在响起,但无法停止,我发现handleBackgroundMessage正在创建新实例,并且在MyApp中具有对象的不同实例和
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
NotificationHandler().onSelectNotification(json.encode(message.data));
});
这个方法是从 Myapp 调用的,所以它有不同的实例,任何人都可以建议我在这里做错了什么,我的代码如下
Future<void> handleBackgroundMessage(RemoteMessage message) async {
if (Platform.isAndroid) {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform);
} else if (Platform.isIOS) {
await Firebase.initializeApp();
}
final liveAstrologerController = Get.put(LiveAstrologerController());
final walletController = Get.put(WalletController());
final chatController = Get.put(ChatController);
final callController = Get.put(CallController());
final reportController = Get.put(ReportController());
if (message.notification!.title == "For Live Streaming Chat") {
Future.delayed(const Duration(milliseconds: 500)).then((value) async {
await localNotifications.cancelAll();
});
String sessionType = message.data["sessionType"];
if (sessionType == "start") {
String? liveChatUserName2 = message.data['liveChatSUserName'];
if (liveChatUserName2 != null) {
liveAstrologerController.liveChatUserName = liveChatUserName2;
liveAstrologerController.update();
}
String chatId = message.data["chatId"];
liveAstrologerController.isUserJoinAsChat = true;
liveAstrologerController.update();
liveAstrologerController.chatId = chatId;
int waitListId = int.parse(message.data["waitListId"].toString());
String time = liveAstrologerController.waitList
.where((element) => element.id == waitListId)
.first
.time;
liveAstrologerController.endTime = DateTime.now().millisecondsSinceEpoch +
1000 * int.parse(time.toString());
liveAstrologerController.update();
} else {}
} else if (message.notification!.title ==
"For timer and session start for live") {
liveAstrologerController.update();
} else if (message.notification!.title == "Start simple chat timer") {
} else {
try {
if (message.data.isNotEmpty) {
var messageData = json.decode((message.data['body']));
if (messageData['notificationType'] != null) {
if (messageData['notificationType'] == 7) {
// get wallet api call
await walletController.getAmountList();
} else if (messageData['notificationType'] == 8) {
chatController.startRingTone();
//AlarmHandler.scheduleAlarm();
chatController.chatList.clear();
chatController.update();
await chatController.getChatList(false);
debugPrint('chat resp-> $messageData');
} else if (messageData['notificationType'] == 2) {
//in background
callController.startRingTone();
await callController.getCallList(false);
} else if (messageData['notificationType'] == 9) {
reportController.reportList.clear();
reportController.update();
await reportController.getReportList(false);
} else if (messageData['notificationType'] == 12 ||
messageData['notificationType'] == 11 ||
messageData['notificationType'] == 10) {
liveAstrologerController.isUserJoinWaitList = true;
liveAstrologerController.update();
}
}
}
} catch (e) {
debugPrint("Exception in _firebaseMessagingBackgroundHandler else $e");
}
}
}
我的应用程序是
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
await GetStorage.init();
await AndroidAlarmManager.initialize();
if (Platform.isAndroid) {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform);
} else if (Platform.isIOS) {
await Firebase.initializeApp();
}
HttpOverrides.global = MyHttpOverrides();
runApp(
EasyLocalization(
supportedLocales: const [
Locale('en', 'US'),
],
path: 'assets/translations',
fallbackLocale: const Locale('en', 'US'),
startLocale: const Locale('en', 'US'),
child: const MyApp(),
),
);
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
dynamic analytics;
final apiHelper = APIHelper();
dynamic observer;
final liveAstrologerController = Get.put(LiveAstrologerController());
final walletController = Get.put(WalletController());
final chatController = Get.put(ChatController());
final callController = Get.put(CallController());
final timerController = Get.put(TimerController());
final reportController = Get.put(ReportController());
final networkController = Get.put(NetworkController());
@override
void initState() {
super.initState();
log('chat hascode MyApp ${chatController.hashCode}');
log('call hascode MyApp ${callController.hashCode}');
inthandlerbackgroudn();
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
if (message.notification!.title == "For Live Streaming Chat") {
String sessionType = message.data["sessionType"];
if (sessionType == "start") {
String? liveChatUserName2 = message.data['liveChatSUserName'];
if (liveChatUserName2 != null) {
liveAstrologerController.liveChatUserName = liveChatUserName2;
liveAstrologerController.update();
}
String chatId = message.data["chatId"];
liveAstrologerController.isUserJoinAsChat = true;
liveAstrologerController.update();
liveAstrologerController.chatId = chatId;
int waitListId = int.parse(message.data["waitListId"].toString());
String time = liveAstrologerController.waitList
.where((element) => element.id == waitListId)
.first
.time;
liveAstrologerController.endTime =
DateTime.now().millisecondsSinceEpoch +
1000 * int.parse(time.toString());
liveAstrologerController.update();
} else {
if (liveAstrologerController.isOpenPersonalChatDialog) {
Get.back(); //if chat dialog opended
liveAstrologerController.isOpenPersonalChatDialog = false;
}
liveAstrologerController.isUserJoinAsChat = false;
liveAstrologerController.chatId = null;
liveAstrologerController.update();
}
} else if (message.notification!.title ==
"For timer and session start for live") {
int waitListId = int.parse(message.data["waitListId"].toString());
liveAstrologerController.joinedUserName =
message.data["name"] ?? "User";
liveAstrologerController.joinedUserProfile =
message.data["profile"] ?? "";
String time = liveAstrologerController.waitList
.where((element) => element.id == waitListId)
.first
.time;
liveAstrologerController.endTime =
DateTime.now().millisecondsSinceEpoch +
1000 * int.parse(time.toString());
liveAstrologerController.update();
} else if (message.notification!.title == "Start simple chat timer") {
chatController.newIsStartTimer = true;
chatController.update();
timerController.endTime =
DateTime.now().millisecondsSinceEpoch + 1000 * 300;
timerController.update();
} else if (message.notification!.title == "End chat from customer") {
log('isInChatScreen ${chatController.isInChatScreen}');
if (chatController.isInChatScreen) {
chatController.updateChatScreen(false);
apiHelper.setAstrologerOnOffBusyline("Online");
chatController.update();
// Get.back();
} else {
log('do nothing chat dismiss');
}
} else if (message.notification!.title ==
"Reject call request from astrologer") {
print('user Rejected call request:-');
callController.isRejectCall = true;
callController.update();
callController.rejectDialog();
} else {
try {
if (message.data.isNotEmpty) {
var messageData = json.decode((message.data['body']));
log('noti body $messageData');
if (messageData['notificationType'] != null) {
if (messageData['notificationType'] == 7) {
// get wallet api call
await walletController.getAmountList();
NotificationHandler().foregroundNotification(message);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
} else if (messageData['notificationType'] == 8) {
log('inside foreground noti type 8');
chatController.startRingTone();
chatController.chatList.clear();
chatController.update();
await chatController.getChatList(false);
NotificationHandler().foregroundNotification(message);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
//SHOW CHAT DIALOG
} else if (messageData['notificationType'] == 2) {
callController.startRingTone();
log('iniside noti type 2');
callController.callList.clear();
callController.update();
await callController.getCallList(false);
NotificationHandler().foregroundNotification(message);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
} else if (messageData['notificationType'] == 9) {
reportController.reportList.clear();
reportController.update();
await reportController.getReportList(false);
NotificationHandler().foregroundNotification(message);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
} else if (messageData['notificationType'] == 12 ||
messageData['notificationType'] == 11 ||
messageData['notificationType'] == 10) {
liveAstrologerController.isUserJoinWaitList = true;
liveAstrologerController.update();
NotificationHandler().foregroundNotification(message);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
} else {
NotificationHandler().foregroundNotification(message);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
}
NotificationHandler().foregroundNotification(message);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
} else {
NotificationHandler().foregroundNotification(message);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
}
} else {
NotificationHandler().foregroundNotification(message);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
}
} catch (e) {
NotificationHandler().foregroundNotification(message);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
}
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
NotificationHandler().onSelectNotification(json.encode(message.data));
});
}
SplashController splashController = Get.put(SplashController());
@override
Widget build(BuildContext context) {
return GetBuilder<SplashController>(builder: (s) {
return Sizer(
builder: (context, orientation, deviceType) => GetMaterialApp(
debugShowCheckedModeBanner: false,
navigatorKey: Get.key,
enableLog: true,
theme: Themes.light,
darkTheme: Themes.dark,
themeMode: ThemeService().theme,
locale: context.locale,
localizationsDelegates: [
...context.localizationDelegates,
FallbackLocalizationDelegate()
],
supportedLocales: context.supportedLocales,
initialBinding: NetworkBinding(),
title: global.appName,
initialRoute: "SplashScreen",
home: SplashScreen(
a: analytics,
o: observer,
),
),
);
});
}
void inthandlerbackgroudn() async {
FirebaseMessaging messaging = FirebaseMessaging.instance;
FirebaseMessaging.onBackgroundMessage(handleBackgroundMessage);
await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: false,
);
}
}
我的 NotificaitonHandler 类是
class NotificationHandler {
final localNotifications = FlutterLocalNotificationsPlugin();
WalletController walletController = Get.put(WalletController());
ReportController reportController = Get.put(ReportController());
HomeController homecontroller = Get.put(HomeController());
SignupController signupController = Get.put(SignupController());
ChatController chatController = Get.find<ChatController>();
CallController callController = Get.find<CallController>();
Future<void> onSelectNotification(String payload) async {
Map<dynamic, dynamic> messageData;
try {
messageData = json.decode(payload);
Map<dynamic, dynamic> body;
body = jsonDecode(messageData['body']);
if (body["notificationType"] == 7) {
await walletController.getAmountList();
Get.to(() => WalletScreen());
} else if (body["notificationType"] == 8) {
chatController.stopRingtone();
Get.find<HomeController>().homeTabIndex = 0;
Get.find<HomeController>().update();
Get.to(() => const HomeScreen());
} else if (body["notificationType"] == 2) {
callController.stopRingtone();
debugPrint('list length ${callController.callList.length}');
callController.callList
.removeWhere((call) => call.callId == body['callId']);
callController.update();
if (body['call_type'].toString() == '10') {
callController.acceptCallRequest(
body['callId'],
body['profile'],
body['name'],
body['id'],
body['fcmToken'],
body['call_duration']);
} else if (body['call_type'].toString() == '11') {
callController.acceptVideoCallRequest(
body['callId'],
body['profile'],
body['name'],
body['id'],
body['fcmToken'],
body['call_duration']);
}
Get.find<HomeController>().homeTabIndex = 2; //pageview index
Get.find<HomeController>().isSelectedBottomIcon = 1; // bottom bar index
Get.find<HomeController>().update();
} else if (body["notificationType"] == 9) {
} else if (body["notificationType"] == 13) {
if (Get.find<HomeController>().notificationHandlingremoteUID != 0) {
global.showToast(message: 'You are already live, end call first');
} else {}
}
} catch (e) {
debugPrint(
'Exception in onSelectNotification main.dart:- ${e.toString()}',
);
}
}
Future<void> foregroundNotification(RemoteMessage payload) async {
final DarwinInitializationSettings initializationSettingsDarwin =
DarwinInitializationSettings(
defaultPresentBadge: true,
requestSoundPermission: true,
requestBadgePermission: true,
defaultPresentSound: true,
onDidReceiveLocalNotification: (id, title, body, payload) async {
debugPrint("object notification call");
return;
},
);
AndroidInitializationSettings android =
const AndroidInitializationSettings('@mipmap/ic_launcher');
final InitializationSettings initialSetting = InitializationSettings(
android: android, iOS: initializationSettingsDarwin);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
flutterLocalNotificationsPlugin.initialize(initialSetting,
onDidReceiveNotificationResponse: (_) {
NotificationHandler().onSelectNotification(json.encode(payload.data));
});
AndroidNotificationChannel channel = const AndroidNotificationChannel(
' local notifications',
'High Importance Notifications for ',
importance: Importance.high,
);
AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
channel.id,
channel.name,
importance: Importance.max,
priority: Priority.high,
icon: "@mipmap/ic_launcher",
playSound: false,
styleInformation: const BigTextStyleInformation(''),
);
const DarwinNotificationDetails iOSDetails = DarwinNotificationDetails();
NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidDetails, iOS: iOSDetails);
global.sp = await SharedPreferences.getInstance();
if (global.sp!.getString("currentUser") != null) {
await flutterLocalNotificationsPlugin.show(
0,
payload.notification!.title,
payload.notification!.body,
platformChannelSpecifics,
payload: json.encode(payload.data.toString()),
);
}
} } 我在我的应用程序中收到两个不同的聊天控制器实例的 hascode,并且 onselected 通知有
[log] chat hascode MyApp 445182886
[log] chat hascode bghandler 668612596
[log] chat hascode NotificationHandler 445182886
好吧,第一件事是我的方法是完全错误的,我正在使用自己的音频播放器来响铃并停止,这不是个好主意,因为 firebase 消息处理程序已经是一个单独运行的隔离,因此在其中创建的实例具有与 myapp 中创建的不同的引用,因此我发现的解决方案是直接使用 firebase 消息传递和 flutter_notification 的内置功能,我在这里做了什么 第一个 api 端你必须通过
[
'title' => 'Hey User you received a chat request from John Doe',
'body' => [
'description' => 'Hey you received a chat request from User' . $user[0]->name,
'notificationType' => 8,
'icon' => 'public/notification-icon/chat.png',
],
'android' => [
'notification' => [
'channel_id' => 'channel_id_13',
'sound' =>'app_sound' // don't use app_sound.mp3 or .wav only name
]
],
'apns' =>[
'payload' => [
'aps' => [
'sound' => 'app_sound.wav'
]
]
]
];
请记下您必须设置声音和channel_id
'android' => [
'notification' => [
'channel_id' => 'channel_id_13',
'sound' =>'app_sound'
]
],
并在 Android 清单和代码中的应用程序端使用它们,就像我在下面所做的那样
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@mipmap/ic_launcher" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="channel_id_13"/>
在你的清单应用程序标签中记住添加相同的频道 ID
android:value="channel_id_13"
现在在我们的代码中,我们可以创建支持后台和前台的通知是
Future<void> foregroundNotificatioCustomAuddio(RemoteMessage payload) async {
final initializationSettingsDarwin = DarwinInitializationSettings(
defaultPresentBadge: true,
requestSoundPermission: true,
requestBadgePermission: true,
defaultPresentSound: false,
onDidReceiveLocalNotification: (id, title, body, payload) async {
return;
},
);
final android = const AndroidInitializationSettings('@mipmap/ic_launcher');
final initialSetting = InitializationSettings(
android: android, iOS: initializationSettingsDarwin);
localNotifications.initialize(initialSetting,
onDidReceiveNotificationResponse: (_) {
onSelectNotification(json.encode(payload.data));
});
final customSound = 'app_sound.wav';
AndroidNotificationDetails androidDetails =
const AndroidNotificationDetails(
'channel_id_14',
'channel.name',
importance: Importance.max,
icon: "@mipmap/ic_launcher",
playSound: true,
enableVibration: true,
timeoutAfter: 10000,
sound: RawResourceAndroidNotificationSound('app_sound'),
);
DarwinNotificationDetails iOSDetails = DarwinNotificationDetails(
sound: customSound,
);
final platformChannelSpecifics =
NotificationDetails(android: androidDetails, iOS: iOSDetails);
global.sp = await SharedPreferences.getInstance();
if (global.sp!.getString("currentUser") != null) {
await localNotifications.show(
10,
payload.notification!.title,
payload.notification!.body,
platformChannelSpecifics,
payload: json.encode(payload.data.toString()),
);
}
}
final localNotifications = FlutterLocalNotificationsPlugin();
现在从
打电话 FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
NotificationHandler()
.foregroundNotificatioCustomAuddio(message);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, badge: true, sound: true);
}
对于背景,现在 firebase 自动处理通知,现在请记住在您的 android/app/src/main/res/raw/app_sound.wav 中添加 app_sound.wav 格式铃声,这样它就可以工作了,我已经在 android 9 和 android 10 中测试了这些