Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onDidReceiveNotificationResponse DID NOT TRIGGER WHEN APP IS IN FOREGROUD #2390

Open
Abdulah-butt opened this issue Aug 19, 2024 · 5 comments

Comments

@Abdulah-butt
Copy link

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_timezone/flutter_timezone.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sos_cameroon/app/common/shared_preference_manager.dart';

import 'package:sos_cameroon/src/features/notifications/data/repositories/local_notification_service.dart';
import 'package:timezone/data/latest_all.dart' as tz;
import 'package:timezone/timezone.dart' as tz;

import '../../models/schedule_notification_model.dart';

@pragma('vm:entry-point')
void notificationTapBackground(NotificationResponse notificationResponse) {
  // ignore: avoid_print
  print('notification(${notificationResponse.id}) action tapped: '
      '${notificationResponse.actionId} with'
      ' payload: ${notificationResponse.payload}');
  if (notificationResponse.input?.isNotEmpty ?? false) {
    // ignore: avoid_print
    print(
        'notification action tapped with input: ${notificationResponse.input}');
  }
}

class FlutterLocalNotification implements LocalNotificationService {
  final SharedPreferences _sharedPreferences =
      SharedPreferencesManager.instance;
  final StreamController<String?> _selectNotificationStream =
      StreamController<String?>.broadcast();

  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();

  final AndroidNotificationDetails _channel = const AndroidNotificationDetails(
      'default_notification_channel_id', // id
      'High Importance Notifications', // title
      // description
      importance: Importance.high,
      enableLights: true,
      playSound: true);

  @override
  Future<void> initialize() async {
    await _configureLocalTimeZone();
    await _configureNotifications();
  }

  Future<bool> _isAlreadyScheduled() async {
    return _sharedPreferences.getBool("local_notification_schedule") ?? false;
  }

  Future<bool> _localNotificationScheduled() async {
    return _sharedPreferences.setBool("local_notification_schedule", true);
  }

  Future<void> _configureNotifications() async {
    const AndroidInitializationSettings initializationSettingsAndroid =
        AndroidInitializationSettings('@mipmap/ic_launcher');
    final DarwinInitializationSettings initializationSettingsDarwin =
        DarwinInitializationSettings(
      requestAlertPermission: true,
      requestBadgePermission: true,
      requestSoundPermission: true,
      onDidReceiveLocalNotification:
          (int id, String? title, String? body, String? payload) async {},
    );
    final InitializationSettings initializationSettings =
        InitializationSettings(
      android: initializationSettingsAndroid,
      iOS: initializationSettingsDarwin,
      macOS: initializationSettingsDarwin,
    );

    await flutterLocalNotificationsPlugin.initialize(
      initializationSettings,
      onDidReceiveNotificationResponse:onNotificationTap,
      onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
    );

  }

// on tap on any notification
  static void onNotificationTap(NotificationResponse notificationResponse) {
    // _selectNotificationStream.add(notificationResponse.payload!);
    debugPrint("NOTIFICATION IS TAPPED +++++++++++");
  }

  @override
  Future<String?> notificationPayloadFromWhichAppOpened() async {
    final NotificationAppLaunchDetails? notificationAppLaunchDetails =
        !kIsWeb && Platform.isLinux
            ? null
            : await flutterLocalNotificationsPlugin
                .getNotificationAppLaunchDetails();
    if (notificationAppLaunchDetails?.didNotificationLaunchApp ?? false) {
      String? selectedNotificationPayload =
          notificationAppLaunchDetails!.notificationResponse?.payload;
      return selectedNotificationPayload;
    }
    return null;
  }

  @override
  Future<void> requestPermissions() async {
    await _requestPermissions();
  }

  @override
  Future<void> scheduleNotification(
      {required int id,
      required String title,
      required String description,
      String? payload,
      required Duration durationFromCurrentTime}) async {
    debugPrint(
        "NOTIFICATION SCHEDULED AT+++++++ $durationFromCurrentTime ++++ ${tz.TZDateTime.now(tz.local).add(durationFromCurrentTime)}");
    await flutterLocalNotificationsPlugin.zonedSchedule(
        id,
        title,
        description,
        payload: payload,
        tz.TZDateTime.now(tz.local).add(durationFromCurrentTime),
        NotificationDetails(android: _channel),
        androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
        uiLocalNotificationDateInterpretation:
            UILocalNotificationDateInterpretation.absoluteTime);
  }

  Future<void> _configureLocalTimeZone() async {
    if (kIsWeb || Platform.isLinux) {
      return;
    }
    tz.initializeTimeZones();
    final String timeZoneName = await FlutterTimezone.getLocalTimezone();
    tz.setLocalLocation(tz.getLocation(timeZoneName));
  }

  Future<void> _requestPermissions() async {
    if (Platform.isIOS || Platform.isMacOS) {
      await flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              IOSFlutterLocalNotificationsPlugin>()
          ?.requestPermissions(
            alert: true,
            badge: true,
            sound: true,
          );
      await flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              MacOSFlutterLocalNotificationsPlugin>()
          ?.requestPermissions(
            alert: true,
            badge: true,
            sound: true,
          );
    } else if (Platform.isAndroid) {
      final AndroidFlutterLocalNotificationsPlugin? androidImplementation =
          flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<
              AndroidFlutterLocalNotificationsPlugin>();
      final bool? grantedNotificationPermission =
          await androidImplementation?.requestNotificationsPermission();
      // If the app requires scheduling notifications with exact timings
      await AndroidFlutterLocalNotificationsPlugin()
          .requestExactAlarmsPermission();
    }
  }

  @override
  Future<void> scheduleAllNotificationsFromJson() async {
    // 1. FIRST CHECK IF NOTIFICATION ALREADY SCHEDULES OR NOT

    // if(await _isAlreadyScheduled()){
    //   debugPrint("NOTIFICATIONS ARE ALREADY SCHEDULED ++++++");
    //   return;
    // }

    List<ScheduleNotificationModel> scheduleNotifications =
        await _loadNotifications();
    for (int index = 0; index < scheduleNotifications.length; index++) {
      ScheduleNotificationModel notification = scheduleNotifications[index];
      LocaleData localeData = notification.locales!['en']!;
      scheduleNotification(
        id: index,
        title: localeData.title ?? "N/A",
        description: localeData.description ?? "N/A",
        payload: json.encode(notification.toJson()),
        durationFromCurrentTime: Duration(
          days: ((notification.day ?? 1) - 1),
          hours: notification.hour ?? 0,
          minutes: notification.minute ?? 0,
          seconds: notification.second ?? 0,
        ),
      );
    }
    _localNotificationScheduled();
  }

  /// Read json according to current locale
  Future<List<ScheduleNotificationModel>> _loadNotifications() async {
    // final  currentLocale = Localizations.localeOf(context);
    // debugPrint("CURRENT LOCALE : ${currentLocale.languageCode}");
    final jsonString =
        await rootBundle.loadString('assets/local_notifications/mock.json');
    final jsonData = json.decode(jsonString) as List<dynamic>;
    return jsonData
        .map((json) => ScheduleNotificationModel.fromJson(json))
        .toList();
  }

  @override
  Stream<String?> selectNotificationStream() {
    return _selectNotificationStream.stream;
  }
}

@Roshan-pcy
Copy link

i have face same issue did get any solution?

@AmirmohammadNemati
Copy link

i have this problem too

@ced1check
Copy link

Same problem here, running on Android, any solutions, are we missing some specific setup?
Will try iOS pretty soon.

@ced1check
Copy link

Worked-around using response here: #2315 (comment)

@MaikuB
Copy link
Owner

MaikuB commented Oct 3, 2024

For those that say that they are facing this issue, check to ensure you have done all the configuration mentioned in the readme. If you have done so and still face an issue, please provide a link to a repository hosting a minimal app that can reproduce the problem. This could be one you've created yourself or another way is to fork the repository and update the example app

Edit: please also mention the platform you encounter the issue on. If you provide a the repo, also include mention that Flutter version. Expectation is I should be able to clone the repository and reproduce the issue easily. Providing code snippets doesn't help as it's missing the native configuration

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants