Skip to main content
SDK Version

Standard

Remote notifications allow your application to receive messages from Actito in real time, even when the app is not active. To enable this functionality, include the actito-push module in your project. This module provides all the components necessary to register the push subscription and handle incoming notifications. You may implement a custom user interface to present notifications. However, we recommend including the actito-push-ui module to take advantage of the managed notification UI, which simplifies implementation and ensures a consistent user experience.

To enable this functionality, run the following command:

dotnet add package Actito.Push
dotnet add package Actito.PushUI
Requirements

Before getting started with this module, ensure that the following steps have been completed:

Notification provider environments

As described in the Environments section of the Getting Started guide, maintaining separate environments for development and production is essential. This separation becomes even more critical when implementing remote notifications.

Each environment should use its own Actito Services configuration to ensure consistent and isolated registration of push subscriptions. For example, development builds should receive notifications only from the development environment, while production builds communicate exclusively with the production environment. This approach ensures data consistency and a clean testing process.

Environments

Requesting permission

To receive remote notifications on Android, your application must request the user’s permission to display notifications. This can typically be done during the onboarding flow or at the point where notifications are first needed.

private async void OnEnableRemoteNotificationsClicked(object sender, EventArgs e)
{
try
{
// Ensure we have sufficient permissions
var granted = await EnsureNotificationsPermissions();
if (!granted) return;

// You can enable remote notifications
await ActitoPush.EnableRemoteNotificationsAsync();
}
catch (Exception exception)
{
// TODO: Handle error
}
}

private async Task<bool> EnsureNotificationsPermissions()
{
var status = await Permissions.CheckStatusAsync<Permissions.PostNotifications>();
if (status == PermissionStatus.Granted) return true;

if (status == PermissionStatus.Denied && DeviceInfo.Platform == DevicePlatform.iOS) return false;

if (Permissions.ShouldShowRationale<Permissions.PostNotifications>())
{
await Shell.Current.DisplayAlert(
title: "Notifications Rational",
message: "Remote notifications rational message.",
cancel: "OK"
);
}

status = await Permissions.RequestAsync<Permissions.PostNotifications>();

return status == PermissionStatus.Granted;
}
note
  • The snippet above uses the MAUI permissions utility plugin to handle the bridge into native permissions. You can use any other plugin or implement the bridge yourself.
  • For Android 12 (API 32) and lower, no explicit user permission is required.
  • It is recommended to request notification permission during onboarding or at a time when the value of notifications is clear to the user.
  • Always handle the case where the user denies permission gracefully.

Enabling remote notifications

Once the necessary permissions are granted, you can enable remote notifications through the Actito SDK:

await ActitoPush.EnableRemoteNotificationsAsync();

After enabling, the SDK will register the device for notifications with Actito.

You can check the user’s current enrollment and permission status using:

// Check if the user has previously enabled remote notifications.
ActitoPush.HasRemoteNotificationsEnabled;

// Check if the device is allowed to receive remote notifications.
ActitoPush.AllowedUI;

These checks can help you update your app’s UI to reflect the user’s notification status or guide them to re-enable permissions if needed.

Disabling remote notifications

If the user chooses to stop receiving notifications, you can disable them programmatically:

await ActitoPush.DisableRemoteNotificationsAsync();

This action unregisters the device from receiving further remote notifications. It is recommended to provide a clear opt-out option in your app’s settings to comply with privacy and consent requirements.

Handling remote notifications

Before you can start receiving push notifications, you will need to set up the native counterparts of your app.

To properly handle remote notifications, your application’s Activity must act as a trampoline — receiving and processing the intents triggered when a user opens a notification or taps a notification action.

Typically, this will be your MainActivity. To enable it to receive these intents, declare the appropriate intent filters in your MainActivity.cs.

[Activity(
LaunchMode = LaunchMode.SingleTask,
...)]
[IntentFilter(
["com.actito.intent.action.RemoteMessageOpened"],
Categories = [Intent.CategoryDefault])]
public class MainActivity : MauiAppCompatActivity {

}

Launch mode configuration

The Activity responsible for handling notification intents must use LaunchMode = LaunchMode.SingleTask. This configuration ensures that the activity is not recreated multiple times when processing a series of intents triggered by opening notifications from the system tray.

For additional details, refer to the official Android documentation on Activity launch modes.

Handling mode configuration

In order to process these intents, your MainActivity must handle them appropriately in its lifecycle methods. The following example illustrates how to handle the notification intents:

public class MainActivity : MauiAppCompatActivity
{
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
// more code ...

if (Intent != null) HandleIntent(Intent);
}

protected override void OnNewIntent(Intent? intent)
{
base.OnNewIntent(intent);
// more code ...

if (intent != null) HandleIntent(intent);
}

private void HandleIntent(Intent intent)
{
if (Actito.HandleTrampolineIntent(intent))
return;

// more code ...
}
}
note

To achieve a seamless presentation of Alert type notification over your app's content, we recommend theming the NotificationActivity with a transparent background style. You can find out more about theming the NotificationActivity in our customization guide.

note

If your application needs to support Map notifications, you must configure a Google Maps API key as outlined in the Google Maps API Key guide.

A notification can be opened by either tapping the actual notification or by tapping an action inside the notification. In each case, we will emit event. Be sure to register your listeners during app initialization to avoid missing events, especially during a cold launch.

public partial class App : Application
{
public App()
{
InitializeComponent();

ActitoPush.NotificationOpened += OnNotificationOpened;
ActitoPush.NotificationActionOpened += OnNotificationActionOpened;
}

private void OnNotificationOpened(object? sender, ActitoNotificationOpenedEventArgs e)
{
#if ANDROID
var activity = Platform.CurrentActivity;
ActitoPushUI.PresentNotification(e.Notification, activity!);

#elif IOS
var rootViewController = UIApplication.SharedApplication.KeyWindow.RootViewController;

if (rootViewController is null)
{
Console.WriteLine("Cannot present a notification with a null root view controller.");
return;
}

if (e.Notification.RequiresViewController())
{
var navigationController = new UINavigationController();
if (navigationController.View is not null)
navigationController.View.BackgroundColor = UIColor.SystemBackground;

rootViewController.PresentViewController(
navigationController,
true,
() => ActitoPushUI.PresentNotification(e.Notification, navigationController)
);
}
else
{
ActitoPushUI.PresentNotification(e.Notification, rootViewController);
}
#endif
}

private void OnNotificationActionOpened(object? sender, ActitoNotificationActionOpenedEventArgs e)
{
#if ANDROID
var activity = Platform.CurrentActivity;
ActitoPushUI.PresentAction(e.Notification, e.Action, activity!);

#elif IOS
var rootViewController = UIApplication.SharedApplication.KeyWindow.RootViewController;

if (rootViewController is null)
{
Console.WriteLine("Cannot present a notification with a null root view controller.");
return;
}

ActitoPushUI.PresentAction(e.Notification, e.Action, rootViewController);

#endif
}
}

Managed vs. Manual handling

You can handle these notification events in one of two ways:

  • Managed Approach (Recommended) — Include and use the Actito.PushUI module to display notifications, actions, and track their engagement. This approach ensures consistency, proper event tracking, and integration with Actito.
  • Manual Approach — Implement your own notification presentation logic. This provides full control over the UI and behavior but requires handling all notification types, user interactions, and event reporting manually.
Important

If you choose the manual approach, you are responsible for managing the full notification lifecycle, including engagement tracking required for analytics and reporting.

Displaying lock screen media

To display rich notifications — such as lock screen media or dynamically updated content — your app must include a Notification Service Extension (NSE). This extension allows the system to process incoming notifications before they are shown to the user, enabling Actito to attach images or other media to your messages.

You can find detailed setup instructions in the Notification Service Extension guide.