Flutter push notification to iOS without Firebase

Welcome everyone, in this article, we will implement flutter push notification to iOS without firebase. We will be using AWS Push Notification Service (SNS) for managing delivery and sending message.

What is push notification?

Push notification is basically of a server send text, image and sound to devices. Furthermore, push notification serve as a channel for users communicate with application installed on their device immediately. Notification will be pushed to devices through cloud message, their devices have to available internet.

Depending on the operating system to choice mobile notification services, Google Cloud Message (GCM) for Android, Apple Push Notification Service (APNs) for iOS. Because of Push notification mechanisms are different on Android and iOS.

  • Android Push Notification
  • iOS Push Notification

Why use Push Notification?

  • Using notification to send real-time updates to their users like new-products, trending stories, etc.
  • It also help to alerts events, coupons, etc. to users quickly.
  • Specially, push notification is a function that could not ignore on your app. It is a powerful tool for increasing revenue and advertising.

Push Notification with Amazon SNS

Amazon SNS is a fast, flexible notification service that is good solution to be send  notification to mobile devices cross platform. Using AWS SNS, you can push notification to individual or large numbers of devices.

A number of benefits when using AWS SNS for pushing notification:

  • Sending notification to multiple platforms with one, consistent API.
  • Message delivery is be analyze and write log to cloud watch.
  • Easily to scale system based on AWS infrastructure.

Enable push notifications in the Apple Developer Portal

  • Sign in to Apple Developer
  • Footer, under Account, click into Certificates, IDs, & Profiles
  • In the left nav, click Identifiers
  • View your app detail on App IDs
  • On the Capabilities tab, check Push Notifications like image below and then Save your change

Code demo

  • Adding packages on pubspec.yaml:
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
  • Getting package by command line below
flutter pub get
  • Enable Remote Push Notification Capability, add this configuration in your ios/Runner/Info.plist
<key>UIBackgroundModes</key>
<array>
    <string>fetch</string>
    <string>remote-notification</string>
</array>
  • Add the following lines to the didFinishLaunchingWithOptions method in the ios/Runner/AppDelegate.swift
if #available(iOS 10.0, *) {
  UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
}
  • APNS without firebase, add this configuration entry in your ios/Runner/Info.plist
<key>flutter_apns.disable_swizzling</key>
<true/>
  • Adding APNs features on main.dart
import 'package:flutter_apns/flutter_apns.dart';
class _MyAppState extends State<MyApp> {
  final ApnsPushConnector connector = ApnsPushConnector();
  
  @override
  void initState() {
    _register();
    
    super.initState();
    
    _register() 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
      });
    }
  }
}

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);
  • Navigate to special page:

The onMessage should be ignored in the configuration.

connector.configure(
  onLaunch: (data) => onPush('onLaunch', data),
  onResume: (data) => onPush('onResume', data),
  onBackgroundMessage: _onBackgroundMessage,
);
  • Enable action notification that let the user respond to a delivered notification without launching the corresponding app:
if (connector is ApnsPushConnector) {
  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 a test push notification

  1. Sign in to AWS SNS console.
  2. Choose Push notifications.
  3. Create a platform application:
    Application name: APNs Platform
    Push notification platform: Apple iOS/VoIP/MacOS
    Push service: iOS
    Authentication method: Token
  4. Create a application endpoint with your device token
  5. Publish message to device with the token is created in previous step
{
  "APNS": "{\"aps\":{\"alert\":\"Sample message for iOS endpoints\",\"sound\":\"default\"}"}"
}

Hope you enjoy :)