Pluggable's Smartpush Plugin for Flutter apps

A Flutter plugin for Flutter apps.

Pre-conditions Integrate with FCM

Before using this plugin you should guarantee that your app already integrates with Firebase Cloud Messaging so that your app can receive push notifications.

  1. First install FlutterFire, a tool which automatically configures your app to use firebase;
  2. Then, install firebase_messaging, a cross-platform messaging solution;
  3. Then, to start using the Cloud Messaging package within your project follow these steps;
  4. Integrating the Cloud Messaging plugin on iOS requires additional setup before your devices receive messages. The full steps are available here, but the following prerequisites are required to be able to enable messaging:
    • You must have an active Apple Developer Account;
    • You must have a physical iOS device to receive messages.
  5. Also for iOS:
    • If you are using swift, in your AppDelegate.swift make sure you have added the first code;
    • If you're using flutter with objective-c, add the second code to your appdelegate.m file.
import Firebase

FirebaseApp.configure() //add this before the code below
GeneratedPluginRegistrant.register(with: self)
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [FIRApp configure]; //add this at the top
    // ...
}

NOTE: FCM via APNs does not work on iOS Simulators. To receive messages & notifications a real device is required. The same is recommended for Android.

Smartpush Usage

  1. After configuring your app to integrate with FCM, you are ready to use this plugin to properly engage with your users. To install the plugin just run, in the root of the project:
flutter pub add smartpush
  • Or run flutter pub upgrade to update to the latest compatible versions of all the dependencies listed in the pubspec.yaml file.
  • For Android, to customize the used notification icon, just add the desired icon in the Android's drawble folder and name it ic_push_app_icon. Otherwise, a default icon, not related to your app, will be used.
  1. Finally, this plugin exposes three mandatory methods, which can be imported and used in your main.dart files as demonstrated in the next lines.
// ...
import 'package:smartpush/smartpush.dart';
// ...
  • The pluggableInitialize method is used to initialize the Smartpush plugin:
String COMPANY_NAME = 'your_company_name';
String COMPANY_LICENSE = 'your_company_key';
String FCM_TOKEN = 'the_fcm_token';
String? EXTERNAL_USER_ID = 'your_user_id';
String? EXTERNAL_TOKEN_ID = 'the_id_of_the_device';
String? EXTERNAL_USER_EMAIL = 'email@domain.com';
bool? PLUGGABLE_LOG = true;

//...
final _smartpushPlugin = Smartpush();

final pluggableInitialize = await _smartpushPlugin.pluggableInitialize(COMPANY_NAME, COMPANY_LICENSE, FCM_TOKEN, EXTERNAL_USER_ID, EXTERNAL_TOKEN_ID, EXTERNAL_USER_EMAIL, PLUGGABLE_LOG);
print("[InitializeSDK]: $pluggableInitialize");
  • The pluggableExecute method is used to execute the SDK AI models to deliver push notifications at the best moment to each particular user. This method, which returns the UUID of the push (which you can use to associate sensor data to your users) should be called in the functions you created to receive background and foreground push notifications (typically, Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async and void _firebaseMessagingForegroundHandler(RemoteMessage message) async), as follows:
//...

/// Receive push while in the background
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
    // If you're going to use other Firebase services in the background, such as Firestore,
	// make sure you call `initializeApp` before using other Firebase services.
    await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform,
    );

    Map<String, String> notificationData = message.data.map((key, value) => MapEntry(key, value.toString()));

    final pluggableExecute = await _smartpushPlugin.pluggableExecute(notificationData, PLUGGABLE_LOG);
    print("[ExecuteSDK]: $pluggableExecute");
    // Save the pushUUID and userID to the database
    // ...
}

/// Receive push while in the foreground
void _firebaseMessagingForegroundHandler(RemoteMessage message) async {

    Map<String, String> notificationData = message.data.map((key, value) => MapEntry(key, value.toString()));

    final pluggableExecute = await _smartpushPlugin.pluggableExecute(notificationData, PLUGGABLE_LOG);
    print("[ExecuteSDK]: $pluggableExecute");
    // Save the pushUUID and userID to the database
    // ...
}
  • The pluggableStoreFeedback method is used to create engagement metrics (used as soon as a notification is opened). This method should be called within a function added to FirebaseMessaging.onMessageOpenedApp.listen, as follows:
//...
void _handlePushClick(RemoteMessage message) async {
	Map<String, String> notificationData = message.data.map((key, value) => MapEntry(key, value.toString()));
	final pluggableStoreFeedback = await _smartpushPlugin.pluggableStoreFeedback(notificationData, log);
    print("[StoreFeedback]: $pluggableStoreFeedback");
}

Future<void> setupInteractedMessage() async {
    // Get any messages which caused the application to open from a terminated state.
    RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage();

    // If the message is not null
    if (initialMessage != null) {
        _handlePushClick(initialMessage);
    }

    FirebaseMessaging.onMessageOpenedApp.listen(_handlePushClick);
}
  1. Three additional methods are exposed by the library to handle tags (aka segments) subscriptions and can be used, if needed, as follows.
  • You can subscribe your client's app to a particular tag - the client will then receive notifications that are sent to that particular tag. You should call the pluggableSubscribeTag method to let the SDK subscribe the user to that tag. This returns 1, if success, otherwise an error message. For that, you must do as follows:
//...

String TAG_NAME = 'tag_name';
String TAG_VALUE = 'tag_value';

final pluggableSubscribeTag = await _smartpushPlugin.pluggableSubscribeTag(TAG_NAME, TAG_VALUE, EXTERNAL_USER_ID, EXTERNAL_TOKEN_ID, PLUGGABLE_LOG);
print("[Subscribed]: $pluggableSubscribeTag");
  • You can also unsubscribe your client's app from a particular tag. You should call the pluggableUnsubscribeTag method to let the SDK unsubscribe the user from that tag. This returns 1, if success, otherwise an error message. For that, you must do as follows:
//...

final pluggableUnsubscribeTag = await _smartpushPlugin.pluggableUnsubscribeTag(TAG_NAME, EXTERNAL_USER_ID, EXTERNAL_TOKEN_ID, PLUGGABLE_LOG);
print("[Unsubscribed]: $pluggableUnsubscribeTag");
  • To get the list of tags the user is currently subscribed to you should call the pluggableGetSubscribedTags method. This returns an array of strings. For that, you must do as follows:
//...

final pluggableGetSubscribedTags = await _smartpushPlugin.pluggableGetSubscribedTags(EXTERNAL_USER_ID, EXTERNAL_TOKEN_ID, PLUGGABLE_LOG);
print("[Get Tags]: $pluggableGetSubscribedTags");
  1. Three additional methods are exposed by the library to handle internal permissions (you are still required to ask the user for PUSH NOTIFICATION permission). These methods allow you to internally enable/disable push notifications (without disabling the OS permission itself) and are called as pluggableEnableInternalPushPermission, pluggableDisableInternalPushPermission, and pluggableGetPushPermissionState. These methods return 0, if the push permissions is disabled, 1, if the push permission is enabled, and -1, meaning that the user did not grant the required OS permission for push notifications. You can use these as follows:
// ...
import 'package:notification_permissions/notification_permissions.dart';
// ...
  • To ask for the OS permission, you can do as follows:
// ...

Future requestPermission() async {
    FirebaseMessaging messaging = FirebaseMessaging.instance;
    // Ask for push permissions
    NotificationSettings settings = await messaging.requestPermission(
        alert: true,
        announcement: false,
        badge: true,
        carPlay: false,
        criticalAlert: false,
        provisional: true,
        sound: true,
    );
    print('User granted permission: ${settings.authorizationStatus}');
    // Presentation for foreground push
    await messaging.setForegroundNotificationPresentationOptions(
        alert: true,
        badge: true,
        sound: true,
    );	
}

// ...

final pluggableEnableInternalPushPermission = await _smartpushPlugin.pluggableEnableInternalPushPermission(PLUGGABLE_LOG);
print("[Permission Enabled]: $pluggableEnableInternalPushPermission");

// ...

final pluggableDisableInternalPushPermission = await _smartpushPlugin.pluggableDisableInternalPushPermission(PLUGGABLE_LOG);
print("[Permission Disabled]: $pluggableDisableInternalPushPermission");

// ...

final pluggableGetPushPermissionState = await _smartpushPlugin.pluggableGetPushPermissionState(PLUGGABLE_LOG);
print("[Permission State]: $pluggableGetPushPermissionState");
  1. It is also important to get the user token and listen for changes to get the user FCM_TOKEN and update it when it changes.
Future<void> setupToken() async {
    // Get the token each time the application loads
    String? token = await FirebaseMessaging.instance.getToken();
    if(token != null) {
            FCM_TOKEN = token;
        }
    // Save the initial token to the database
    // ...
    print('Device token is as follows: $token');
}

More info

  • For full compatibility, attention to the used versions of XCODE, SWIFT and COCOAPODS. Recommended versions are XCODE=15, SWIFT=5.9, and COCOAPODS=1.14.2.

  • For more info visit https://pluggableai.xyz/ or give us feedback to info@pluggableai.xyz.