Skip to content

Push notifications

Android (FCM)

AppAmbit provides a Push Notifications SDK that allows you to easily integrate push notifications into your Android applications using Firebase Cloud Messaging (FCM). This SDK simplifies the process of sending and receiving push notifications, managing device tokens, and handling notification payloads.

Prerequisites

If you haven't yet configured your environment on the AppAmbit platform to start sending Push Notifications, go to the next page.

Requirements

  • AppAmbit Core SDK: This SDK is an extension and requires the core appambit-sdk to be installed and configured.
  • Firebase Project: A configured Firebase project and a google-services.json file in your application module.
  • Android API level 21 (Lollipop) or newer.

Install dependencies

To use the Push Notifications SDK, ensure that you have the following dependencies added to your project:

Install both libraries via NuGet Package Manager Console:

dotnet add package com.AppAmbit.Maui --version 2.0.1
dotnet add package AppAmbit.PushNotifications --version 2.0.1

Add Firebase config to your MAUI project file and place the file under Platforms/Android/:

<GoogleServicesJson Include="Platforms/Android/google-services.json" />

In your build.gradle file, add the following dependencies:

dependencies {
    implementation 'com.appambit:appambit:0.2.2'
    implementation 'com.appambit:appambit-push-notifications:0.2.2'

    // The Firebase BOM is required to align Firebase library versions.
    implementation platform('com.google.firebase:firebase-bom:33.1.2')
}
dependencies {
    implementation("com.appambit:appambit:0.2.2")
    implementation("com.appambit:appambit-push-notifications:0.2.2")

    // The Firebase BOM is required to align Firebase library versions.
    implementation(platform("com.google.firebase:firebase-bom:33.1.2"))
}

Install both libraries via pub:

flutter pub add appambit_sdk_flutter
flutter pub add appambit_sdk_push_notifications

In your build.gradle file, add the following dependencies:

android/app/build.gradle

plugins {
    // Google services (FCM)
    id("com.google.gms.google-services")
}
android/build.gradle
buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        // Google services (FCM)
        classpath("com.google.gms:google-services:4.3.15")
    }
}

android/app/build.gradle

plugins {
    // Google services (FCM)
    id "com.google.gms.google-services"
}
android/build.gradle
buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        // Google services (FCM)
        classpath "com.google.gms:google-services:4.3.15"
    }
}

Install both libraries via NPM:

npm install appambit
npm install appambit-push-notifications

In your build.gradle file, add the following dependencies:

android/app/build.gradle.kts

apply plugin: "com.google.gms.google-services"

dependencies {
    // The Firebase BOM and Messaging are required to align Firebase library versions.
    implementation(platform("com.google.firebase:firebase-bom:33.1.2"))
    implementation ("com.google.firebase:firebase-messaging:23.4.0")
}
android/build.gradle.kts
dependencies {
    classpath("com.google.gms:google-services:4.3.15")
}

android/app/build.gradle

apply plugin: "com.google.gms.google-services"

dependencies {
    // The Firebase BOM and Messaging are required to align Firebase library versions.
    implementation platform('com.google.firebase:firebase-bom:33.1.2')
    implementation 'com.google.firebase:firebase-messaging:23.4.0'
}

android/build.gradle

dependencies {
    classpath "com.google.gms:google-services:4.3.15"
}

Install both libraries via NuGet Package Manager Console:

dotnet add package com.AppAmbit.Avalonia --version 2.0.1
dotnet add package AppAmbit.PushNotifications --version 2.0.1

Add Firebase config to your Avalonia project file:

<GoogleServicesJson Include="Platforms/Android/google-services.json" />

Setup

Initialize the Core SDK: In your MauiProgram.cs class or MainActivity, initialize the core AppAmbit SDK with your App Key.

using AppAmbit;

var builder = MauiApp.CreateBuilder();
builder
    .UseMauiApp<App>()
    .UseAppAmbit("<YOUR-APPKEY>");

Initialize the Push SDK: Immediately after, start the Push Notifications SDK.

Platforms/Android/MainActivity.cs

using AppAmbit.PushNotifications;
using AndroidX.Activity;

protected override void OnCreate(Bundle? savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    PushNotifications.Start(ApplicationContext);
    PushNotifications.RequestNotificationPermission((ComponentActivity)this);
}

Import the necessary classes:

import com.appambit.sdk.AppAmbit;
import com.appambit.sdk.PushNotifications;
import com.appambit.sdk.AppAmbit
import com.appambit.sdk.PushNotifications

Initialize the Core SDK: In your Application class or MainActivity, initialize the core AppAmbit SDK with your App Key.

AppAmbit.start(getApplicationContext(), "<YOUR-APPKEY>");
AppAmbit.start(this, "<YOUR-APPKEY>");

Initialize the Push SDK: Immediately after, start the Push Notifications SDK.

PushNotifications.start();
PushNotifications.start()

Request Permissions: In your main activity, request the required notification permission.

PushNotifications.requestNotificationPermission(this);
PushNotifications.requestNotificationPermission(this)

Import the necessary classes:

import 'package:appambit_sdk_push_notifications/appambit_sdk_push_notifications.dart';
import 'package:appambit_sdk_flutter/appambit_sdk_flutter.dart';

Initialize the Core SDK: In your main.dart, initialize the core AppAmbit SDK with your App Key.

AppAmbitSdk.start(appKey: '<YOUR-APPKEY>');

Initialize the Push SDK: Immediately after, start the Push Notifications SDK.

PushNotificationsSdk.start();

Request Permissions: In your main activity, request the required notification permission.

PushNotificationsSdk.requestNotificationPermission();

Import the necessary classes:

import * as AppAmbit from "appambit";
import * as PushNotifications from "appambit-push-notifications";

Initialize the Core SDK: In your App.tsx class, initialize the core AppAmbit SDK with your App Key.

AppAmbit.start("<YOUR-APPKEY>");

Initialize the Push SDK: Immediately after, start the Push Notifications SDK.

PushNotifications.start();

Request Permissions: In your main activity, request the required notification permission.

PushNotifications.requestNotificationPermission();

Initialize the Core SDK: In your MauiProgram.cs class or MainActivity, initialize the core AppAmbit SDK with your App Key and initialize the Push Notifications SDK.

using AppAmbitAvalonia;
using AppAmbit.PushNotifications;
using AndroidX.Activity;

public class MainActivity : AvaloniaMainActivity<App>
{
    protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
    {
        AppAmbitSdk.Start("<YOUR_APPKEY>");
        PushNotifications.Start(ApplicationContext);
        PushNotifications.RequestNotificationPermission((ComponentActivity)this);
        return base.CustomizeAppBuilder(builder)
            .WithInterFont();
    }
}

Usage

Enable and Disable Notifications

By default, notifications are enabled when you first call start(). To manage user preferences afterward, use SetNotificationsEnabled.

// Disable (updates backend + deletes FCM token)
PushNotifications.SetNotificationsEnabled(ctx, false);

// Enable again
PushNotifications.SetNotificationsEnabled(ctx, true);

This method updates the opt-out status on the AppAmbit dashboard and stops the device from receiving FCM messages. You can check the current setting at any time:

bool enabled = PushNotifications.IsNotificationsEnabled(ctx);

Permission listener (optional)

To know if the user granted or denied the notification permission, you can provide an optional listener.

class PermissionListener : Java.Lang.Object, PushNotifications.IPermissionListener
{
    public void OnPermissionResult(bool granted) =>
        System.Diagnostics.Debug.WriteLine($"Push permission: {granted}");
}

PushNotifications.RequestNotificationPermission(activity, new PermissionListener());

Enabling and Disabling Notifications

By default, notifications are enabled when you first call start(). To manage user preferences afterward, use setNotificationsEnabled.

// To disable all future notifications
PushNotifications.setNotificationsEnabled(getApplicationContext(), false);

// To re-enable them
PushNotifications.setNotificationsEnabled(getApplicationContext(), true);
// To disable all future notifications
PushNotifications.setNotificationsEnabled(this, false)

// To re-enable them
PushNotifications.setNotificationsEnabled(this, true)

This method updates the opt-out status on the AppAmbit dashboard and stops the device from receiving FCM messages. You can check the current setting at any time:

val isEnabled = PushNotifications.isNotificationsEnabled(context)

Permission Listener (Optional)

To know if the user granted or denied the notification permission, you can provide an optional listener.

PushNotifications.requestNotificationPermission(this) { isGranted ->
    if (isGranted) {
        Log.d(TAG, "Permission granted!")
    } else {
        Log.w(TAG, "Permission denied. We can't show notifications.")
    }
}

Enabling and Disabling Notifications

By default, notifications are enabled when you first call start(). To manage user preferences afterward, use setNotificationsEnabled.

// To disable all future notifications
PushNotificationsSdk.setNotificationsEnabled(false);

// To re-enable them
PushNotificationsSdk.setNotificationsEnabled(true);

This method updates the opt-out status on the AppAmbit dashboard and stops the device from receiving FCM messages. You can check the current setting at any time:

var isEnabled = await PushNotificationsSdk.isNotificationsEnabled();

Permission Listener (Optional)

To know if the user granted or denied the notification permission, you can provide an optional listener.

var isGranted = await PushNotificationsSdk.requestNotificationPermissionWithResult();
if (isGranted) {
    print("Permission granted!");
} else {
    print("Permission denied.");
}

Enabling and Disabling Notifications

By default, notifications are enabled when you first call start(). To manage user preferences afterward, use setNotificationsEnabled.

// To disable all future notifications
PushNotifications.setNotificationsEnabled(false)

// To re-enable them
PushNotifications.setNotificationsEnabled(true)

This method updates the opt-out status on the AppAmbit dashboard and stops the device from receiving FCM messages. You can check the current setting at any time:

const isEnabled = await PushNotifications.isNotificationsEnabled()

Permission Listener (Optional)

To know if the user granted or denied the notification permission, you can provide an optional listener.

PushNotifications.requestNotificationPermissionWithResult().then(
    (granted: boolean) => {
        if(granted) {
            console.log("Notification permission granted");
        } else {
            console.log("Notification permission denied");
        }
    }
);

Enable and Disable Notifications

By default, notifications are enabled when you first call start(). To manage user preferences afterward, use SetNotificationsEnabled.

// Disable (updates backend + deletes FCM token)
PushNotifications.SetNotificationsEnabled(ctx, false);

// Enable again
PushNotifications.SetNotificationsEnabled(ctx, true);

This method updates the opt-out status on the AppAmbit dashboard and stops the device from receiving FCM messages. You can check the current setting at any time:

bool enabled = PushNotifications.IsNotificationsEnabled(ctx);

Permission listener (optional)

To know if the user granted or denied the notification permission, you can provide an optional listener.

class PermissionListener : Java.Lang.Object, PushNotifications.IPermissionListener
{
    public void OnPermissionResult(bool granted) =>
        System.Diagnostics.Debug.WriteLine($"Push permission: {granted}");
}

PushNotifications.RequestNotificationPermission(activity, new PermissionListener());

Customization

The SDK is designed to be highly customizable, automatically adapting to the data you send in your FCM payload, while also offering a powerful hook for advanced modifications.

Automatic Customization

The SDK automatically configures the notification by reading standard fields from your FCM message. For most use cases, you won't need to write any custom code.

notification object:

The SDK uses the standard keys from the FCM notification object.

  • title: The notification's title.
  • body: The notification's main text.
  • icon: The name of a drawable resource for the small icon.
  • color: The notification's accent color (e.g., #FF5722).
  • click_action: An intent filter name to be triggered when the notification is tapped.
  • channel_id: The ID of the notification channel to use.
  • image: A URL to an image to be displayed in the notification.
  • notification_priority: The integer priority of the notification (e.g., 1 for PRIORITY_HIGH).

data object:

The data object is a free-form container for any custom key-value pairs you wish to send (e.g., {"your_key": "your_value", "another_key": 123}). Its sole purpose is to pass custom data to your application, which you can then access using the NotificationCustomizer to implement any advanced logic you require.

Advanced Customization with NotificationCustomizer

For scenarios that require custom logic or advanced UI modifications, you can register a NotificationCustomizer. This is a powerful hook that gives you complete freedom to modify the notification before it's displayed. You receive the NotificationCompat.Builder and an AppAmbitNotification object, which contains the entire data payload from your FCM message.

The data payload is a free-form key-value map. You are not limited to any specific keys; you can send any data you need and use it to build your custom notification.

Example: Building a Custom Notification

The following example shows how to read custom fields from the data payload to add a custom action button. This is just one of many possibilities.

  1. Send any custom data you need. The keys and values are completely up to you. For example:

    {
    "notification": {
        "title": "New Message",
        "body": "You have a new message from a friend."
    },
    "data": {
        "key1": "Mark as Read",
        "key2": "MARK_AS_READ_ACTION",
        "any_other_key": "any_value"
    }
    }
    
  2. Register the NotificationCustomizer and use your custom keys:

class Customizer : Java.Lang.Object, PushNotifications.INotificationCustomizer
{
    public void Customize(Context ctx, NotificationCompat.Builder b, AppAmbitNotification n)
    {
        b.SetColor(Android.Graphics.Color.ParseColor("#0066FF"));

        // Example: add an action from custom data keys
        if (n.Data.TryGetValue("action_intent", out var action) &&
            n.Data.TryGetValue("action_title", out var title))
        {
            var intent = new Intent(action);
            var pending = PendingIntent.GetBroadcast(
                ctx, 0, intent,
                PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable);
            b.AddAction(0, title, pending);
        }
    }
}

PushNotifications.SetNotificationCustomizer(new Customizer());

Send any custom keys you need in data, AppAmbitNotification.Data exposes the full map.

The SDK is designed to be highly customizable, automatically adapting to the data you send in your FCM payload, while also offering a powerful hook for advanced modifications.

Automatic Customization

The SDK automatically configures the notification by reading standard fields from your FCM message. For most use cases, you won't need to write any custom code.

notification object:

The SDK uses the standard keys from the FCM notification object.

  • title: The notification's title.
  • body: The notification's main text.
  • icon: The name of a drawable resource for the small icon.
  • color: The notification's accent color (e.g., #FF5722).
  • click_action: An intent filter name to be triggered when the notification is tapped.
  • channel_id: The ID of the notification channel to use.
  • image: A URL to an image to be displayed in the notification.
  • notification_priority: The integer priority of the notification (e.g., 1 for PRIORITY_HIGH).

data object:

The data object is a free-form container for any custom key-value pairs you wish to send (e.g., {"your_key": "your_value", "another_key": 123}). Its sole purpose is to pass custom data to your application, which you can then access using the NotificationCustomizer to implement any advanced logic you require.

Advanced Customization with NotificationCustomizer

For scenarios that require custom logic or advanced UI modifications, you can register a NotificationCustomizer. This is a powerful hook that gives you complete freedom to modify the notification before it's displayed. You receive the NotificationCompat.Builder and an AppAmbitNotification object, which contains the entire data payload from your FCM message.

The data payload is a free-form key-value map. You are not limited to any specific keys; you can send any data you need and use it to build your custom notification.

Example: Building a Custom Notification

The following example shows how to read custom fields from the data payload to add a custom action button. This is just one of many possibilities.

  1. Send any custom data you need. The keys and values are completely up to you. For example:

    {
    "notification": {
        "title": "New Message",
        "body": "You have a new message from a friend."
    },
    "data": {
        "key1": "Mark as Read",
        "key2": "MARK_AS_READ_ACTION",
        "any_other_key": "any_value"
    }
    }
    
  2. Register the NotificationCustomizer and use your custom keys:

PushNotifications.setNotificationCustomizer((context, builder, notification) -> {
    Map<String, String> data = notification.getData();

    // You have full access to the builder and the data map.
    // You can add action buttons, apply a custom style, or change any aspect of the notification.

    // Let's use the custom keys from our example payload to add an action button.
    // Remember to replace these with your actual keys.
    String actionTitle = data.get("key1");
    String actionIntentFilter = data.get("key2");

    if (actionTitle != null && actionIntentFilter != null) {
        Intent intent = new Intent(actionIntentFilter);
        intent.putExtra("EXTRA_DATA", data.get("any_other_key"));

        PendingIntent pendingIntent = PendingIntent.getBroadcast(
            context,
            0,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );
        // Add the action to the notification
        builder.addAction(0, actionTitle, pendingIntent);
    }
});
PushNotifications.setNotificationCustomizer { context, builder, notification ->
    val data = notification.data

    // You have full access to the builder and the data map.
    // You can add action buttons, apply a custom style, or change any aspect of the notification.

    // Let's use the custom keys from our example payload to add an action button.
    // Remember to replace these with your actual keys.
    val actionTitle = data["key1"]
    val actionIntentFilter = data["key2"]

    if (!actionTitle.isNullOrEmpty() && !actionIntentFilter.isNullOrEmpty()) {
        val intent = Intent(actionIntentFilter).apply {
            putExtra("EXTRA_DATA", data["any_other_key"])
        }

        val pendingIntent = PendingIntent.getBroadcast(
            context,
            0,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
        // Add the action to the notification
        builder.addAction(0, actionTitle, pendingIntent)
    }
}

The SDK is designed to be highly customizable, automatically adapting to the data you send in your FCM payload, while also offering a powerful hook for advanced modifications.

Automatic Customization

The SDK automatically configures the notification by reading standard fields from your FCM message. For most use cases, you won't need to write any custom code.

notification object:

The SDK uses the standard keys from the FCM notification object.

  • title: The notification's title.
  • body: The notification's main text.

data object:

The data object is a free-form container for any custom key-value pairs you wish to send (e.g., {"your_key": "your_value", "another_key": 123}). Its sole purpose is to pass custom data to your application, which you can then access using the NotificationCustomizer to implement any advanced logic you require.

Advanced Customization with NotificationCustomizer

The data payload is a free-form key-value map. you are not limited to any specific keys, you can send any data you need and use it to build your custom notification.

Example: Building a Custom Notification

The following example shows how to read custom fields from the data payload to add a custom action button. This is just one of many possibilities.

  1. Send any custom data you need. The keys and values are completely up to you. For example:

    {
    "notification": {
        "title": "New Message",
        "body": "You have a new message from a friend."
    },
    "data": {
        "key1": "Mark as Read",
        "key2": "MARK_AS_READ_ACTION",
        "any_other_key": "any_value"
    }
    }
    
  2. Register the NotificationCustomizer and use your custom keys:

    PushNotificationsSdk.setNotificationCustomizer((data) {
        debugPrint("Notification Data Received: $data");
    });
    

The SDK is designed to be highly customizable, automatically adapting to the data you send in your FCM payload, while also offering a powerful hook for advanced modifications.

Automatic Customization

The SDK automatically configures the notification by reading standard fields from your FCM message. For most use cases, you won't need to write any custom code.

notification object:

The SDK uses the standard keys from the FCM notification object.

  • title: The notification's title.
  • body: The notification's main text.

data object:

The data object is a free-form container for any custom key-value pairs you wish to send (e.g., {"your_key": "your_value", "another_key": 123}). Its sole purpose is to pass custom data to your application, which you can then access using the NotificationCustomizer to implement any advanced logic you require.

Advanced Customization with NotificationCustomizer

The data payload is a free-form key-value map. you are not limited to any specific keys, you can send any data you need and use it to build your custom notification.

Example: Building a Custom Notification

The following example shows how to read custom fields from the data payload to add a custom action button. This is just one of many possibilities.

  1. Send any custom data you need. The keys and values are completely up to you. For example:

    {
    "notification": {
        "title": "New Message",
        "body": "You have a new message from a friend."
    },
    "data": {
        "key1": "Mark as Read",
        "key2": "MARK_AS_READ_ACTION",
        "any_other_key": "any_value"
    }
    }
    
  2. Register the NotificationCustomizer and use your custom keys:

PushNotifications.setNotificationCustomizer((payload: PushNotifications.NotificationPayload) => {
    console.log("Customizer received payload:", payload);
    console.log("Customizer received data:", payload.data);
    console.log("Customizer received title:", payload.notification?.title);
    console.log("Customizer received body:", payload.notification?.body);
});
PushNotifications.start();

The SDK is designed to be highly customizable, automatically adapting to the data you send in your FCM payload, while also offering a powerful hook for advanced modifications.

Automatic Customization

The SDK automatically configures the notification by reading standard fields from your FCM message. For most use cases, you won't need to write any custom code.

notification object:

The SDK uses the standard keys from the FCM notification object.

  • title: The notification's title.
  • body: The notification's main text.
  • icon: The name of a drawable resource for the small icon.
  • color: The notification's accent color (e.g., #FF5722).
  • click_action: An intent filter name to be triggered when the notification is tapped.
  • channel_id: The ID of the notification channel to use.
  • image: A URL to an image to be displayed in the notification.
  • notification_priority: The integer priority of the notification (e.g., 1 for PRIORITY_HIGH).

data object:

The data object is a free-form container for any custom key-value pairs you wish to send (e.g., {"your_key": "your_value", "another_key": 123}). Its sole purpose is to pass custom data to your application, which you can then access using the NotificationCustomizer to implement any advanced logic you require.

Advanced Customization with NotificationCustomizer

For scenarios that require custom logic or advanced UI modifications, you can register a NotificationCustomizer. This is a powerful hook that gives you complete freedom to modify the notification before it's displayed. You receive the NotificationCompat.Builder and an AppAmbitNotification object, which contains the entire data payload from your FCM message.

The data payload is a free-form key-value map. You are not limited to any specific keys; you can send any data you need and use it to build your custom notification.

Example: Building a Custom Notification

The following example shows how to read custom fields from the data payload to add a custom action button. This is just one of many possibilities.

  1. Send any custom data you need. The keys and values are completely up to you. For example:

    {
    "notification": {
        "title": "New Message",
        "body": "You have a new message from a friend."
    },
    "data": {
        "key1": "Mark as Read",
        "key2": "MARK_AS_READ_ACTION",
        "any_other_key": "any_value"
    }
    }
    
  2. Register the NotificationCustomizer and use your custom keys:

class Customizer : Java.Lang.Object, PushNotifications.INotificationCustomizer
{
    public void Customize(Context ctx, NotificationCompat.Builder b, AppAmbitNotification n)
    {
        b.SetColor(Android.Graphics.Color.ParseColor("#0066FF"));

        // Example: add an action from custom data keys
        if (n.Data.TryGetValue("action_intent", out var action) &&
            n.Data.TryGetValue("action_title", out var title))
        {
            var intent = new Intent(action);
            var pending = PendingIntent.GetBroadcast(
                ctx, 0, intent,
                PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable);
            b.AddAction(0, title, pending);
        }
    }
}

PushNotifications.SetNotificationCustomizer(new Customizer());

Send any custom keys you need in data, AppAmbitNotification.Data exposes the full map.

iOS (APNs)

AppAmbit provides comprehensive iOS push notifications SDK that integrates seamlessly with the AppAmbit Core SDK ecosystem and follows the same architectural patterns as the Android SDK for cross-platform parity.

Prerequisites

If you haven't yet configured your environment on the AppAmbit platform to start sending Push Notifications, go to the next page.

Features

  • Simple API: Matches Android SDK for cross-platform consistency
  • Minimal setup: Just call PushNotifications.start() after AppAmbit initialization
  • Decoupled architecture: Internal PushKernel handles APNs, public PushNotifications facade
  • Customizable notifications: Modify notification content before display
  • Thread-safe: Compatible with Swift 6 Concurrency
  • Persistent state: User preferences stored in UserDefaults

Requirements

  • iOS 12.0 or newer
  • Xcode 15 or newer
  • Swift 5.7 or newer

Install

Swift Package Manager

  • Add the repository URL in Xcode under File → Add Packages…
  • Select the latest version and attach it to your app target

Install both libraries via NuGet Package Manager Console:

dotnet add package com.AppAmbit.Maui --version 2.0.1
dotnet add package AppAmbit.PushNotifications --version 2.0.1

Add this to your Podfile:

pod 'AppAmbitPushNotifications'
# or specify version
pod 'AppAmbitPushNotifications', '~> 0.2.0'

Then run:

pod install

Open the generated .xcworkspace project.

(If you get an error like “Unable to find a specification for AppAmbitPushNotifications”: run pod repo update, then pod install.)

Install both libraries via pub:

flutter pub add appambit_sdk_flutter
flutter pub add appambit_sdk_push_notifications

Install both libraries via NPM:

npm install appambit
npm install appambit-push-notifications

Setup

Initialize the Core SDK: In your MauiProgram class, initialize with your APPKEY.

Platform specific code:

using AppAmbit.PushNotifications;
using AppAmbit;
namespace AppAmbitTestingiOS;

[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
    public override UIWindow? Window
    {
        get;
        set;
    }

    public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
    {
        AppAmbitSdk.Start("<YOUR-APPKEY>");
        PushNotifications.Start();

        Window = new UIWindow(UIScreen.MainScreen.Bounds);
        Window.RootViewController = new MainTabBarController();
        Window.MakeKeyAndVisible();
        return true;
    }
}

Request Permissions: In your app, request the required notification permission.

PushNotifications.RequestNotificationPermission(new PermissionListener(granted => 
        {
            MainThread.BeginInvokeOnMainThread(async () =>
            {
                if (granted)
                {
                    PushNotifications.SetNotificationsEnabled(true);
                }
                else
                {
                    Debug.WriteLine("Permission Denied");
                }
            });
        }
    )
);

Initialize using MAUI program:

using Foundation;
using UIKit;
using AppAmbit.PushNotifications;

namespace AppAmbitTestingApp;

[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate
{
    protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();

    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        var result = base.FinishedLaunching(app, options);

    // Start push and wire token updates to AppAmbit (same pattern as Android)
    PushNotifications.Start(null);

    return result;
}

[System.Runtime.InteropServices.DllImport("/usr/lib/libSystem.dylib")]
private static extern IntPtr dlerror();
}

Initialize the Push SDK: Immediately after, start the Push Notifications SDK.

Platforms/iOS/AppDelegate.cs

using AppAmbit;
using AppAmbit.PushNotifications;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiProgram.CreateMauiAppBuilder();

        AppAmbit.Start("<YOUR-APPKEY>");
        PushNotifications.Start(null);

        return builder.Build();
    }
}

Request Permissions: In your app, request the required notification permission.

PushNotifications.RequestNotificationPermission(new PermissionListener(granted =>
        {
            InvokeOnMainThread(async () =>
            {
                if (granted)
                {
                    PushNotifications.SetNotificationsEnabled(true);
                    Debug.WriteLine("Permission Granted");
                }
                else
                {
                    Debug.WriteLine("Permission denied");
                }
            });
        }
    )
);

Initialize the Core SDK: In your SwiftUI App struct or AppDelegate class, initialize with your APPKEY.

import SwiftUI
import AppAmbit
import AppAmbitPushNotifications

@main
struct MyApp: App {
    init() {
        // First, start AppAmbit Core SDK
        AppAmbit.start(appKey: "<YOUR-APPKEY>") {
            // Then start Push SDK after AppAmbit finishes initialization
            PushNotifications.start()
        }
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Request Permissions: In your app, request the required notification permission.

// Request notification permission from the user
PushNotifications.requestNotificationPermission { granted in
    if granted {
        print("Permission granted!")
        // Optionally enable notifications
        PushNotifications.setNotificationsEnabled(true)
    } else {
        print("Permission denied")
    }
}
#import "AppDelegate.h"
@import AppAmbit;
@import AppAmbitPushNotifications;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [AppAmbit start:@"<YOUR-APPKEY>"];
    [PushNotifications start];
    return YES;
}

Request Permissions: In your app, request the required notification permission.

[PushNotifications requestNotificationPermissionWithListener:^(BOOL granted) {
    if (granted) {
        [PushNotifications setNotificationsEnabled:YES];
    } else {
        NSLog(@"Permission denied");
    }
}];

Initialize the Core SDK: In your main.dart file, initialize with your APPKEY.

import 'package:appambit_sdk_push_notifications/appambit_sdk_push_notifications.dart';
import 'package:appambit_sdk_flutter/appambit_sdk_flutter.dart';
import 'package:flutter/material.dart';

void main() async {
    WidgetsFlutterBinding.ensureInitialized();
    AppAmbitSdk.start(appKey: '<YOUR-APPKEY>');
    PushNotificationsSdk.start();
    runApp(const MyApp());
}

Request Permissions: In your app, request the required notification permission.

var isGranted = await PushNotificationsSdk.requestNotificationPermissionWithResult();

if (isGranted) {
  await PushNotificationsSdk.setNotificationsEnabled(true);
}

Initialize the Core SDK: In your App.js file, initialize with your APPKEY.

import * as AppAmbit from "appambit";
import * as PushNotifications from "appambit-push-notifications";

export default function App() {
    AppAmbit.start("<YOUR-APPKEY>");
    PushNotifications.start();
}

Request Permissions: In your app, request the required notification permission.

const granted = await PushNotifications.requestNotificationPermissionWithResult();

if (granted) {
  await PushNotifications.setNotificationsEnabled(true);
}

Usage

Enable Notifications

PushNotifications.SetNotificationsEnabled(true);

Disable Notifications

PushNotifications.SetNotificationsEnabled(false);

Check current status

var isEnabled = PushNotifications.IsNotificationsEnabled();

Enable and Disable Notifications

Enable notifications (registers for APNs and syncs with backend)

PushNotifications.setNotificationsEnabled(true)

Enable notifications and wait for APNs + backend sync

PushNotifications.setNotificationsEnabled(true) { success in
    print("Push sync completed: \(success)")
}

Disable notifications (unregisters from APNs and syncs with backend)

PushNotifications.setNotificationsEnabled(false)

Check current status

let isEnabled = PushNotifications.isNotificationsEnabled()

Enable notifications

[PushNotifications setNotificationsEnabled:YES];

Enable notifications and wait for APNs + backend sync

[PushNotifications setNotificationsEnabled:YES completion:^(BOOL success) {
    NSLog(@"Push sync completed: %@", success ? @"YES" : @"NO");
}];

Disable notifications

[PushNotifications setNotificationsEnabled:NO];

Check current status

BOOL isEnabled = [PushNotifications isNotificationsEnabled];

Enable Notifications

await PushNotificationsSdk.setNotificationsEnabled(true);

Disable Notifications

await PushNotificationsSdk.setNotificationsEnabled(false);

Check current status

var isEnabled = await PushNotificationsSdk.isNotificationsEnabled();

Enable Notifications

await PushNotifications.setNotificationsEnabled(true);

Disable Notifications

await PushNotifications.setNotificationsEnabled(false);

Check current status

var isEnabled = await PushNotifications.isNotificationsEnabled()

Enable Notifications

AppAmbit.PushNotifications.PushNotifications.SetNotificationsEnabled(true);

Disable Notifications

AppAmbit.PushNotifications.PushNotifications.SetNotificationsEnabled(false);

Check current status

bool isEnabled = AppAmbit.PushNotifications.PushNotifications.IsNotificationsEnabled();

Customize Notifications (Optional)

Set a customizer to modify notifications before they're displayed

PushNotifications.SetNotificationCustomizer(new SimpleNotificationCustomizer());
private sealed class SimpleNotificationCustomizer : PushNotifications.INotificationCustomizer
{
    public void Customize(object context, object builder, PushNotificationData notification)
    {
        System.Diagnostics.Debug.WriteLine($"[Customizer] Title: {notification.Title}, Body: {notification.Body}");

        if (notification.Data is System.Collections.IDictionary dict)
        {
            foreach (var key in dict.Keys)
            {
                System.Diagnostics.Debug.WriteLine($"[Customizer] Data[{key}] = {dict[key]}");
            }
        }
        else if (notification.Data != null)
        {
            System.Diagnostics.Debug.WriteLine($"[Customizer] Data (raw): {notification.Data}");
        }
    }
}

Set a customizer to modify notifications before they're displayed

PushNotifications.setNotificationCustomizer { content, notification in
    // Modify the notification content
    content.title = "Custom: \(notification.title ?? "")"
    content.body = "Modified: \(notification.body ?? "")"
    content.badge = 1
    content.sound = .default

    // Access custom data
    if let customValue = notification.data["myKey"] {
        print("Custom data: \(customValue)")
    }
}

Set a customizer to modify notifications before they're displayed

PushNotificationsSdk.setNotificationCustomizer((data) {
    debugPrint("Notification Data Received: $data");
});

Set a customizer to modify notifications before they're displayed

PushNotifications.setNotificationCustomizer((payload: PushNotifications.NotificationPayload) => {
    console.log("Customizer received payload:", payload);
    console.log("Customizer received data:", payload.data);
    console.log("Customizer received title:", payload.notification?.title);
    console.log("Customizer received body:", payload.notification?.body);
});

Set a customizer to modify notifications before they're displayed

AppAmbit.PushNotifications.PushNotifications.SetNotificationCustomizer(new SimpleNotificationCustomizer());
private sealed class SimpleNotificationCustomizer : AppAmbit.PushNotifications.PushNotifications.INotificationCustomizer
{
    public void Customize(object context, object builder, AppAmbit.PushNotifications.PushNotificationData notification)
    {
        System.Diagnostics.Debug.WriteLine($"[Customizer] Title: {notification.Title}, Body: {notification.Body}");

        if (notification.Data is System.Collections.IDictionary dict)
        {
            foreach (var key in dict.Keys)
            {
                System.Diagnostics.Debug.WriteLine($"[Customizer] Data[{key}] = {dict[key]}");
            }
        }
        else if (notification.Data != null)
        {
            System.Diagnostics.Debug.WriteLine($"[Customizer] Data (raw): {notification.Data}");
        }
    }
}

Notification Service Extension (Images)

To support image attachments, add a UNNotificationServiceExtension and inherit from AppAmbitNotificationService. This handles downloading and attaching the image URL from the payload.

Xcode Steps

  1. File > New > Target > Notification Service Extension
  2. Add the AppAmbitPushNotifications package to the extension target in Xcode.
  3. Use the following class:
import AppAmbitPushNotifications

final class NotificationService: AppAmbitNotificationService {
    // Override only if you need to inspect custom payload fields.
    override func handlePayload(_ notification: AppAmbitNotification, userInfo: [AnyHashable: Any]) {
        // no-op by default
    }
}

If your app is Objective-C, you can still add this extension in Swift.

Dashboard Form Fields Support (APNs Mapping)

These fields are provided by your backend (dashboard/console). The SDK reads them from APNs payloads.

Targeting/Scheduling (Backend only) - Send To, Rate Limit, Send At: handled by backend delivery, not by the iOS SDK.

Content & Behavior (APNs payload)

  • Title / Body -> aps.alert.title / aps.alert.body
  • Sound -> aps.sound (e.g. "default" or custom filename)
  • Badge Count -> aps.badge
  • Category -> aps.category (requires app-side UNNotificationCategory registration)
  • Thread ID -> aps.thread-id
  • Interruption Level -> aps.interruption-level (iOS 15+)
  • Custom Data Payload -> any key outside aps (available in AppAmbitNotification.data)
  • Image URL -> requires UNNotificationServiceExtension and mutable-content: 1

Requirements for Advanced Fields

  • Category: the app must register matching UNNotificationCategory identifiers.
  • Image URL: the app must add a UNNotificationServiceExtension that downloads the image and attaches it to the notification. The backend must include mutable-content: 1 and an agreed custom key (e.g. image_url) in the payload.
  • Interruption Level: only applies on iOS 15+.

Architecture

This SDK follows the same architecture as the Android version:

  • PushNotifications (public): The facade that exposes all functionality
  • PushKernel (internal): Decoupled core that handles APNs communication
  • AppAmbitNotification: Model that encapsulates notification data

The kernel is completely invisible to the end user. All interactions go through PushNotifications.

How It Works

  1. Token Management: When the app registers for notifications, APNs provides a device token. This token is automatically sent to the AppAmbit backend via ConsumerService.updateConsumer().

  2. State Persistence: The enabled/disabled state is stored in UserDefaults, so it persists across app launches.

  3. Backend Sync: Every time you call setNotificationsEnabled(), the SDK updates the backend with the current token and status. When enabling, the backend update happens after APNs returns a token to avoid duplicate updates.

  4. Customization: Before displaying a foreground notification, the SDK checks if a customizer is set and invokes it, allowing you to modify the content.

Requirements

  • iOS 12.0+
  • Swift 6.0+
  • AppAmbit Core SDK (must be initialized first)

Differences from Android

While the API is nearly identical, there are platform-specific differences:

Feature Android iOS
Token type FCM Token APNs Device Token
Permissions POST_NOTIFICATIONS (Android 13+) User Notifications authorization
State storage SharedPreferences UserDefaults
Customization timing Before display (MessagingService) Before display (UNUserNotificationCenterDelegate)

Support

For questions or issues, refer to the example application in Swift example.