Push notifications

Last modified by Sylvain Berfini on 2023/07/10 15:48

Push notifications

Push notification configuration as also been simplified.

This feature is enabled automatically on Android & iOS but you can disable it with core.setPushNotificationEnabled(false) or with the following rc setting:

[net]
push_notification=0

When enabled, liblinphone can find the push token of your device by itself and configure it in the Account / ProxyConfig objects for which push notifications are allowed.

To do so, call account.setRemotePushNotificationAllowed(true) / proxyConfig.setRemotePushNotificationAllowed(true) or in your rc configuration set:

[proxy_0]
push_notification_allowed=1
remote_push_notification_allowed=1

Note this setting is also enabled by default on mobile plateforms if not set in your default configuration.

Another change is the format of the push information in the contact header parameters.

We have started changes in flexisip to better follow the RFC 8599. To keep the previous format, set the following: (legacy format support was dropped in SDK 5.2)

[net]
use_legacy_push_notification_params=1

Finally, for this to work, the following conditions must be met depending on the platform:

Android

  • Add if not already done your google-services.json file in your module folder (usually app/)
  • Add the firebase dependency in your app's build.gradle file
dependencies {
  implementation platform('com.google.firebase:firebase-bom:31.5.0')
  implementation 'com.google.firebase:firebase-messaging'
}
  • Add the liblinphone FirebaseMessaging service in your application
<service android:name="org.linphone.core.tools.firebase.FirebaseMessaging" android:exported="false">
   <intent-filter>
       <action android:name="com.google.firebase.MESSAGING_EVENT" ></action>
   </intent-filter>
</service>
  • When a push notification will be received, if your application is still alive, the core.ensureRegistered() method will be called automatically.
    Otherwise we will send a broadcast intent in which you should create your Core object again.
    Here's how to listen for it:

Create a CorePushReceiver class somewhere (in my example it will be in .core package):

public class CorePushReceiver extends BroadcastReceiver {
   @Override
   public void onReceive(Context context, Intent intent) {
       //TODO: create a Core object to receive the call or message that triggered the push
   }
}

Add your receiver class in your Manifest.xml:

<receiver android:name=".core.CorePushReceiver">
   <intent-filter>
       <action android:name="org.linphone.core.action.PUSH_RECEIVED"></action>
   </intent-filter>
</receiver>

iOS

The 5.0 linphone SDK will automatically register for remote notifications if you enable it in the core :

in Objective-C: 

linphone_core_set_push_notification_enabled(core, true)

in Swift:

core.pushNotificationEnabled = true

Enabling the push notifications in the core will cause it to create a PushRegistry on start. This means that you do not need to handle it in your App anymore. However, if you already implemented it when using SDK older than 5.0, they will not be compatible. If you would rather manage all of the push notification settings in your app, leave the core.pushNotificationEnabled to false and ignore the rest of this section.
​​​​

You must handle the Remote Notification Device Token directly in your application delegate by implementing the didRegisterForRemoteNotificationsWithDeviceToken function :

in Objective-C: 

- (void)application:(UIApplication *)application  didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    linphone_core_did_register_for_remote_push(core, (__bridge void*)remoteNotificationToken);
}

in Swift:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    var stringifiedToken = deviceToken.map{String(format: "%02X", $0)}.joined()
    stringifiedToken.append(String(":remote"))
    core.didRegisterForRemotePushWithStringifiedToken(deviceTokenStr: stringifiedToken)
 }

For a given account, you should make sure that the push settings matches with the behaviour you expect :

in Objective-C:

LinphoneAccountParams *newParams = linphone_account_params_clone(linphone_account_get_params(account));

// Set wether VOIP push notifications are enabled
linphone_account_params_set_push_notification_allowed(newParams, pushEnabled);
  
// Set wether remote push notifications are enabled
linphone_account_params_set_remote_push_notification_allowed(newParams, pushEnabled);

linphone_account_set_params(account, newParams)
linphone_account_params_unref(newParams);

in Swift:

var newParams = account.params.clone()

// Set wether VOIP push notifications are enabled 
newParams?.pushNotificationAllowed = pushEnabled
  
// Set wether remote push notifications are enabled
newParams?.remotePushNotificationAllowed = pushEnabled

account.params = newParams

If you are not using legacy push params, the default push notification provider will be set to "apns" which will only work if you are signing you application with a production certificate. If you are signing with a developper certificate, iOS requires the provider to be "apns.dev". This is one way to handle it in your account parameters :

in Objective-c:
 

LinphoneAccountParams *newParams = linphone_account_params_clone(linphone_account_get_params(account));
LinphonePushNotificationConfig* pushConfig = linphone_account_params_get_push_notification_config(newParams);
linphone_push_notification_config_set_provider(pushConfig, "apns.dev");
linphone_account_set_params(account, newParams)
linphone_account_params_unref(newParams);

in Swift:

let newParams = myAccount.params?.clone()
newParams.pushNotificationConfig.provider = "apns.dev"
myAccount.params = newParams