UserGuide

iOS Notifications

From Xojo Documentation

Setting Expectations

There are a a few main things that you need to understand about working with User Notifications on iOS:

  1. You must request permission from the user of the device to present notifications.
  2. A user can revoke permission at any time which means your notifications will no longer be delivered.
  3. Timely delivery is not guaranteed. Notifications can be delayed for a number of reasons including (but not limited to):
    1. The user's Screen Time or Sleep settings
    2. The user's preferences for your app.
    3. The device's available power.
  4. Remote Notifications that are pushed through a server do not work in the iOS simulator. That said, you can create remote notification packet and drag and drop it onto the simulator for testing purposes.

These are limitations of iOS itself, not Xojo.

Notification Types

There are four kinds of notifications available to you in the Xojo Mobile Framework:

  1. Time Interval Notifications which are delivered based on the number of seconds between the request and the delivery. Xojo allows you to use and Integer or a DateInterval to specify the interval.
  2. Calendar Notifications which are delivered based on a calendar date, specified with a DateTime.
  3. Location Notifications which are delivered when the device moves into or out of a circular region defined by geographic coordinates and a radius.
  4. Remote Notifications which are delivered through the Apple Push Notification service (APNs).

Quick Start

To add Notification support to your project you need to add a NotificationCenter object to your project. You can do this by right-clicking on the Navigator or clicking the Insert icon on the toolbar and selecting "Notifications".

NOTE: If you do not add the NotificationCenter object to your project, trying to execute any of the code below will result in an UnsupportedOperationException.

Getting Permission

As mentioned above, you will need to request permission to send notifications to the user. To do this, you will call a method on the NotificationCenter object:

NotificationCenter.RequestAuthorization(ParamArray options() as MobileNotifications.AuthorizationOptions)

The call to this method is asynchronous and will trigger one of two events on the NotificationCenter object itself. The options available to you are:

  • Badge - Ability to add a badge to your app icon when a notification is delivered
  • Sound - Ability to play a sound when a notification is delivered
  • Alert - Ability to show an alert when a notification is delivered
  • CarPlay - Ability to show notifications in CarPlay when they are delivered
  • CriticalAlert - Ability to show notifications that override sound and banner restrictions. This option is designed for government agencies and requires a special entitlement from Apple.
  • ProvidesNotificationSettings - Indicates to the system that your app provides its own notification settings view.
  • Provisional - Ability to show notifications on a provisional basis which the user can decide to accept later.
  • Announcement - Ability to have notifications read over AirPods.


AuthorizationSucceeded(settings as NotificationSettings)

This event will be raised if the user gives (or has given) permission to present notifications on their device. The settings object lets you see the current state of notifications on the device when the request was made, such as whether the user has sound turned on or off or if your notifications appear in the device's notification center at all.

Error(error as NotificationException, notification as Notification)

This event can be raised in many situations, but when requesting permission, that would usually mean that the user declined or has completely turned off notifications for your app.

Scheduling Notifications

Once you have permission, sending a simple notification is easy! Add a button to screen1, add a Pressed event and add the following code:

// First you need to set up a content object
Var content as New NotificationContent("Xojo can send notifications!")
// ...and then you schedule it!
NotificationCenter.Send(content)

Before you hit Run, there are two more events you need to know about.

NotificationSent(notification as Notification)

This event is raised when a notification has been added to the system for delivery at some time in the future. NOTE: In all cases where a notification is received as a parameter, the actual object will be a subclass of Notification indicating the actual notification type: • CalendarNotification • LocationNotification • RemoteNotification • TimeIntervalNotification

NotificationReceived(notification as Notification) as PresentationModes

This event is raised when your app is in the foreground and a notification is delivered. This is important because you may want to deliver the notification yourself directly to the user. If you would rather have the system deliver it, you will add this return statement:

Return MobileNotifications.PresentationModes.All

If you don't do this and your app is still in the foreground it'll look like nothing is happening!

Other Events

BackgroundNotificationReceived(userInfo as Dictionary) as RemoteFetchResults


This event is raised when a remote content-only notification is received. If your application is in the background when the notification is delivered, your app will be launched in the background and given approximately 30 seconds to retrieve whatever information it needs and must return a value indicating if it was successful or not. Your code should not block the main thread during this time as it will make the user's device appear unresponsive for an unknown reason.

OpenNotificationSettings(notification as Notification)


This event is raised if you have specified that your app has its own notifications settings and the user clicks the app's notification settings link in the system notification settings for your app.

ProcessUserResponse(notification as Notification, action as String, textResult as String)

This event is raised when a notification is presented to the user and they take some sort of action on it. By default, the only action available is that the user touched it, but there are some options for adding buttons and text input fields. See the section on Categories below for more information.

RemoteNotificationSucceeded(token as String)


This event is raised when you request permission to send remote notifications to the device. The token you receive is a globally unique identifier for this particular instance of your app on this device. If your app is deleted and reinstalled, this identifier will be changed.

Content Options

While the example provided above was a very simple example, it's important to know that the content of notifications is extremely flexible. The constructor for the NotificationContent class takes the following parameters:

  • Title as String: First line of the title.
  • Subtitle as String: The second line of the title (optional).
  • Body as String: The body of the notification (optional).
  • Badge as Integer: The badge to apply to the application icon (optional, 0 = none).
  • data As Dictionary: Data to be delivered with the notification. The data contained within must be compatible with JSON, so values can be strings, numbers, booleans, dictionaries and arrays of any of those things.
  • thread as String: An identifier for grouping similar notifications together.
  • category as String: An identifier for an interactivity category.

Time and Date Notifications

Instead of creating a notification to be shown right now as we did above, there are several other ways to create a notification. Unlike the first example, for any notifications that you create for delivery some time in the future, the framework will return a UUID so that you can remove the notification in the future if it becomes irrelevant for some reason.

// Set up some content
Var content as new NotificationContent("Bagels on Sale!", "", "Today only – 99¢ each!", 1)

// Schedule a notification for 10 seconds in the future
Var uuid as String = NotificationCenter.Send(10, content)

// Schedule a notification 3 days from now
Var di as New DateInterval(0, 0, 3)
Var uuid2 as String = NotificationCenter.Send(di, content)

// Schedule a notification for a particular date
Var dt as New DateTime(2021, 1, 1, 0, 0, 0, Timezone.Current)
Var uuid3 as String = NotificationCenter.Send(dt, content)

Location Notifications

For location based notifications you will need to get another form of permission from the user. This is the "while in use" permission for the user's location. It is the system itself that will be tracking the user's movements, but you will still need user permission to set up the notification itself. You can get that permission using the MobileLocation control. Once you have that, you can schedule notifications for when a user enters or leaves a circular region defined by a geographic coordinate, a radius and an identifier.

// Set up some content
Var content as new NotificationContent("Bob's Bagels", "", _
"Come on in and see us today!")
// Schedule a notification for when users get near the store
Var uuid as String = NotificationCenter.Send(40.8135, -74.1146, 300, _
"STORE", LocationNotification.Modes.NotifyOnEntry, content)

Keep in mind that iOS uses some heuristics to figure out if a user is actually entering or leaving the region and that they are not just skimming the edge, so your notification may not appear immediately.

Remote Notifications

To send remote notifications to your app, there are a few things you'll need to do the following things:

  1. Apple Developer website
    1. Remote Notifications will need to be added to the application's identifier.
    2. You will also need an Apple Push Services certificate
  2. Xojo
    1. The Remote Notifications entitlement needs to be enabled in the Xojo iOS build settings on the Advanced Tab under Capabilities.
  3. A tool or provider for interfacing with the Apple Push Notification system (APNs).

Once you have these things, sending remote notifications to your app is pretty simple. If you want to send notifications that are visible to the user like the ones above, you will still need to get the user's permission for that. In addition, you need to register your app for Remote Notifications by calling:

NotificationCenter.RegisterForRemoteNotifications

This asynchronous call will try to call into Apple's Push Notification service (APNs) servers to get a globally unique identifier for your app on this particular device. If successful, the RemoteRegistrationSucceeded event will fire and provide you with a hex encoded token for use when you need to send a message to the current device. You should immediately send this information to a server and store it with other customer relevant data. This token will change if the user removes your app and reinstalls it so you should request this information every time the app is launched.

For more information about sending remote notifications see Apple's documentation on the subject.

Categories

Categories make it possible to allow users to respond directly to a delivered notification through buttons and text fields. Here's an example of how you might allow a direct text response to a notification:

// Create a new category with the identifier "REPLY"
Var cat as New NotificationCategory("REPLY")

// Create a text field
// Parameters:
// caption - Caption on the action button
// hint - Text hint
// sendcaption - Caption on the button to send the text
// identifier - Identifier that will be sent to the app
Var textfield as New NotificationResponseTextField("Reply", _
"Please type your reply", "Send", "REPLY")
cat.actions.Add(textfield)


// Add a Cancel button
// Parameters:
// caption - Caption on the action button
// identifier - Identifier that will be sent to the app
cat.actions.Add(New NotificationResponseButton("Cancel", "CANCEL"))

NotificationCenter.AddResponseCategory(cat)

Once you have this category defined, you can use the "REPLY" category whenever scheduling a notification and it will have these two options available.

Tips & Tricks

While you can't send remote notifications to the iOS simulator (Requires Xcode 11.4 or higher) for testing, you drag a remote notification packet directly into the simulator. Here's an example:

{
   "Simulator Target Bundle": "your.bundle.identifier.here",
   "aps": {
      "alert": {
         "title" : "Chicken Avocado Taco Platter", "subtitle" : "All New Flavors!",
         "body" : "Special - Today Only $4.99"
      } 
   }
}

If you would like to test sending remote notifications to a physical device, we suggest using this utility: https://github.com/onmyway133/PushNotifications/releases

See Also

MobileNotifications, CalendarNotification, LocationNotification, Notification, NotificationContent, NotificationSettings, NotificationException, NotificationResponseCategory, NotificationSettings, RemoteNotification, and TimeIntervalNotification classes.