Skip to content

Step 5. Receive remote push notifications

Handle remote push messages that arrive on iOS in the app client.

This document describes how to receive notification events while the app is running with the Hive Axyl APNs plugin and how to check the payload when the user launches the app by tapping a notification.


You can implement APNs push reception handling in the following ways.

The APNs plugin provides only receive events and cold start notification retrieval. The app client itself handles how notifications are displayed, how data is interpreted, and screen navigation.

Note
  • On iOS, the OS does not deliver receive events directly to the plugin. When the app's delegate forwards OS callbacks to the Notify* methods, the plugin raises the NotificationPresented or NotificationOpened event.
  • The app's application(_:didFinishLaunchingWithOptions:) delegate code also captures the cold start payload, and it must pass the captured payload with NotifyColdStartNotificationAsync().


Method 1. Receive notifications while running

When the app's delegate forwards the following two callbacks, the NotificationPresented or NotificationOpened event occurs depending on the notification state. The events are delivered on the engine main thread.

  • NotifyWillPresentNotificationAsync(notification): Call it right before a notification is displayed in the foreground (willPresent). After the call, the NotificationPresented event occurs. The app returns the foreground presentation options (badge, sound, banner, and so on) directly to the OS completionHandler within its own delegate.
  • NotifyDidReceiveResponseAsync(notification, actionIdentifier): Call it when the user taps the notification or selects a custom action (didReceive). After the call, the NotificationOpened event occurs. For actionIdentifier, pass the OS's UNNotificationResponse.actionIdentifier value as is.

For both methods, the success response contains no data for the app to use, and the return objects branch into Success/Failure. PresentationOptions in the NotifyWillPresentNotificationAsync() response is always an empty array. The app returns the presentation options directly to the OS completionHandler.


Call example

using Hive.Axyl.Core;
using Hive.Axyl.Push.Addon.APNS;

IAPNSPlugin apns = HiveCore.Resolve<IAPNSPlugin>();

apns.NotificationPresented += notification =>
{
    // Foreground reception - the app decides what to do, such as showing an in-app banner.
    string title = notification.Title;
    string body  = notification.Body;

    // Custom data is delivered as the original APNs payload JSON.
    string userInfoJson = notification.UserInfoJson;
};

apns.NotificationOpened += opened =>
{
    // Notification tap or action selection - the app decides what to do, such as navigating to a screen.
    string actionIdentifier = opened.ActionIdentifier;
    string userInfoJson = opened.Notification.UserInfoJson;
};


Considerations when calling

  • The APNs plugin instance must be kept alive to receive the NotificationPresented and NotificationOpened events.
  • The app delegate must forward OS notification callbacks to the plugin's Notify* methods.
  • The app client decides directly through the OS completionHandler how to display notifications in the foreground.


Method 2. Handle app entry from a notification tap

When the user launches the app by tapping a notification, get the payload of that notification with GetColdStartNotificationAsync().

Method

public Task GetColdStartNotificationAsync();


The cold start notification buffer is single-use. For a normal launch, or after the notification has already been taken out once, an empty notification with all fields set to default values is returned, and this is not a failure. Call it once at app startup to check whether the app was entered from a notification tap.

When the app is launched from a notification tap while it is not running, you can get the payload with GetColdStartNotificationAsync() only after you first pass the original payload JSON captured in the app delegate with NotifyColdStartNotificationAsync(userInfoJson).


Call parameters

Field name Type Required Description
ct CancellationToken Optional The cancellation token used to cancel the call. If omitted, the default value is used.


Call example

The return object of GetColdStartNotificationAsync(), ApnsServiceGetColdStartNotificationResult, is divided into success and failure states. The method call does not throw exceptions (Exception), and all processing results are delivered through the return object. Therefore, instead of using a separate try/catch statement, branch on the response status with a switch statement.

using Hive.Axyl.Core;
using Hive.Axyl.Push.Addon.APNS;

ApnsServiceGetColdStartNotificationResult result = await apns.GetColdStartNotificationAsync();

switch (result)
{
    case ApnsServiceGetColdStartNotificationResult.Success success:
        ApnsNotification notification = success.Data.Notification;
        // For entry from a notification tap, the payload is filled in; for a normal launch, all fields have default values.
        if (!string.IsNullOrEmpty(notification.UserInfoJson))
        {
            // Interpret the payload and handle it, such as by moving to a specific screen.
        }
        break;

    // Handle common failures - for the detailed error model, see [Error handling](PLACEHOLDER_에러처리_링크)
    case ApnsServiceGetColdStartNotificationResult.Failure failure:
        HiveError err = failure.Problem;
        Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
        break;

    // Safety net: unknown new results
    default:
        Debug.LogWarning($"Unhandled result: {result.GetType().Name}");
        break;
}


Considerations when calling

  • Call it once at app startup to check whether the app was entered from a notification tap.
  • Even if Success is returned, if the notification fields have default values, it is a normal launch or a buffer that was already taken out.
  • To capture the cold start payload, the app delegate must handle the launch options and call NotifyColdStartNotificationAsync(). For details, see Prepare delegate code.
  • On macOS, an empty notification can be returned if the build has no capture source, such as a normal .app launch, or if you get the notification before the relay is complete.


Response data

On success, Data of ApnsServiceGetColdStartNotificationResult.Success contains the notification.

Field name Type Required Description
Data.Notification ApnsNotification Required The payload of the notification the user tapped. For a normal launch or if the buffer was already taken out, it is an empty notification with all fields set to default values.


Response status

The return object ApnsServiceGetColdStartNotificationResult branches into the following cases. Handle it with a switch statement.

Response case Description App client handling
Success The retrieval succeeded. For entry from a notification tap, the payload is filled in; for a normal launch, it is an empty notification. Branch on whether a payload is present
Failure Native integration error. Problem (HiveError) contains the details. Treat it as a normal launch or log the error


For reference. Check received notification data

Custom data sent along with the notification (for example, a deep link or an event identifier) is delivered in ApnsNotification.UserInfoJson, the original APNs payload JSON. Nested structures are delivered without loss, so the app parses the JSON to implement behavior such as screen navigation and state updates.

Data is delivered bundled with a displayed notification, and whether a message that contains only data (silent push) can be sent follows the push sending (server) specification. For the related build configuration, see APNs integration setup.


For reference: ApnsNotification structure

A received notification has a structure that carries over the content of the iOS notification (UNNotification) as is. Fields without a value have default values (empty string/0).

Field name Type Required Description
Title string Required The notification title.
Subtitle string Required The notification subtitle.
Body string Required The notification body.
Badge int Required The app icon badge count. 0 if there is no value or if the payload clears the badge.
Sound string Required The notification sound.
CategoryIdentifier string Required The notification category identifier.
ThreadIdentifier string Required The notification group (thread) identifier.
LaunchImageName string Required The launch image name.
TargetContentIdentifier string Required The target content identifier.
InterruptionLevel UNNotificationInterruptionLevel Required The notification interruption level (Passive/Active/TimeSensitive/Critical). If there is no value, it is Unspecified.
RelevanceScore double Required The relevance score used to sort notification summaries (0.0 to 1.0).
UserInfoJson string Required The original JSON string of the entire APNs payload (aps dictionary + custom keys). Nested structures are delivered without loss.
Note

Displaying notification images requires a separate UNNotificationServiceExtension target. The SDK does not provide an extension runtime, and if the app does not add one, notifications display only text.


The following documents are related to the content of this document.