SDK Features - Push Notification
Security: Push Notification require the following security schemes to be valid
- 🔓 Authentication
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.
- Step 6: Log received notifications.
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
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
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.
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";
6. Log received Notifications #
When a notification is recieved on the user device you must call the following API. It will be used for Stellantis internal logs.
Depending on the operating system you should pass this dictionnary as the payload parameter:
- iOS:
bestAttemptContent.userInfo
. - Android:
remoteMessage.data
.
1
2
3
4
5
6
pims.set("pims.sdk.notification",
mapOf( /* parameters */
Pair("payload", remoteMessage.data)
)
) { message -> /* handle message */ }
1
2
3
4
5
6
pims.set(api: "pims.sdk.notification",
parameters: [
"payload": bestAttemptContent.userInfo
]
) { (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
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