Ожидаемое поведение: < /h3>
Звук должен останавливаться, когда пользователь нажимает на уведомление, независимо от того, находится ли приложение на переднем плане, фоновом плане или инактивном. Проблема: < /h3>
Если приложение активно или на заднем плане, звук правильно останавливается, когда уведомление нажимается. Аудиоплеер, когда он неактивен, и я изо всех сил пытаюсь реализовать решение, которое правильно обрабатывает этот сценарий.main.dart
import 'dart:developer';
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:maalik/app.dart';
import 'package:maalik/services/firebase_api.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'firebase_options.dart';
import 'package:flutter/material.dart';
String? fcmToken;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
FirebaseMessaging.instance.getInitialMessage();
await NotificationServices.initLocalNotification();
final notificationServices = NotificationServices();
fcmToken = await notificationServices.initFcmNotification();
FlutterError.onError = (errorDetails) {
FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
};
PlatformDispatcher.instance.onError = (error, stack) {
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
return true;
};
FirebaseCrashlytics.instance.app.setAutomaticDataCollectionEnabled(false);
await SharedPreferences.getInstance().then((value) {
runApp(const MyApp());
});
FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
NotificationServices().listenNotification();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
log('Notification clicked: ${message.notification}');
_stopAudio(); // Stop the audio when notification is tapped
});
}
@pragma('vm:entry-point')
Future _stopAudio() async {
try {
if (player != null) {
await player!.stop();
await player!.release();
player = null;
log("Audio stopped from background notification");
}
} catch (e) {
log("Error stopping audio: $e");
}
}
@pragma('vm:entry-point')
Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
log('Raw Message Data: ${message.data}');
log('Message Origin: ${message.senderId}');
log("Handling background message: ${message.notification}");
if (message.data['channelId'] == 'order_received') {
audioPlayerStart();
}
}
< /code>
firebase_api.dart
import 'dart:developer';import 'package:audioplayers/audioplayers.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:maalik/main.dart';
import 'package:sound_mode/sound_mode.dart';
import 'package:volume_controller/volume_controller.dart';
AudioPlayer? player;
class NotificationServices {
final _firebaseMessaging = FirebaseMessaging.instance;
static final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
static Future initLocalNotification({bool isScheduled = false}) async {
final androidInit = AndroidInitializationSettings('@mipmap/launcher_icon');
final iosInit = DarwinInitializationSettings();
final initSetting = InitializationSettings(android: androidInit, iOS: iosInit);
await _flutterLocalNotificationsPlugin.initialize(
initSetting,
onDidReceiveNotificationResponse: (NotificationResponse response) async {
log("Notification clicked: ${response.payload}");
if (player != null) {
await player!.stop();
await player!.release();
player = null;
log("Audio stopped");
}
},
onDidReceiveBackgroundNotificationResponse: _backgroundNotificationHandler,
);
log("inside initlocalNotification");
AndroidNotificationChannel orderReceiveChannel = AndroidNotificationChannel(
'order_received',
'Order Notification Channel',
description: 'Order Notification Channel',
enableVibration: true,
importance: Importance.max,
playSound: false,
sound: RawResourceAndroidNotificationSound('notification'),
);
const AndroidNotificationChannel otherNotificationChannel =
AndroidNotificationChannel(
'other_notification',
'Other Notification Channel',
description: 'Other Notification Channel',
enableVibration: true,
importance: Importance.max,
playSound: true,
);
await _flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation()
?.createNotificationChannel(orderReceiveChannel);
await _flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation()
?.createNotificationChannel(otherNotificationChannel);
}
Future initFcmNotification() async {
validateSoundFile();
try {
await _firebaseMessaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
log("inside request permission");
} catch (e) {
print(e);
}
try {
final fcmToken = await _firebaseMessaging.getToken();
log('fcmToken: $fcmToken');
return fcmToken;
} catch (e) {
print(e);
}
return '';
}
listenNotification() {
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
log("inside listenNotification");
if (message.data['channelId'] == 'order_received') {
audioPlayerStart();
}
if (notification != null && android != null) {
AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
message.data['channelId'] ?? 'other_notification',
'Order Notification Channel',
playSound: false,
sound: RawResourceAndroidNotificationSound('notification'),
priority: Priority.max,
);
DarwinNotificationDetails iosDetails = DarwinNotificationDetails(
sound: 'notification.wav',
);
NotificationDetails notificationDetails = NotificationDetails(
android: androidDetails,
iOS: iosDetails,
);
_flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
notificationDetails,
);
}
});
}
}
@pragma('vm:entry-point')
void audioPlayerStart() async {
try {
var ringer_mode = await SoundMode.ringerModeStatus;
if (ringer_mode.name == 'normal') {
VolumeController volumeController = VolumeController();
volumeController.maxVolume(showSystemUI: false);
if (player == null) {
player = AudioPlayer(playerId: "customNotificationPlayer");
await player?.setVolume(1.0);
}
if (player != null) {
await player!.play(AssetSource('notification.mp3'));
await Future.delayed(Duration(minutes: 2));
await player!.stop();
await player!.release();
await player!.dispose();
player = null;
}
}
} catch (e) {
print("Error playing sound: $e");
}
}
@pragma('vm:entry-point')
void _backgroundNotificationHandler(NotificationResponse response) {
log("Background notification clicked");
_stopAudio();
}
Подробнее здесь: https://stackoverflow.com/questions/793 ... s-inactive