admin

I'm a Full-stack developer

Tag

Flutter push notification
Published date: 14/06/2023

Welcome everyone, in this article, we will implement flutter push notification through APNs (Apple Push Notification Service) and FCM (Firebase Cloud Message), and manage messages sent using AWS SNS (Amazon Simple Notification Service).


Before we go straight, we need to understand the generalization.


What is Push Notification?


Simply understand, a push notification is a server that sends a text, image, or audio message to an end-user device. In addition, push notification is a service as well as a channel for communication between the user and the application installed on the user's device in real time. Push notification requires the device to have an internet connection (Wifi / 3G / LTE / 5G, ....)


Each operating system corresponds to a different notification service because each operating system will have a different notification mechanism. For Android will use GCM's service, APNs for devices with iOS operating system.



  • How Android works:

  • How iOS works:

Why use Amazon SNS to manage messages?


Amazon SNS is a good solution to send notifications to mobile devices with different operating systems quickly and flexibly according to selected notification service such as GCM, APNs, ... More especially, Amazon SNS can send messages to specific devices or to many devices in bulk.


There are 3 main benefits to choosing Amazon SNS:


  • Send notifications to multiple platforms with a consistent API.
  • Message delivery will be analyzed and logged to the cloud watch.
  • Easily scale systems based on AWS infrastructure.


So what are the benefits of using Push Notification when developing a mobile app?


  • Use notifications to send real-time updates.
  • It also helps to announce events, coupons, etc. to users quickly.
  • In particular, push notifications are a must-have function on your app.
  • It is a powerful tool to increase sales and advertising.


How to integrate into the Flutter app?


Enable Push Notification in Apple Developer Portal


  • Sign in to Apple Developer
  • At the bottom of the page, under accounts, select Certificates, IDs, & Profiles
  • In the left navigation, select Identifiers
  • View your app details on App IDs
  • In the Capabilities tab, check Push Notifications as shown below, then Save to save your changes


Connect to Google Firebase

  • Đăng nhập vào Firebase.
  • Sign up for the Android platform and Firebase

  • Modify information for Android package
  • Add Firebase to your app


Integrate code into Flutter


  • pubspec.yaml file
dependencies:
  flutter:
    sdk: flutter
  
  firebase_messaging: ^12.0.1
  firebase_core: ^1.20.0
  firebase_core_platform_interface: 4.5.1
  flutter_local_notifications: ^13.0.0
  flutter_apns: ^1.6.0


  • Load package
flutter pub get


  • ios/Runner/Info.plist file
<key>UIBackgroundModes</key>
<array>
    <string>fetch</string>
    <string>remote-notification</string>
</array>


  • ios/Runner/AppDelegate.swift file
if #available(iOS 10.0, *) {
  UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
}


  • android/app/src/main/AndroidManifest.xml file
<manifes>
  <application>
   <activity>
     <intent-filter>
       <action android:name="android.intent.action.MAIN"/>
       <category android:name="android.intent.category.LAUNCHER"/>
     </intent-filter>
   </activity>
   <meta-data
     android:name="com.google.firebase.messaging.default_notification_icon"
     android:value="@mimap/ic_notification"
   />
   <meta-data
     android:name="com.google.firebase.messaging.default_notification_color"
     android:resource="@android:color/white"
   />
   <meta-data
     android:name="com.google.firebase.messaging.default_notification_channel_id"
     android:value="default_notification_channel_id"
   />
  </application>
</manifes>


  • main.dart file
import 'package:flutter_apns/flutter_apns.dart';

@pragma('vm:entry-point)
Future firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  print("Handling a background message: ${message.messageId}");
}

class _AppState extends State<App> {
  @override
  void initState() {
    super.initState();
    
    _pushNotification = defaultTargetPlatform == TargetPlatform.iOS ? APNsNotificationService() : FCMNotificationService();
    _pushNotification.init();
    }
  }
}

Future<dynamic> onPush(String name, RemoteMessage payload) {
  storage.append('$name: ${payload.notification?.title}');

  final action = UNNotificationAction.getIdentifier(payload.data);

  if (action != null && action != UNNotificationAction.defaultIdentifier) {
    storage.append('Action: $action');
  }

  return Future.value(true);
}

Future<dynamic> _onBackgroundMessage(RemoteMessage data) =>
    onPush('onBackgroundMessage', data);

public class FCMNotificationService extends FirebaseMessagingService {
  @override
  void init() async {
    await Firebase.initializeApp();
    _messaging = FirebaseMessaging.instance;
    NotificationSettings settings = await _messaging.requestPermission(
    alert: true,
    badge: true,
    provisional: false,
    sound: true,
  );

  if (settings.authorizationStatus == AuthorizationStatus.authorized) {
    print('User granted permission');
    // TODO: handle the received notifications
    
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      PushNotification notification = PushNotification(
        title: message.notification?.title,
        body: message.notification?.body,
      );
    }
    
    FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
  } else {
    print('User declined or has not accepted permission');
  }
  }
}

public class APNsNotificationService extends FirebaseMessagingService {
  @override
  void init() async {
    connector.configure(
      onLaunch: (data) => onPush('onLaunch', data),
      onResume: (data) => onPush('onResume', data),
      onMessage: (data) => onPush('onMessage', data),
      onBackgroundMessage: _onBackgroundMessage,
    );
      
    connector.requestNotificationPermissions();
      
    connector.token.addListener(() {
      print('Token ${connector.token.value}');
      // Store APNs Token into AWS SNS
    });
    
    connector.shouldPresent = (x) async {
      final remote = RemoteMessage.fromMap(x.payload);
      return remote.category == 'MEETING_INVITATION';
    };
      
    connector.setNotificationCategories([
      UNNotificationCategory(
        identifier: 'MEETING_INVITATION',
        actions: [
          UNNotificationAction(
            identifier: 'ACCEPT_ACTION',
            title: 'Accept',
              options: UNNotificationActionOptions.values,
          ),
          UNNotificationAction(
            identifier: 'DECLINE_ACTION',
            title: 'Decline',
            options: [],
          ),
        ],
        intentIdentifiers: [],
        options: UNNotificationCategoryOptions.values,
      ),
    ]);
  }
}


Send messages using Amazon SNS


  • Sign in to the AWS console.
  • Select the Push Notification service.
  • Create 2 platform applications.
  • Create an application endpoint and token from your device.
  • Push message to devices as below payload:
{
  "APNS": "{\"aps\":{\"alert\":\"Sample message for iOS endpoints\",\"sound\":\"default\"}"}",
  "GCM":"{ \"notification\": { \"body\": \"Sample message for Android endpoints\", \"title\":\"Test\" } }"
}


Good luck and hope you enjoy this post!!!!

Recommend

TypeScript Design Pattern - Abstract Factory
admin07/08/2023

TypeScript Design Pattern - Abstract Factory
The abstract factory pattern is one of five design patterns in the Creational Design Pattern group. The abstract factory provides an interface for creating families of related or dependent objects without specifying their concrete classes.
Flutter push notification
admin14/06/2023

Flutter push notification
Welcome everyone, in this article, we will implement flutter push notification through APNs (Apple Push Notification Service) and FCM (Firebase Cloud Message), and manage messages sent using AWS SNS (Amazon Simple Notification Service).
TypeScript Design Pattern - Singleton
admin07/08/2023

TypeScript Design Pattern - Singleton
The singleton ensures only a single install is created in a class and provides a method to access this instance everywhere in a codebase.
Newest

RESTful API - How to design?
admin09/06/2023

RESTful API - How to design?
In this article, I will describe the useful points of designing a good API.
Design Patterns
admin07/08/2023

Design Patterns
The design pattern does not be a specific programming language. Almost programming languages might apply design patterns that to resolve a problem repeat.
Data structure: Singly Linked List
admin07/04/2024

Data structure: Singly Linked List
In this article, I will show you how to set up a singly linked list algorithm in Python.