inway / flutter_ringtone_player

Simple Flutter plugin to play ringtone, alarm & notification sounds
MIT License
89 stars 57 forks source link

How to stop Flutter Ringtone Player on background notification #71

Open KetutKusuma opened 6 months ago

KetutKusuma commented 6 months ago

i was use the flutter ringtone player on background and the sound is playing, now i want to stop it on the notification where is the notification has action button (using awesomenotification), it is not working and i found some reference on this github issues but it's not working to me

the code on the main :

Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  log("Handling a background body: ${message.notification!.body}");
  await Firebase.initializeApp();
  String? body = message.notification!.body;
  if (body != null) {
    if (body.contains('Public Safety Center')) {
      ReceivePort receiver = ReceivePort();
      IsolateNameServer.registerPortWithName(receiver.sendPort, isolateName);

      receiver.listen((message) async {
        print('uhuy listennn');
        if (message == "stop") {
          await FlutterRingtonePlayer.stop();
        }
      });
      FlutterRingtonePlayer.play(
        fromAsset: 'assets/sound/vintage_alarm.wav',
        volume: 0.8,
        looping: false,
        asAlarm: true,
      );
      await AwesomeNotifications().createNotification(
        content: NotificationContent(
          id: message.notification.hashCode,
          channelKey: 'alerts',
          title: message.notification!.title,
          body: message.notification!.body,
          notificationLayout: NotificationLayout.Default,
          wakeUpScreen: true,
          category: NotificationCategory.Alarm,
          locked: true,
          autoDismissible: false,
          summary: 'Notif',
        ),
        actionButtons: [
          NotificationActionButton(
            key: 'STOP',
            label: 'stop',
            actionType: ActionType.SilentBackgroundAction,
            isDangerousOption: false,
          )
        ],
      );
    }
  }
}

the main :

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  await FirebaseApi().initNotification();
  await NotificationController.initializeIsolateReceivePort();
  await NotificationController.initializeLocalNotifications();
  await NotificationController.startListeningNotificationEvents();
  await dotenv.load(fileName: '.env');
  runApp(const MyApp());
}

and the notification controller :

class NotificationController {
  static ReceivedAction? initialAction;

  ///  *********************************************
  ///     INITIALIZATIONS
  ///  *********************************************
  ///
  static Future<void> initializeLocalNotifications() async {
    await AwesomeNotifications().initialize(
      // 'assets/logo/logo_bsc_warna.png',
      null,
      [
        NotificationChannel(
          channelKey: 'alerts',
          channelName: 'Alerts',
          channelDescription: 'Notification tests as alerts',
          playSound: true,
          onlyAlertOnce: true,
          groupAlertBehavior: GroupAlertBehavior.Children,
          importance: NotificationImportance.High,
          defaultPrivacy: NotificationPrivacy.Private,
          defaultColor: primaryColor,
          ledColor: primaryColor,
        )
      ],
      debug: true,
    );

    // Get initial notification action is optional
    initialAction = await AwesomeNotifications()
        .getInitialNotificationAction(removeFromActionEvents: false);
  }

  static ReceivePort? receivePort;
  static Future<void> initializeIsolateReceivePort() async {
    receivePort = ReceivePort('Notification action port in main isolate')
      ..listen(
          (silentData) => onActionReceivedImplementationMethod(silentData));

    // This initialization only happens on main isolate
    IsolateNameServer.registerPortWithName(
        receivePort!.sendPort, 'notification_action_port');
  }

  ///  *********************************************
  ///     NOTIFICATION EVENTS LISTENER
  ///  *********************************************
  ///  Notifications events are only delivered after call this method
  static Future<void> startListeningNotificationEvents() async {
    log('start listening notification');
    AwesomeNotifications().setListeners(
      onActionReceivedMethod: onActionReceivedMethod,
      onDismissActionReceivedMethod: onDismissActionReceivedMethod,
      onNotificationCreatedMethod: onNotificationCreatedMethod,
      onNotificationDisplayedMethod: onNotificationDisplayedMethod,
    );
  }

  ///  *********************************************
  ///     NOTIFICATION EVENTS
  ///  *********************************************
  ///
  @pragma('vm:entry-point')
  static Future<void> onActionReceivedMethod(
      ReceivedAction receivedAction) async {
    log('action : $receivedAction');
    if (receivedAction.actionType == ActionType.SilentBackgroundAction ||
        receivedAction.actionType == ActionType.SilentAction) {
      log('SILENT ACTION');
      stopAudio();
    }
    stopAudio();
    log('receivee action : ${receivedAction.actionType}');

    return onActionReceivedImplementationMethod(receivedAction);
  }

  @pragma("vm:entry-point")
  static Future<void> onNotificationCreatedMethod(
      ReceivedNotification receivedNotification) async {
    // Your code goes here
    log('MASUK CREATE');
  }

  /// Use this method to detect every time that a new notification is displayed
  @pragma("vm:entry-point")
  static Future<void> onNotificationDisplayedMethod(
      ReceivedNotification receivedNotification) async {
    // Your code goes here
    log('MASUK DISPLAYED');
  }

  /// Use this method to detect if the user dismissed a notification
  @pragma("vm:entry-point")
  static Future<void> onDismissActionReceivedMethod(
      ReceivedAction receivedAction) async {
    // Your code goes here
    log('MASUK DISMISS');
    stopAudio();
  }

  static Future<void> onActionReceivedImplementationMethod(
      ReceivedAction receivedAction) async {
    log('RECEIVE GENG UHUY');
    navKey.currentState!.pushAndRemoveUntil(
        MaterialPageRoute(
          builder: (context) => const BerandaView(),
        ), (action) {
      return true;
    }
        // '/notification-page',
        // (route) => (route.settings.name != '/notification-page') || route.isFirst,
        // arguments: receivedAction,
        );
  }

  ///  *********************************************
  ///     REQUESTING NOTIFICATION PERMISSIONS
  ///  *********************************************
  ///
  static Future<bool> displayNotificationRationale() async {
    bool userAuthorized = false;
    BuildContext context = navKey.currentContext!;
    await showDialog(
        context: context,
        builder: (BuildContext ctx) {
          return AlertDialog(
            title: Text('Get Notified!',
                style: Theme.of(context).textTheme.titleLarge),
            content: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Row(
                  children: [
                    Expanded(
                      child: Image.asset(
                        logo,
                        height: MediaQuery.of(context).size.height * 0.3,
                        fit: BoxFit.fitWidth,
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 20),
                const Text(
                    'Allow Awesome Notifications to send you beautiful notifications!'),
              ],
            ),
            actions: [
              TextButton(
                  onPressed: () {
                    Navigator.of(ctx).pop();
                  },
                  child: Text(
                    'Deny',
                    style: Theme.of(context)
                        .textTheme
                        .titleLarge
                        ?.copyWith(color: Colors.red),
                  )),
              TextButton(
                  onPressed: () async {
                    userAuthorized = true;
                    Navigator.of(ctx).pop();
                  },
                  child: Text(
                    'Allow',
                    style: Theme.of(context)
                        .textTheme
                        .titleLarge
                        ?.copyWith(color: Colors.deepPurple),
                  )),
            ],
          );
        });
    return userAuthorized &&
        await AwesomeNotifications().requestPermissionToSendNotifications();
  }

  ///  *********************************************
  ///     NOTIFICATION CREATION METHODS
  ///  *********************************************
  ///
  static Future<void> createNewNotification(RemoteMessage remoteMessage,
      {bool isPsc = false}) async {
    bool isAllowed = await AwesomeNotifications().isNotificationAllowed();
    if (!isAllowed) isAllowed = await displayNotificationRationale();
    if (!isAllowed) return;
    // AwesomeNotifications().
    if (isPsc) {
      log('open the audio');
      await FlutterRingtonePlayer.play(
        fromAsset: 'assets/sound/vintage_alarm.wav',
        volume: 0.05,
        looping: true,
        asAlarm: true,
      );
    }
    log('psc ?? $isPsc');
    RemoteNotification? remoteNotification = remoteMessage.notification;
    Map<String, String?>? payload = {
      'uhuy': 'uhuy',
    };
    await AwesomeNotifications().createNotification(
      content: NotificationContent(
        id: remoteNotification.hashCode, // -1 is replaced by a random number
        channelKey: 'alerts',
        title: remoteNotification!.title,
        body: remoteNotification.body,
        // icon: 'assets/logo/logo_bsc_warna.png',
        //'asset://assets/images/balloons-in-sky.jpg',
        notificationLayout: NotificationLayout.Default,
        wakeUpScreen: true,
        // criticalAlert: true,
        locked: isPsc ? true : false,
        autoDismissible: false,
        summary: 'Notif',
        payload: payload,
      ),
      actionButtons: !isPsc
          ? null
          : [
              NotificationActionButton(
                key: 'STOP',
                label: 'stop',
                actionType: ActionType.DismissAction,
                isDangerousOption: false,
              )
            ],
    );
  }

  static Future<void> createNewNotificationSchedule(RemoteMessage remoteMessage,
      {bool isPsc = false}) async {
    bool isAllowed = await AwesomeNotifications().isNotificationAllowed();
    if (!isAllowed) isAllowed = await displayNotificationRationale();
    if (!isAllowed) return;

    RemoteNotification? remoteNotification = remoteMessage.notification;
    Map<String, String?>? payload = {
      'uhuy': 'uhuy',
    };

    await AwesomeNotifications().createNotification(
      content: NotificationContent(
        id: remoteNotification.hashCode, // -1 is replaced by a random number
        channelKey: 'alerts',
        title: remoteNotification!.title,
        body: remoteNotification.body,
        notificationLayout: NotificationLayout.Default,
        wakeUpScreen: true,
        locked: isPsc ? true : false,
        autoDismissible: false,
        summary: 'Notif',
        payload: payload,
        customSound: 'assets/sound/vintage_alarm.wav',
        displayOnBackground: true,
        displayOnForeground: true,
      ),
      // schedule: NotificationInterval(
      //   interval: 60,
      //   preciseAlarm: true,
      //   repeats: true,
      //   timeZone: AwesomeNotifications.localTimeZoneIdentifier,
      // ),
      actionButtons: !isPsc
          ? null
          : [
              NotificationActionButton(
                key: 'STOP',
                label: 'stop',
                actionType: ActionType.DismissAction,
                isDangerousOption: false,
              )
            ],
    );
  }

  static Future<void> resetBadgeCounter() async {
    await AwesomeNotifications().resetGlobalBadge();
  }

  static Future<void> cancelNotifications() async {
    await AwesomeNotifications().cancelAll();
  }
}

please tell me if this issue can be solve, thankyou

Kanwarpalsingh1986 commented 3 months ago

same issue here

mdaniyal9 commented 2 months ago

any update on this?

rameshnittali commented 1 month ago

Any update on this? Even I am facing the same issue.

ijascookee commented 1 month ago

Any update on this

rameshnittali commented 1 month ago

I did a workaround using Flutter local notification package, where I removed the "notifications" from the FCM payload so that it is treated as a background message, thus the notification is handled by the flutter local notification and provide the respective sound file to the notification. Here is the answer from stackoverflow that helped me : https://stackoverflow.com/a/76335830/2144478