这份文档还在翻译中,预期年底前完成。欢迎您提供宝贵的意见及建议。

Overview

On incoming events such as a new message, or an incoming call, the user often expects to receive a push notification, if the app is not active.

This guide explains how to configure your Android app to receive push notifications from the Nexmo Client SDK.

Set up Firebase project for your app

In order to enable push notifications for your Android app, you should use the Firebase Cloud Messaging (FCM) API. To do that, start by adding Firebase to your Android project.

In case you have not done that already, more details can be found in the official Firebase documentation.

Provision your server key

Obtain a jwt_dev, which is a jwt without a sub claim. More details on how to generate a JWT can be found in the setup guide.

Get your private_key_file from the Firebase console. Navigate to Firebase console, Project settings, Service accounts, Firebase Admin SDK, generate new private key. You will need to ensure the private_key_file is encoded to JSON using a suitable method before you can send it to the push service.

Get your projectId from the Firebase console. Navigate to Firebase console, Project settings, General, projectId.

Get your Nexmo Application ID, app_id. It can be obtained from Nexmo Dashboard.

Run the following Curl command, replacing jwt_dev, private_key_file, projectId, app_id with your values:

curl -v -X PUT \
   -H "Authorization: Bearer $jwt_dev" \
   -H "Content-Type: application/json" \
   -d "{\"token\":\"$private_key_file\", \"projectId\":\"$projectId\"}" \
   https://api.nexmo.com/v1/applications/$app_id/push_tokens/android  

Add Firebase Cloud Messaging dependency to your Android project

In your IDE, in your app level build.gradle file (usually app/build.gradle), add the firebase-messaging dependency:

dependencies{
    implementation("com.google.firebase:firebase-messaging:x.y.z")
}
dependencies{
    implementation 'com.google.firebase:firebase-messaging:x.y.z'
}

You need to replace x.y.z with the latest Cloud Messaging versions number, which can be found on the Firebase website.

Implement a service to receive push notifications

If you do not have one already, create a service that extends FirebaseMessagingService.

In order for Nexmo to be able to send push notifications to a device, the Nexmo server has to know the device token, also known as InstanceID.

In your class that extends FirebaseMessagingService, override onNewToken() method and update the Nexmo and pass new token to NexmoClient:

class MyFirebaseMessagingService: FirebaseMessagingService() {
    // No need for client initialization here. Client initialization is already done in BaseApplication class.
    // NexmoClient.Builder().build(this)
    private val client = NexmoClient.get()

    override fun onNewToken(token: String) {
        super.onNewToken(token)

        client.enablePushNotifications(token, object: NexmoRequestListener<Void> {
            override fun onSuccess(p0: Void?) { }

            override fun onError(apiError: NexmoApiError) {}
        })
    }
}
public class MyFirebaseMessagingService extends FirebaseMessagingService {

    // No need for client initialization here. Client initialization is already done in BaseApplication class.
    // new NexmoClient.Builder().build(this);
    private NexmoClient client = NexmoClient.get();

    @Override
    public void onNewToken(@NonNull String token) {
        super.onNewToken(token);

        client.enablePushNotifications(token, new NexmoRequestListener<Void>() {
            @Override
            public void onSuccess(@Nullable Void p0) {}

            @Override
            public void onError(@NonNull NexmoApiError nexmoApiError) {}
        });
    }
}

Make sure your service is declared in your AndroidManifest.xml (typically app/src/main/AndroidManifest.xml):

<service android:name=".MyFirebaseMessagingService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

Receive push notifications

Push notifications are received in your implementation of MyFirebaseMessagingService, on onMessageReceived() method.

You can use NexmoClient.isNexmoPushNotification(message.data)) to determine if the message is sent from Nexmo server.

Use processPushNotification(message.data, listener) to process the data received from Firebase Cloud Messaging (FCM) into an easy to use Nexmo object:

class MyFirebaseMessagingService : FirebaseMessagingService() {

    // We can retrieve client instance after it has been initializated.
    // NexmoClient.Builder().build(context)
    private val client = NexmoClient.get()

    override fun onNewToken(token: String) {
        super.onNewToken(token)
        //...   
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        // determine if the message is sent from Nexmo server
        if (NexmoClient.isNexmoPushNotification(remoteMessage.data)) {
            client.processNexmoPush(remoteMessage.data, object : NexmoPushEventListener {
                override fun onIncomingCall(call: NexmoCall?) {
                    Log.d("TAG", "FirebaseMessage:onIncomingCall() with: $call")
                }

                override fun onNewEvent(event: NexmoEvent?) {
                    Log.d("TAG", "FirebaseMessage:onNewEvent() with: $event")
                }

                override fun onError(apiError: NexmoApiError?) {
                    Log.d("TAG", "FirebaseMessage:onError() with: $apiError")
                }
            })
        }
    }
}
public class MyFirebaseMessagingService extends FirebaseMessagingService {

    // We can retrieve client instance after it has been initializated.
    // new NexmoClient.Builder().build(context);
    private NexmoClient client = NexmoClient.get();

    @Override
    public void onNewToken(@NonNull String token) {
        super.onNewToken(token);

        //...
    }

    @Override
    public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);

        // determine if the message is sent from Nexmo server
        if (NexmoClient.isNexmoPushNotification(remoteMessage.getData())) {
            client.processNexmoPush(remoteMessage.getData(), new NexmoPushEventListener() {
                @Override
                public void onIncomingCall(NexmoCall call) {
                    Log.d("TAG", "FirebaseMessage:onIncomingCall() with: " + call);
                }

                @Override
                public void onNewEvent(NexmoEvent event) {
                    Log.d("TAG", "FirebaseMessage:onNewEvent() with: " + event);
                }

                @Override
                public void onError(NexmoApiError apiError) {
                    Log.d("TAG", "FirebaseMessage:onError() with: " + apiError);
                }
            });
        }
    }
}

NOTE: In order to apply any methods on Nexmo Client object (for example answer a call, hangup, and so on) Nexmo Client has to be initialized and the user has to be logged in to it.

Conclusion

In this guide you have seen how to set up push notifications.

Overview

On incoming events such as a new message, or an incoming call, the user often expects to receive a push notification, if the app is not active.

There are two types of push notifications that you can use:

  • VoIP push (PushKit) - the better fit for applications that use Nexmo In-App Voice functionality.
  • Regular push (UserNotifications) - the better fit for applications that use Nexmo In-App Chat functionality.

This guide will cover how to VoIP push notifications with the Client SDK.

Create a push certificate

Apple Push Notifications service (APNs) uses certificate-based authentication to secure the connections between APNs and Vonage servers. So you will need to create a certificate and upload it to the Vonage Servers.

Adding a push notification capability

To use push notifications you are required to add the push notification capability to your Xcode project. To do this select your target and select Signing & Capabilities:

#{alt_text}

Then select add capability and add the Push Notifications capability:

#{alt_text}

If Xcode is automatically managing the signing of your app it will update the provisioning profile linked to your Bundle Identifier to include the capability.

Generating a push certificate

To generate a push certificate you will need to log in to your Apple developer account and head to the Certificates, Identifiers & Profiles page and add a new certificate:

#{alt_text}

Choose a VoIP Services Certificate and continue. You will now need to choose the App ID for the app that you want to add VoIP push notifications to and continue. If your app is not listed you will have to create an App ID. Xcode can do this for you if it automatically if it manages your signing for you, otherwise you can create a new App ID on the Certificates, Identifiers & Profiles page under Identifiers. Make sure to select the push notifications capability when doing so.

You will be prompted to upload a Certificate Signing Request (CSR). You can follow the instructions on Apple's help website to create a CSR on your Mac. Once the CSR is uploaded you will be able to download the certificate. Double click the .cer file to install it in Keychain Access.

To get the push certificate in the format that is needed by the Vonage servers you will need to export it. Locate your VoIP Services certificate in Keychain Access and right-click to export it. Name the export applecert and select .p12 as the format:

#{alt_text}

You can find more details about connecting to APNs in Apple's official documentation.

Upload your certificate

To upload your certificate to the Vonage servers you will also need:

  • A jwt_dev, which is a jwt without a sub claim. More details on how to generate a JWT can be found in the setup guide.

  • Your Nexmo Application ID. It can be obtained from the Nexmo Dashboard.

Then run the following Curl command, replacing jwt_dev, applecert.p12, app_id with your values:

hexdump -ve '1/1 "%.2x"' < applecert.p12 > applecert.pfx.hex
hextoken=`cat applecert.pfx.hex`

curl -v -X PUT \
   -H "Authorization: Bearer $jwt_dev" \
   -H "Content-Type: application/json" \
   -d "{\"token\":\"$hextoken\"}" \
   https://api.nexmo.com/v1/applications/$app_id/push_tokens/ios

Integrate push notifications in your application

VoIP push notifications are suitable for VoIP apps. Among other benefits, it allows you to receive notifications even when the app is terminated.

To integrate VoIP push in your app, follow these steps:

1. Enable VoIP Background Mode for your app

Similar to the process for adding the push notifications capability earlier, in Xcode, under your target, open Capabilities and select Background Modes. Once the capability is added tick the "Voice over IP" option:

#{alt_text}

2. Import PushKit, adopt PKPushRegistryDelegate, and sign up to VoIP notifications

Add a voipRegistry property:

let voipRegistry = PKPushRegistry(queue: nil)

and set it up:

func registerForVoIPPushes() {
    self.voipRegistry.delegate = self
    self.voipRegistry.desiredPushTypes = [PKPushType.voIP]
}

Add a voipRegistry property:

@property PKPushRegistry* voipRegistry;

and set it up:

- (void) registerForVoIPPushes {
    self.voipRegistry = [[PKPushRegistry alloc] initWithQueue:nil];
    self.voipRegistry.delegate = self;

    // Initiate registration.
    self.voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
}

3. Implement the following delegate method and add the code to handle an incoming VoIP push notification

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith 
        payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
    if(NXMClient.shared.isNexmoPush(userInfo: payload.dictionaryPayload)) {
        guard let pushPayload = NXMClient.shared.processNexmoPushPayload(payload.dictionaryPayload) else {
            NSLog("Not a Nexmo push notification")
            return
        }
    }
}
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload 
        forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion {
    if ([NXMClient.shared isNexmoPushWithUserInfo:payload.dictionaryPayload]) {
        NXMPushPayload *pushPayload = [NXMClient.shared processNexmoPushPayload:payload.dictionaryPayload];
        if (!pushPayload){
           NSLog(@"Not a nexmo push");
           return;
        };
    }
}

For the SDK to process the push properly NXMClient should be logged in.

4. Enable Nexmo push notifications through a logged in NXMClient

NXMClient.shared.enablePushNotifications(withPushKitToken: pushKitToken, 
        userNotificationToken: nil, isSandbox: true) { (error) in
    // code
}
[NXMClient.shared enablePushNotificationsWithPushKitToken:pushKitToken 
        userNotificationToken:userNotificationToken isSandbox:YES 
        completionHandler:^(NSError * _Nullable error) {
    // code 
}];
  • 'isSandbox' is YES/true for an app using the Apple sandbox push servers and NO/false for an app using the Apple production push servers.

  • 'pushKitToken' is the token received in pushRegistry(_:didUpdate:for:).

Conclusion

In this guide you have seen how to set up push notifications.