Push Notifications allow you to reach users irrespective of whether your application is running in the foreground, the background or has been terminated, even when your application is not connected to Ably.
On iOS, Ably connects to APNs to send messages to devices. On Android, Ably connects to Firebase Cloud Messaging to send messages to devices. As both services do not guarantee message delivery and may even throttle messages to specific devices based on battery level, message frequency, and other criteria, messages may arrive much later than sent or ignored.
- Requires initialising
AblyRealtime
: Currently activating push notifications for a device requires an instance ofAblyRealtime
which gets instantiated when the application starts up. Please, submit an issue if you do not require a realtime instance and would like to use Xamarin push notifications without using anAblyRealtime
connection. For the time being when calling(AndroidMobileDevice|AppleMobileDevice).Initialise
please setClientOptions.AutoConnect
tofalse
which will keep theAblyRealtime
instance from using any resources.
- Android API level 19+ (Android 4.4+)
- Android devices
- Android emulator (with Google APIs)
- iOS 10+
- Physical devices only
- Not supported: iOS Simulator. Calling
UIApplication:registerForRemoteNotifications
will result inapplication:didFailToRegisterForRemoteNotificationsWithError
method being called in your AppDelegate with an error:remote notifications are not supported in the simulator
). This is an iOS simulator limitation.
To get push notifications setup in your own app, read Setting up your own app.
- Open the DotnetPush solution which can be found in the
examples
folder in the repository, make sure to change the application Id in the Manifest file. - Create a Firebase project, and in the Project settings, add an android app with your unique application ID. Follow the steps provided on the setup process, or the following:
- You can leave
Debug signing certificate SHA-1
empty. - Download the generated
google-services.json
file - Place
google-services.json
inexample/android/app/
. We havegitignore
d this file since it is associated with our Firebase project, but it is not sensitive, so you can commit it to share it with other developers/colleagues.
- You can leave
- Provide Ably with the FCM server key: In your firebase project settings, create or use an existing cloud messaging server key, and enter it in your Ably app's dashboard (App > Notifications tab > Push Notifications Setup > Setup Push Notifications).
- You can follow the excellent Android push notifications tutorial which includes screenshots for the steps you need to take to link your Ably account with Firebase messaging.
- You need to have a Apple developer program membership ($99/year)
- Open your iOS app in Xcode: when in your project directory, run
xed ios
or double clickios/Runner.xcworkspace
inyour_project_name/ios
- Add your developer account in Xcode, in
Preferences
>Accounts
. - In the project navigator, click
Runner
> ClickRunner
target (not project) >General
. Change the bundle identifier to a unique identifier. Then, under theSigning & Capabilities
tab >Team
dropdown menu, select your developer team associated with your developer account. This will register your bundle ID on App Store connect if it is not yet registered. - Create a push notification certificate (
.p12
) and upload it to the Ably dashboard to allow Ably to authenticate with APNs on your behalf, using How do I obtain the APNs certificates needed for iOS Push Notifications?. - Add
Push Notifications
capability: Click Runner in project navigator, clickRunner
target, under the Signing & Capabilities tab, click+ Capability
, and selectPush Notifications
. - Add
remote notification
background mode:- Under the Signing & Capabilities tab, click
+ Capability
and selectBackground Modes
. - Check
remote notifications
.
- Under the Signing & Capabilities tab, click
- Add your developer account in Xcode, in
- The above is also described in our native ios tutorial.
Devices need to be activated with Ably once. Once activated, you can use their device ID, client ID or push token (APNs device token/ FCM registration token) to push messages to them using the Ably dashboard or a Push Admin (SDKs which provide push admin functionality, such as the .net sdk, Ably-java, Ably-js, etc.). However, to send push notifications through Ably channels, devices need to subscribe to a channel for push notifications. Once subscribed, messages on that channel with a push payload will be sent to devices which are subscribed to that channel.
The DotNetPush app contains an example of how to use the Push Notification functionality. For Android devices please refer to MainActivity.cs and MyFirebaseMessaging.cs. For iOS please refer to AppDelegate.
- The first step is to initialise the specific mobile device. You can achieve this by using either
AppleMobileDevice.Initialise
orAndroidModileDevice.Initialise
. To initialise you need to pass a valid AblyClientOptions
which will be used to initialise the Ably realtime client and an instance ofPushCallbacks
which you can use to recieve notification when the device isActivated
,Deactivated
orSyncRegistrationFailed
. - The initialise method will create an instance of
IRealtimeClient
which can be used to activate push notifications for the device by callingclient.Push.Activate()
. - Active is not guaranteed to happen straight away. The developer will be notified by calling
ActivatedCallback
which was passed to theInitialise
method when hooking up push notifications
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Xamarin.Forms.Forms.Init();
InitialiseAbly();
//...
return base.FinishedLaunching(app, options);
}
private void InitialiseAbly()
{
var clientId = ""; // Set a clientId or generate one. It can be later used to send push notifications to the device.
var callbacks = new PushCallbacks
{
ActivatedCallback = error => { /* handle notification */ },
DeactivatedCallback = error => { /* handle notification */ },
SyncRegistrationFailedCallback = error => { /* handle notification */ },
};
_realtime = AppleMobileDevice.Initialise(GetAblyOptions(savedClientId), callbacks);
_realtime.Connect();
}
private ClientOptions GetAblyOptions(string savedClientId)
{
var options = new ClientOptions
{
// https://ably.com/documentation/best-practice-guide#auth
// recommended for security reasons. Please, review Ably's best practise guide on Authentication
// Please provide a way for AblyRealtime to connect to the services. Having API keys on mobile devices is not
Key = "<key>",
ClientId = string.IsNullOrWhiteSpace(savedClientId) ? Guid.NewGuid().ToString("D") : savedClientId,
};
_realtime = new AblyRealtime(options);
// If you are going to use the AblyRealtime client in the app feel free to call Connect here
// If not then skip it and add `AutoConnect = false,` to the ClientOptions.
_realtime.Connect();
return options;
}
Use the AblyRealtime
returend by Initialise
.
- Get the Realtime/ Rest channel:
var channel = realtime.Channels.Get("channelName")
- Subscribe the device to the push channel, by either using the device ID or client ID:
channel.Push.SubscribeClient()
orchannel.Push.SubscribeDevice()
- This is different to subscribing to a channel for messages.
- Your device is now ready to receive and display user notifications (called alert notifications on iOS and notifications on Android) to the user, when the application is in the background.
- For debugging: You could use the Ably dashboard (notification tab) or the Push Admin API using another SDK to ensure the device has been subscribed by listing the subscriptions on a specific channel. Alternatively, you can list the push channels the device or client is subscribed to:
var subscriptions = channel.Push.ListSubscriptions()
. This API requires Push Admin capability, and should be used for debugging. This means you must use an Ably API key or token with thepush-admin
capability.
Once you have subscribed to recieve push notifications for a channel, other devices can send messages with specific MessageExtras
which will trigger a push notification to be sent to your device.
Shows a notification to the user immediately when it is received by their device.
Android: This is known as a notification message. A notification message cannot be customised or handled (e.g. run logic when a user taps the notification) - therefore, if you need to handle user taps or customize a notification, send a data message and create a local notification.
iOS: This is known as an alert push notification. An alert notification can be customised.
This is how you construct a message with a push notification. Normal subscribers will only receive the message where devices subscribed to that channel will receive the Push notification.
var extrasText = @"{
""push"": {
""notification"": {
""title"": ""Hello from Ably."",
""body"": ""Example push notification from Ably."",
""sound"": ""default"",
},
},
}
";
var extras = new MessageExtras(JToken.Parse(extrasText));
var message = new Message("messageName", "This is an Ably message published on channels that is also sent as a notification message to registered push devices.", messageExtras: extras); // Optional data field sent will not be received in push messages.
Allows you to run logic in your application, such as download the latest content, perform local processing and creating a local notification.
Android: This is known as a data message.
iOS: This is known as a background notification. These messages must have a priority of 5
, a push-type of background
, and the content-available
set to 1
, as shown in the code snippet below. To learn more about the message structure required by APNs, read
Pushing Background Updates to Your App. You may see this documented as "silent notification" in Firebase documentation.
On iOS, a background notification may be throttled to 2 or 3 messages per hour, or limited for other reasons (for example, your app was just installed recently). To ensure your messages arrive promptly, you may send a message with both notification and data, which will show a notification to the user.
var extras = new MessageExtras(JToken.Parse(@"{
""push"": {
""data"": {""foo"": ""bar"", ""baz"": ""quz""},
""apns"": {
""apns-headers"": {
""apns-push-type"": ""background"",
""apns-priority"": ""5"",
},
""aps"": {
""content-available"": 1
}
}
},
}
"));
var message = new Message("messageName", "This is an Ably message published on channels that is also sent as a notification message to registered push devices.", messageExtras: extras); // Optional data field sent will not be received in push messages.
You can find an example of how to receive Push notification messages in the DotNetPush sample app.
For iOS check the DidReceiveRemoteNotification
method inside AppDelegate.cs
and for Android check OnMessageReceived
method inside MyFirebaseMessaging.cs
Only use high priority when it requires immediate user attention or interaction. Use the normal priority (5) otherwise. Messages with a high priority wake a device from a battery saving state, which drains the battery even more.
- High priority:
'priority': 'high'
insidepush.fcm.android
for Android.apns-priority: '10'
insidepush.apns.apns-headers
for iOS. - Normal priority:
'priority': 'normal'
insidepush.fcm.android
for Android.apns-priority: '5'
insidepush.apns.apns-headers
for iOS.
Push notifications containing both the notification and data objects will be treated as both alert notifications and data messages.
For examples of handling incoming messages and dealing with notifications, see push_notification_handlers in the example app.
Android: If the app is in the background / terminated, you cannot configure / disable notification messages as they are automatically shown to the user by Firebase Messaging Android SDK. To create notifications which launch the application to a certain page (notifications which contain deep links or app links), or notifications which contain buttons / actions, images, and inline replies, you should send a data message and create a notification when the message is received.
iOS: If the app is in the background / terminated, the Ably sdk doesn't provide the functionality to configure / extend alert notifications on iOS, and these will automatically be shown to the user.
Do this only if you do not want the device to receive push notifications at all.
realtime.Push.Deactivate();