How do I send a notification to another user when one user presses a button? Can someone show me a code snippet?

I realize that this question was asked before, however, it was closed since there were "several answers." The links that were provided that were similar did not explain sending notifications in flutter.


Solution 1: Roman Jaquez

You will need Firebase Cloud Messaging for that.

The way I've done it is using a Cloud Function that you can trigger via HTTP or even via a Firestore trigger, like this:


// The Firebase Admin SDK to access Firestore.
const admin = require('firebase-admin');
admin.initializeApp();

const db = admin.firestore();

/**
 * Triggered by a change to a Firestore document.
 *
 * @param {!Object} event Event payload.
 * @param {!Object} context Metadata for the event.
 */
exports.messageNotificationTrigger = (change, context) => {

  db.collection('users').get().then((snapshot) => {
    snapshot.docs.forEach(doc => {

      const userData = doc.data();

      if (userData.id == '<YOUR_USER_ID>') {
         admin.messaging().sendToDevice(userData.deviceToken, {
           notification: { 
             title: 'Notification title', body: 'Notification Body'}
           });
      }
    });
  });
};

Every user you have registered in your users collection must have a device token, sent from their device they access the app.

From Flutter, using the FCM package, this is how you send the device token to Firebase:

// fetch the device token from the Firebase Messaging instance
      // and store it securely on Firebase associated with this user uid
      FirebaseMessaging.instance.getToken().then((token) {
        FirebaseFirestore.instance.collection('users').doc(userCreds.user!.uid).set({
          'deviceToken': token
        });
      });

Where userCredentials.user!.uid is the user you use to log in to your application using Firebase Authentication like this:

UserCredential userCreds = await FirebaseAuth.instance.signInWithCredential(credential);

Hope that helps.


Solution 2: Mmoniem

The above solution works, however, my solution is much simpler, and avoids adding new technologies

I have figured out how send a notification to another device using an in app feature.

First, you will need to import the necessary packages:

firebase_messaging
flutter_local_notifications

Note: you will also use the http package

Also note: to send notifications to another device, you must know the device token of that device. I prefer getting the token and saving it in Firestore or Realtime Database. Here is the code to get the device token.

String? mtoken = " ";

void getToken() async {
    await FirebaseMessaging.instance.getToken().then((token) {
      setState(() {
        mtoken = token;
      });
    });
  }

The token will be saved in mtoken, you can now use this as the token for the coming steps.

The next step is to request permission to send push notifications to your app.

  void requestPermission() async {
    FirebaseMessaging messaging = FirebaseMessaging.instance;

    NotificationSettings settings = await messaging.requestPermission(
      alert: true,
      announcement: false,
      badge: true,
      carPlay: false,
      criticalAlert: false,
      provisional: false,
      sound: true,
    );

    if (settings.authorizationStatus == AuthorizationStatus.authorized) {
      print('User granted permission');
    } else if (settings.authorizationStatus ==
        AuthorizationStatus.provisional) {
      print('User granted provisional permission');
    } else {
      print('User declined or has not accepted permission');
    }
  }

(If you get "User declined or has not accepted permission" in your console, try going out of your app, finding the icon in the homescreen, pressing and holding on the app icon, tapping "App Info", tapping "Notifications" and turn on "All [app name] notifications."

You will also need two functions to load a Firebase Cloud Messaging notification and one to listen for a notification.

Code to load a Firebase Cloud Messaging notification:

 void loadFCM() async {
    if (!kIsWeb) {
      channel = const AndroidNotificationChannel(
        'high_importance_channel', // id
        'High Importance Notifications', // title
        importance: Importance.high,
        enableVibration: true,
      );

      flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

      /// Create an Android Notification Channel.
      ///
      /// We use this channel in the `AndroidManifest.xml` file to override the
      /// default FCM channel to enable heads up notifications.
      await flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              AndroidFlutterLocalNotificationsPlugin>()
          ?.createNotificationChannel(channel);

      /// Update the iOS foreground notification presentation options to allow
      /// heads up notifications.
      await FirebaseMessaging.instance
          .setForegroundNotificationPresentationOptions(
        alert: true,
        badge: true,
        sound: true,
      );
    }
  } 

And this function to listen for a Firebase Cloud Messaging notifcation.

void listenFCM() async {
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      RemoteNotification? notification = message.notification;
      AndroidNotification? android = message.notification?.android;
      if (notification != null && android != null && !kIsWeb) {
        flutterLocalNotificationsPlugin.show(
          notification.hashCode,
          notification.title,
          notification.body,
          NotificationDetails(
            android: AndroidNotificationDetails(
              channel.id,
              channel.name,
              // TODO add a proper drawable resource to android, for now using
              //      one that already exists in example app.
              icon: 'launch_background',
            ),
          ),
        );
      }
    });
  }

You will want to run loadFCM, listenFCM, and requestPermission when the page is initialized.

  void initState() {
    super.initState();
    requestPermission();
    loadFCM();
    listenFCM();
  }

The next step is to find your Firebase Cloud Messaging API key. This can simply be done by heading to your Firebase project > Project Settings > Cloud Messaging then copy the API key under Cloud Messaging API (Legacy).

When you have your Firebase Cloud Messaging API key, this is the code to display a notification given the notification title, body, and device token to send it to.

  void sendPushMessage(String body, String title, String token) async {
    try {
      await http.post(
        Uri.parse('https://fcm.googleapis.com/fcm/send'),
        headers: <String, String>{
          'Content-Type': 'application/json',
          'Authorization':
              'key=REPLACETHISWITHYOURAPIKEY',
        },
        body: jsonEncode(
          <String, dynamic>{
            'notification': <String, dynamic>{
              'body': body,
              'title': title,
            },
            'priority': 'high',
            'data': <String, dynamic>{
              'click_action': 'FLUTTER_NOTIFICATION_CLICK',
              'id': '1',
              'status': 'done'
            },
            "to": token,
          },
        ),
      );
      print('done');
    } catch (e) {
      print("error push notification");
    }
  }

Now you can call this function like this:

sendPushMessage('Notification Body', 'Notification Title', 'REPLACEWITHDEVICETOKEN');

I hope this helps.