Mobile SDK

iOS or Android

SDK Features - Push Notification

Info: Stellantis Mobile SDK for ex Groupe PSA brands (Citroën, DS, Peugeot, Opel and Vauxhall) is not publicly available yet.

Security: Push Notification require the following security schemes to be valid

Connectivity: this feature is available using 📡 Cellular network over-the-air

  • 🚗 The vehicle should be able to access internet.
  • 📱 The device should be able to access internet.

References: check-out 🔔 Push Notification component list of APIs.

Push Notification is a feature allowing receiving system notifications on the End User mobile device through Stellantis’ Firebase service.

Notifications can be triggered by the following events:

  • ✅🔋 Remote charge ends successfully: the vehicle battery reaches 100%.
  • ❌🔌 remote charge is interrupted: the charge is stopped before reaching 100%.

In order to add the Push Notification feature to your project, you must perform the following steps:

  • Step 1: Configure Stellantis’ Firebase Account in the project.
  • Step 2: Deal with Stellantis’ Firebase Token registration.
  • Step 3: Select the vehicle(s) to enable Push Notif on.
  • Step 4: Enabled service on the selected vehicles
  • Step 5: Customize the notification appearance on the user device.

1. Firebase Config #

First of all, you need to set up Stellantis’ Firebase configuration in your App.

Push Notification are triggered by Stellantis’ Firebase, that why Stellantis Firebase Account should be activated inthe project. Doing so, Stellantis will be able to trigger push notification on the user device.

Once set up, you must inform create a link between the mobile device and Stellantis Firebase account by registering token.

To implement Firebase in your project, checkout firebase configuration for iOS or Android.

Multiple Firebase Accounts

In case you already have Firebase configured for your own use, this is how you can add a second account in your project.
Android
iOS

Delete unnecessary provider

If com.google.firebase.provider.FirebaseInitProvide it is registered in the manifest of your project, you should delete it.

Register the supplementary config

Use this code to register the supplementary config:

1
2
3
4
5
6
7
val firebaseOptions = FirebaseOptions.Builder().setApiKey("AIzaSyCCdTRue6r3Y3d-jfU-AasXeVmFyKCnIIE")
    .setProjectId("rt-b2c-fcm-staging")
    .setGcmSenderId("1024186873749")
    .setStorageBucket("rt-b2c-fcm-staging.appspot.com")
    .setApplicationId("1:1024186873749:android:88ac59e395d56f4a27289c").build()

FirebaseApp.initializeApp(applicationContext, firebaseOptions,"pushNotifications")

Retrieve Firebase token

Implement this code to retrieve the firebase token:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
val messagingApp = FirebaseApp.getInstance("pushNotifications")
val firebaseMessaging = messagingApp.get(FirebaseMessaging::class.java) as FirebaseMessaging

firebaseMessaging.token.addOnCompleteListener(
  OnCompleteListener { task ->
    if (!task.isSuccessful) {
        Timber.w("Fetching FCM registration token failed with exception: ${task.exception}")
        return@OnCompleteListener
    }

    // Get new FCM registration token
    val token = task.result
    Timber.i("registerForPushNotifications : pushId = $token")
  }
)

Add config files

Add the 3 config files from the firebase console in your project:

  • GoogleService-Info-Debug.plist
  • GoogleService-Info-Push.plist
  • GoogleService-Info.plist

Register the supplementary config

Use this code to register the supplementary config:

1
2
3
4
if let pushFilePath = Bundle.main.path(forResource: "GoogleService-Info-Push", ofType: "plist"),
    let pushOptions = FirebaseOptions(contentsOfFile: pushFilePath) {
    FirebaseApp.configure(name: firebaseName, options: pushOptions)
  }

Retrieve Firebase token

Implement this code to retrieve the firebase token:

1
2
3
4
5
6
7
guard let pushConfig = FirebaseApp.app(name: firebaseName) else { return }
Messaging.messaging().retrieveFCMToken(forSenderID: pushConfig.options.gcmSenderID) { fcmToken, error in
    if let fcmToken = fcmToken {
        // Configure SET pims.sdk.token
        // Check-out Step 2
    }
}

2. Deal with Firebase Token #

Setting up Firebase on the device allows retrieving a Firebase FCM token.

This token needs to be registered to Stellantis’ in order to create an association with a mobile device.

Register FCM Token

The Firebase FCM token needs to be registered in the following API in order for Stellantis to trigger Push Notification on the user device:

1
2
3
4
5
6
7
pims.set("pims.sdk.token",
  mapOf( /* parameters */
  Pair("action", "registerPushToken"),
  Pair("token", "<fcm_token>")
  )
) { message -> /* handle message */ }
1
2
3
4
5
6
7
pims.set(api: "pims.sdk.token", 
  parameters: [
  "action": "registerPushToken",
  "token": "<fcm_token>",
  ]
) { (message) in /* handle message */ }
1
2
3
4
5
6
// representation of the `succeeded` dictionary object message as JSON
{
  "transactionId": "953cfefb-bc72",
  "status": "SUCCEEDED",
  "result": null
}

false

Unregister FCM Token

You should implement a listener function in your App, if the system notifications are disabled by the user, you should call the following API to unregister the token:

1
2
3
4
5
6
pims.set("pims.sdk.token",
  mapOf( /* parameters */
  Pair("action", "unregisterPushToken"),
  )
) { message -> /* handle message */ }
1
2
3
4
5
6
pims.set(api: "pims.sdk.token", 
  parameters: [
  "action": "unregisterPushToken",
  ]
) { (message) in /* handle message */ }
1
2
3
4
5
6
// representation of the `succeeded` dictionary object message as JSON
{
  "transactionId": "953cfefb-bc72",
  "status": "SUCCEEDED",
  "result": null
}

false

3. Select Vehicles & check their status #

Once, the Firebase Token is registered, the mobile device and Stellantis account are linked. We should then inform Stellantis to enable the service for a vehicle(s)/device. To do this, we first need to select vehicles.

Therefore you must use the following API to achieve the following goals:

  • Check the current status of the service on the vehicles (enable/disabled).
  • Select the vehicle(s) to enable/disable the service on, in Step 4.

This API performs both action at the same time: vehicle(s) are selected for step 4 & returns the status of the services currently active.

You must use this information to choose which action you want to perform, if the service is already activated, it doesn’t need to be activated again. Also you can deactivate only services that are already activated.

1
2
3
4
5
6
pims.get("pims.sdk.event",
  mapOf( /* parameters */
  Pair("vins", listOf("VR1AB12C3D4567890", "VR2AB12C3D4567890"))
  )
) { message -> /* handle message */ }
1
2
3
4
5
6
pims.get(api: "pims.sdk.event", 
  parameters: [
  "vins": ["VR1AB12C3D4567890", "VR2AB12C3D4567890"]
  ]
) { (message) in /* handle message */ }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// representation of the `succeeded` dictionary object message as JSON
{
  "transactionId": "953cfefb-bc72",
  "status": "SUCCEEDED",
  "result": {
  "events": [
    { 
      "vin": "VR1AB12C3D4567890",
      "notification": [
        { "name": "remoteChargeFinished",
          "status": "enabled" },
        { "name": "remoteChargeInterrupted",
          "status": "disabled" }
        ]
    },
    { 
      "vin": "VR2AB12C3D4567890",
      "notification": [
        { "name": "remoteChargeFinished",
          "status": "disabled" },
        { "name": "remoteChargeInterrupted",
          "status": "enabled" }
        ]
    },
  ]
}
}

false

The response of this API let you know if these VIN has already subscribed. Also, vehicles requested with this API are selected for Step 4.

4. Enable an event #

In order to activate the PushNotification feature, we should enable at least one service on the vehicle(s). pims.sdk.event-enable API allows enabling services on the vehicles selected in step 3. The following events are available:

  • ✅🔋 remoteChargeFinished
  • ❌🔌 remoteChargeInterrupted

Service status: enabling service on a vehicle should be done according to the current status of the service. Already activated services don’t need to be activated again. Otherwise, we can disable service.

Selecting Vehicle(s): this API effects vehicles selected in the previous step that’s why selecting vehicle(s) is mandatory before using it. Check out step 3 to select & check vehicle(s) status.

1
2
3
4
5
6
7
pims.set("pims.sdk.event",
  mapOf( /* parameters */
  Pair("action", "enable"),
  Pair("type", listOf("remoteChargeFinished", "remoteChargeInterrupted"))
  )
) { message -> /* handle message */ }
1
2
3
4
5
6
7
pims.set(api: "pims.sdk.event", 
  parameters: [
  action": "enable",
  type": ["remoteChargeFinished", "remoteChargeInterrupted"]
  ]
) { (message) in /* handle message */ }
1
2
3
4
5
6
// representation of the `succeeded` dictionary object message as JSON
{
  "transactionId": "953cfefb-bc72",
  "status": "SUCCEEDED",
  "result": null
}

false

If you want to turn off the PushNotification system, use pims.sdk.event-disable.

5. Customize System Notif #

At this step, the PushNotification system should be properly functional on the device. But the notification message needs to be customized to fit your App needs.

Set Up System Notif

By default, the notification title and content are not clear to an end user. These guidance allows to custom the push notification:
Android
iOS

Add a FirebaseMessagineService

Add a class FirebaseMessagineService in your App, check out the official documentation.

Edit the Notification Extension

In the FirebaseMessagineService, create a method onMessageReceived().

Add the following code to the method:

1
2
3
4
5
6
7
val title = resources.getString(
  resources.getIdentifier(
  remoteMessage.data["title"], "string",packageName))

val body = resources.getString(
  resources.getIdentifier(
  remoteMessage.data["body"], "string",packageName))

This will link the title and the content of the notification to the localizable file.

Add localizable file(s)

Add a localizable file strings.xml for every supported language, here is the format of the english version:

1
2
3
4
5
6
7
<string name="remoteChargeFinished.title">Charge notification</string>
<string name="remoteChargeFinished.body">Your vehicle is 100% charged</string>
<string name="remoteChargeFinished.action">Charge notification action</string>

<string name="remoteChargeInterrupted.title">Charge Interrupted</string>
<string name="remoteChargeInterrupted.body">Your vehicle is no longer charging</string>
<string name="remoteChargeInterrupted.action">Charge Interrupted action</string>

Add a UNNotificationServiceExtension

Create a new template and add an iOS Notification Service Extension to your project. Check out the UNNotificationServiceExtension Apple documentation.

Add Notif Service Extension

Edit the Notification Extension

In the file NotificationService.swift, in the first method didReceive() find this line of code:

1
bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"

We should replace it with the following code:

1
2
bestAttemptContent.title = NSLocalizedString(bestAttemptContent.title, comment: "")
bestAttemptContent.body = NSLocalizedString(bestAttemptContent.body, comment: "")

This will link the title and the content of the notification to the localizable file.

Add localizable file(s)

Add a localizable file Localizable.string for every supported language, here is the format of the english version:

1
2
3
4
5
"remoteChargeFinished.title" = "Charge notification";
"remoteChargeFinished.body" = "Your vehicle is 100% charged";

"remoteChargeInterrupted.title" = "Charge Interrupted";
"remoteChargeInterrupted.body" = "Your vehicle is no longer charging";

Disable an event #

On the action of the End User, you should disable event notification by calling the following API:

1
2
3
4
5
6
7
pims.set("pims.sdk.event",
  mapOf( /* parameters */
  Pair("action", "disable"),
  Pair("type", listOf("remoteChargeFinished", "remoteChargeInterrupted"))
  )
) { message -> /* handle message */ }
1
2
3
4
5
6
7
pims.set(api: "pims.sdk.event", 
  parameters: [
  action": "disable",
  type": ["remoteChargeFinished", "remoteChargeInterrupted"]
  ]
) { (message) in /* handle message */ }
1
2
3
4
5
6
// representation of the `succeeded` dictionary object message as JSON
{
  "transactionId": "953cfefb-bc72",
  "status": "SUCCEEDED",
  "result": null
}

false

Remove a vehicle #

On the action of the End User, you should remove a vehicle from the event system:

1
2
3
4
5
6
7
pims.set("pims.sdk.event",
  mapOf( /* parameters */
  Pair("action", "remove"),
  Pair("vin", "VR1AB12C3D4567890")
  )
) { message -> /* handle message */ }
1
2
3
4
5
6
7
pims.set(api: "pims.sdk.event", 
  parameters: [
  action": "remove",
  vin": "VR1AB12C3D4567890"
  ]
) { (message) in /* handle message */ }
1
2
3
4
5
6
// representation of the `succeeded` dictionary object message as JSON
{
  "transactionId": "953cfefb-bc72",
  "status": "SUCCEEDED",
  "result": null
}

false