Lex
Lex

Reputation: 121

Flutter Awesome notifications not showing in background or when app is terminated

Good day.

I am using Awesome notifications in a food ordering app to notify users when their food is ready.

Notifications come through when the app is open, but not when the app is in the background/terminated. Once I re-open the app, all the notifcations that triggered while the app was in the background/terminated come through at once.

I have activated listeners in my main.dart file. These listeners listen for changes made to the my database (I am using Firebase), and generate local notifications when specific changes occur. For example, if the "order status" attribute in the database changes from "accepted" to "completed", the user will get a notification that their order is ready to collect.

Am I missing something? I thought this plugin automatically handled notifcations when the app is in the background or is terminated.

Any help would be greatly appreciated!!

Listeners are activated in my main.dart file when the app builds and a user is logged in:

class AuthenticationWrapper extends StatelessWidget {
  const AuthenticationWrapper({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => Scaffold(
        body: StreamBuilder<User?>(
          stream: FirebaseAuth.instance.authStateChanges(),
          builder: (context, snapshot) {
            if (snapshot.hasError) {
              return const Center(child: Text("Something went wrong :("));
            } else if (snapshot.hasData) {
              //The following methods are only executed if a user is logged in.
              //The methods below require the userID, therefore the user must fist be logged in for them to work
              listenForAcceptedOrders();
              listenForRejectedOrders();
              listenForCompletedOrders();

              //Listner for tapping on a notification or dismissing one
              AwesomeNotifications().setListeners(
                  onActionReceivedMethod:
                      NotificationController.onActionReceivedMethod,
                  onDismissActionReceivedMethod:
                      NotificationController.onDismissActionReceivedMethod);

              return const HomePage();
            } else {
              return SignInPage();
            }
          },
        ),
      );
}

The notificationlistner methods:

void listenForAcceptedOrders() async {
  print("Current User ID-------->>>$loggedInUserID");
//This method listens for accepted orders and displays a notification
//It checks for new records entered into the managedOrders table containing the same customerID as the user currently logged in.
//If the customerID matches the ID of the current user logged in, it means that an order placed by THIS user has been accepted.
  _orderStream = _dbRef.child("ManagedOrders").onChildAdded.listen((event) {
    databaseMapper = event.snapshot.value as Map;
    String customerID = databaseMapper["customerID"].toString();
    String orderNum = databaseMapper["orderNum"].toString();
    String status = databaseMapper["status"].toString();

    print("CUSTOMERID ______......>>$customerID");

    if (customerID == loggedInUserID && status == "accepted") {
      acceptedOrderNotification(orderNum);
    } else {
      print("NO MATCH FOUND");
    }
  });
}

void listenForRejectedOrders() async {
  print("Current User ID-------->>>$loggedInUserID");
//This method listens for rejected orders and displays a notification
//It checks for new records entered into the managedOrders table containing the same customerID as the user currently logged in AND a status = rejetced
//If the customerID matches the ID of the current user logged in, it means that an order placed by THIS user has been accepted.
  _orderStream = _dbRef.child("ManagedOrders").onChildAdded.listen((event) {
    databaseMapper = event.snapshot.value as Map;
    String customerID = databaseMapper["customerID"].toString();
    String orderNum = databaseMapper["orderNum"].toString();
    String status = databaseMapper["status"].toString();

    print("CUSTOMERID ______......>>$customerID");

    if (customerID == loggedInUserID && status == "rejected") {
      rejectedOrderNotification(orderNum);
    }
  });
}

void listenForCompletedOrders() async {
//This method listens for completed orders and displays a notification
//It checks for new records entered into the CompleteOrders table containing the same customerID as the user currently logged in.
//If the customerID matches the ID of the current user logged in, it means that an order placed by THIS user has been completed.

  _orderStream = _dbRef.child("CompleteOrders").onChildAdded.listen((event) {
    databaseMapper = event.snapshot.value as Map;
    String customerID = databaseMapper["customerID"].toString();
    String orderNum = databaseMapper["orderNum"].toString();

    if (customerID == loggedInUserID) {
      completedOrderNotification(orderNum);
    } else {
      print("NO MATCH FOUND");
    }
  });

Notifications code:

import 'package:awesome_notifications/awesome_notifications.dart';

Future<void> placeOrderNotification(String orderNo) async {
  await AwesomeNotifications().createNotification(
      content: NotificationContent(
          id: 001,
          channelKey: 'basic_channel',
          title:
              "${Emojis.activites_balloon} Your order request has been sent! (OrderNo: $orderNo)",
          body: "Nandos will update your order status shortly..."));
}

Future<void> acceptedOrderNotification(String orderNo) async {
  await AwesomeNotifications().createNotification(
      content: NotificationContent(
          id: 002,
          channelKey: 'basic_channel',
          title:
              "${Emojis.hand_thumbs_up} Your order (OrderNo: $orderNo) has been accepted!",
          body: "Nandos is now preparing your order"));
}

Future<void> rejectedOrderNotification(String orderNo) async {
  await AwesomeNotifications().createNotification(
      content: NotificationContent(
          id: 003,
          channelKey: 'basic_channel',
          title:
              "${Emojis.hand_thumbs_down} Your order (OrderNo: $orderNo) has been rejected!",
          body: "Nandos cannot take your order at this time"));
}

Future<void> completedOrderNotification(String orderNo) async {
  await AwesomeNotifications().createNotification(
      content: NotificationContent(
          id: 004,
          channelKey: 'basic_channel',
          title:
              "${Emojis.activites_fireworks} Your order (OrderNo: $orderNo) is ready to be collected!",
          body: "Please go collect your order at Nandos"));
}

Upvotes: 5

Views: 4205

Answers (2)

Paras Palli
Paras Palli

Reputation: 211

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />    
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>

// Inside Application Tags

        <receiver android:name="me.carda.awesome_notifications.core.broadcasters.receivers.ScheduledNotificationReceiver" android:exported="true" />
        <receiver android:name="me.carda.awesome_notifications.core.broadcasters.receivers.RefreshSchedulesReceiver" android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.QUICKBOOT_POWERON" />
            </intent-filter>
        </receiver>

Upvotes: 0

Pavel Galaktionov
Pavel Galaktionov

Reputation: 11

I had the same problem. Solution, that works for me, is to change importance from NotificationImportance.Max to NotificationImportance.High. Now, notifications are displaying in backgroud app too. See code snippet below...

class NotificationService {
  static ReceivedAction? initialAction;

  static Future<void> initializeNotification() async {
    await AwesomeNotifications().initialize(
      null,
      [
        NotificationChannel(
          channelGroupKey: 'high_importance_channel',
          channelKey: 'high_importance_channel',
          channelName: 'Basic notifications',
          channelDescription: 'Notification channel for basic tests',
          defaultColor: const Color(0xFF9D50DD),
          ledColor: Colors.white,
          importance: **NotificationImportance.High**,//NotificationImportance.Max
          channelShowBadge: true,
          onlyAlertOnce: true,
          playSound: true,
          criticalAlerts: true,
        )
      ],
      channelGroups: [
        NotificationChannelGroup(
          channelGroupKey: 'high_importance_channel_group',
          channelGroupName: 'Group 1',
        )
      ],
      debug: true,
    );

...
}

Upvotes: 1

Related Questions