Adobe recommande vivement d’utiliser le SDK mobile Adobe Experience Platform en configurant l’extension Adobe Campaign dans l’interface utilisateur de collecte de données. Le SDK mobile Adobe Experience Platform permet d’optimiser les solutions et services Experience Cloud d’Adobe dans vos applications mobiles. La configuration des SDK s’effectue dans l’interface utilisateur de collecte de données, qui offre des options de configuration flexibles et des intégrations extensibles basées sur des règles. En savoir plus dans la documentation Adobe Developer.
Pour obtenir le SDK Campaign (anciennement connu sous le nom de SDK Neolane), contactez l’Assistance clientèle d’Adobe.
Pour plus d’informations sur les différentes versions Android et iOS prises en charge, consultez la matrice de compatibilité.
Vous trouverez ci-dessous la procédure pour intégrer le SDK Campaign.
Sous Android : le fichier neolane_sdk-release.aar doit être lié au projet.
L’autorisation suivante permet l'accès au serveur Adobe Campaign :
Neolane.getInstance().setIntegrationKey("your Adobe mobile app integration key");
Neolane.getInstance().setMarketingHost("https://yourMarketingHost:yourMarketingPort/");
Neolane.getInstance().setTrackingHost("https://yourTrackingHost:yourTrackingPort/");
La permisson suivante permet de récupérer un identifiant unique par téléphone :
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
A partir de la version 1.0.24 du SDK, cette autorisation est uniquement utilisée pour les versions antérieures à Android 6.0.
A partir de la version 1.0.26 du SDK, cette autorisation n'est plus utilisée.
Sous iOS : les fichiers libNeolaneSDK.a et Neolane_SDK.h doivent être liés au projet. A partir de la version 1.0.24 du SDK, l'option ENABLE_BITCODE est activée.
Pour la version 1.0.25 du SDK, les quatre architectures sont disponibles dans le fichier Neolane_SDK.h.
Afin d'intégrer le SDK Campaign dans l'application mobile, l'administrateur fonctionnel doit fournir au développeur les informations suivantes :
Une clé d'intégration permettant à la plateforme Adobe Campaign d'identifier l'application mobile.
Cette clé d'intégration est renseignée dans la console Adobe Campaign, dans l'onglet Informations du service dédié à l'application mobile. Pour plus d'informations, consultez la section Paramétrage de l’application mobile dans Adobe Campaign.
Une URL de tracking correspondant à l'adresse du serveur de tracking Adobe Campaign.
Une URL marketing permettant de collecter les abonnements.
Sous Android :
Neolane.getInstance().setIntegrationKey("your Adobe mobile app integration key");
Neolane.getInstance().setMarketingHost("https://yourMarketingHost:yourMarketingPort/");
Neolane.getInstance().setTrackingHost("https://yourTrackingHost:yourTrackingPort/");
Sous iOS :
Neolane_SDK *nl = [Neolane_SDK getInstance];
[nl setMarketingHost:strMktHost];
[nl setTrackingHost:strTckHost];
[nl setIntegrationKey:strIntegrationKey];
La fonction d'enregistrement permet :
d'envoyer l'identifiant de notification ou push id (deviceToken pour iOS et registrationID pour Android) à Adobe Campaign.
de récupérer la clé de réconciliation ou userKey (par exemple l'adresse email ou le numéro de compte)
Sous Android :
void registerInNeolane(String registrationId, String userKey, Context context)
{
try{
Neolane.getInstance().registerDevice(registrationToken, userKey, null, context);
} catch (NeolaneException e){
//...
} catch (IOException e){
//...
}
}
Si vous utilisez FCM (Firebase Cloud Messaging), nous vous conseillons d'utiliser la fonction registerDevice lors de l'appel de la fonction onTokenRefresh pour notifier Adobe Campaign du changement de token de l'appareil mobile de l'utilisateur.
public class NeoTripFirebaseInstanceIDService extends FirebaseInstanceIdService {
@Override
public void onTokenRefresh() {
String registrationToken = FirebaseInstanceId.getInstance().getToken();
NeolaneAsyncRunner neolaneAs = new NeolaneAsyncRunner(Neolane.getInstance());
...
...
// Neolane Registration
neolaneAs.registerDevice(registrationToken, userKey, additionnalParam, this, new NeolaneAsyncRunner.RequestListener() {
public void onComplete(String e, Object state) { ... }
public void onNeolaneException(NeolaneException e, Object state) { ... }
public void onIOException(IOException e, Object state) { ... }
});
...
...
}
}
Sous iOS :
// Callback called on successful registration to the APNs
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
// Pass the token to Adobe Campaign
Neolane_SDK *nl = [Neolane_SDK getInstance];
[nl registerDevice:tokenString:self.userKey:dic];
}
Sous Android :
Les fonctions de tracking permettent de tracker l'affichage de la notification (impression sur écran) et l'activation des notifications (ouvertures).
Pour tracker l'affichage d'une notification (réalisé via l'appel de la fonction notifyReceive du SDK),suivez l'implémentation ci-après. Si vous utilisez FCM (Firebase Cloud Messaging), nous vous conseillons d'utiliser la fonction notifyReceive lors de l'appel de la fonction onMessageReceived par le système Android.
package com.android.YourApplication;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class YourApplicationFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
@Override
public void onMessageReceived(RemoteMessage message) {
Log.d(TAG, "Receive message from: " + message.getFrom());
Map<String,String> payloadData = message.getData();
final Bundle extras = new Bundle();
final Iterator<Entry<String, String>> iter = payloadData.entrySet().iterator();
while(iter.hasNext())
{
final Entry<String, String> entry =iter.next();
extras.putString(entry.getKey(), entry.getValue());
}
SharedPreferences settings = this.getSharedPreferences(YourApplicationActivity.APPLICATION_PREF_NAME, Context.MODE_PRIVATE);
String mesg = payloadData.get("_msg");
String title = payloadData.get("title");
String url = payloadData.get("url");
String messageId = payloadData.get("_mId");
String deliveryId = payloadData.get("_dId");
YourApplicationActivity.handleNotification(this, mesg, title, url, messageId, deliveryId, extras);
}
}
public static void handleNotification(Context context, String message, String title, String url, String messageId, String deliveryId, Bundle extras){
if( message == null ) message = "No Content";
if( title == null ) title = "No title";
if( url == null ) url = "https://www.tripadvisor.fr";
int iconId = R.drawable.notif_neotrip;
// notify Neolane that a notification just arrived
SharedPreferences settings = context.getSharedPreferences(NeoTripActivity.APPLICATION_PREF_NAME, Context.MODE_PRIVATE);
Neolane.getInstance().setIntegrationKey(settings.getString(NeoTripActivity.APPUUID_NAME, NeoTripActivity.DFT_APPUUID));
Neolane.getInstance().setMarketingHost(settings.getString(NeoTripActivity.SOAPRT_NAME, NeoTripActivity.DFT_SOAPRT));
Neolane.getInstance().setTrackingHost(settings.getString(NeoTripActivity.TRACKRT_NAME, NeoTripActivity.DFT_TRACKRT));
NeolaneAsyncRunner nas = new NeolaneAsyncRunner(Neolane.getInstance());
nas.notifyReceive(Integer.valueOf(messageId), deliveryId, new NeolaneAsyncRunner.RequestListener() {
public void onNeolaneException(NeolaneException arg0, Object arg1) {}
public void onIOException(IOException arg0, Object arg1) {}
public void onComplete(String arg0, Object arg1){}
});
if (yourApplication.isActivityVisible())
{
Log.i("INFO", "The application has the focus" );
...
}
else
{
// notification creation :
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification;
// Activity to start :
Intent notifIntent = new Intent(context.getApplicationContext(), NotificationActivity.class);
notifIntent.putExtra("notificationText", message);
notifIntent.putExtra(NotificationActivity.NOTIFICATION_URL_KEYNAME, url);
notifIntent.putExtra("_dId", deliveryId);
notifIntent.putExtra("_mId", messageId);
notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(context, 1, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notification = new Notification.Builder(context)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(iconId)
.setContentIntent(contentIntent)
.build();
// launch the notification :
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(Integer.valueOf(messageId), notification);
}
}
Voici un exemple d'implémentation pour le tracking de l'ouverture d'une notification (réalisé via l'appel de la fonction notifyOpening du SDK). La classe NotificationActivity correspond à celle utilisée pour créer l'objet notifIntent dans l'exemple précédent.
public class NotificationActivity extends Activity {
public void onCreate(Bundle savedBundle) {
[...]
Bundle extra = getIntent().getExtras();
if (extra != null) {
// reinit the acc sdk
SharedPreferences settings = getSharedPreferences(NeoTripActivity.APPLICATION_PREF_NAME, Context.MODE_PRIVATE);
Neolane.getInstance().setIntegrationKey(settings.getString(NeoTripActivity.APPUUID_NAME, NeoTripActivity.DFT_APPUUID));
Neolane.getInstance().setMarketingHost(settings.getString(NeoTripActivity.SOAPRT_NAME, NeoTripActivity.DFT_SOAPRT));
Neolane.getInstance().setTrackingHost(settings.getString(NeoTripActivity.TRACKRT_NAME, NeoTripActivity.DFT_TRACKRT));
// Get the messageId and the deliveryId to do the tracking
String deliveryId = extra.getString("_dId");
String messageId = extra.getString("_mId");
if (deliveryId != null && messageId != null) {
try {
Neolane.getInstance().notifyOpening(Integer.valueOf(messageId), Integer.valueOf(deliveryId));
} catch (NeolaneException e) {
// ...
} catch (IOException e) {
// ...
}
}
}
}
}
Sous iOS :
La fonction de tracking permet de tracker l'activation des notifications (ouvertures).
(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)launchOptions
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
if( launchOptions ) { // Retrieve notification parameters here ... // Track application opening Neolane_SDK
*nl = [Neolane_SDK getInstance]; [nl track:launchOptions:NL_TRACK_CLICK]; }
...
completionHandler(UIBackgroundFetchResultNoData);
}
À partir de la version 7.0, une fois la fonction application:didReceiveRemoteNotification:fetchCompletionHandler mise en œuvre, le système d'exploitation appelle uniquement cette fonction. La fonction application:didReceiveRemoteNotification n'est donc pas appelée.
iOS permet d'envoyer des notifications silencieuses, des notifications ou des données qui seront directement envoyées à une application mobile sans les afficher. Adobe Campaign vous permet de les tracker.
Pour suivre votre notification silencieuse, suivez l'exemple ci-après.
// AppDelegate.m
...
...
#import "AppDelegate.h"
#import "Neolane_SDK.h"
...
...
// Callback called when the application is already launched (whether the application is running foreground or background)
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)launchOptions fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
NSLog(@"IN didReceiveRemoteNotification:fetchCompletionHandler");
if (launchOptions) NSLog(@"IN launchOptions: %@", [launchOptions description]);
NSLog(@"Application state: %ld", (long)application.applicationState);
// Silent Notification (specific case, can use NL_TRACK_RECEIVE as the user doesn't have click/open the notification)
if ([launchOptions[@"aps"][@"content-available"] intValue] == 1 )
{
NSLog(@"Silent Push Notification");
...
...
//Call receive tracking
Neolane_SDK *nl = [Neolane_SDK getInstance];
[nl track:launchOptions:NL_TRACK_RECEIVE];
completionHandler(UIBackgroundFetchResultNoData); //Do not show notification
return;
}
...
...
completionHandler(UIBackgroundFetchResultNoData);
}
Cela s'applique exclusivement à iOS.
Sous iOS, le protocole délégué vous permet d’obtenir le résultat de l’appel de registerDevice et peut être utilisé pour déterminer si une erreur s’est produite pendant l’enregistrement.
Le prototype de registerDeviceStatus est le suivant :
- (void) registerDeviceStatus: (ACCRegisterDeviceStatus) status:(NSString *) errorReason;
Le Statut vous permet de déterminer si un enregistrement a été effectué avec succès ou si une erreur s’est produite.
ErrorReason fournit des informations supplémentaires sur les erreurs qui se sont produites. Pour en savoir plus sur les erreurs disponibles et leur description, reportez-vous au tableau ci-dessous.
Status |
Description |
ErrorReason |
---|---|---|
ACCRegisterDeviceStatusSuccess |
Succès de l'enregistrement |
EMPTY |
ACCRegisterDeviceStatusFailureMarketingServerHostnameEmpty |
Le nom d'hôte du serveur marketing ACC est vide ou non défini. |
EMPTY |
ACCRegisterDeviceStatusFailureIntegrationKeyEmpty |
La clé d'intégration est vide ou non définie. |
EMPTY |
ACCRegisterDeviceStatusFailureConnectionIssue |
Problème de connexion lié à ACC |
Informations supplémentaires (dans la langue actuelle du système d'exploitation) |
ACCRegisterDeviceStatusFailureUnknownUUID |
L'UUID indiqué (clé d'intégration) est inconnu. |
EMPTY |
ACCRegisterDeviceStatusFailureUnexpectedError |
Une erreur inattendue a été retournée au serveur ACC. |
Message d'erreur retourné à ACC. |
Le protocole Neolane_SDKDelegate et la définition du délégué registerDeviceStatus sont les suivants :
// Neolane_SDK.h
// Neolane SDK
..
..
// Register Device Status Enum
typedef NS_ENUM(NSUInteger, ACCRegisterDeviceStatus) {
ACCRegisterDeviceStatusSuccess, // Resistration Succeed
ACCRegisterDeviceStatusFailureMarketingServerHostnameEmpty, // The ACC marketing server hostname is Empty or not set
ACCRegisterDeviceStatusFailureIntegrationKeyEmpty, // The integration key is empty or not set
ACCRegisterDeviceStatusFailureConnectionIssue, // Connection issue with ACC, more information in errorReason
ACCRegisterDeviceStatusFailureUnknownUUID, // The provided UUID (integration key) is unknown
ACCRegisterDeviceStatusFailureUnexpectedError // Unexpected error returned by ACC server, more information in errorReason
};
// define the protocol for the registerDeviceStatus delegate
@protocol Neolane_SDKDelegate <NSObject>
@optional
- (void) registerDeviceStatus: (ACCRegisterDeviceStatus) status :(NSString *) errorReason;
@end
@interface Neolane_SDK: NSObject {
}
...
...
// registerDeviceStatus delegate
@property (nonatomic, weak) id <Neolane_SDKDelegate> delegate;
...
...
@end
Pour implémenter le délégué registerDeviceStatus, procédez comme suit :
Implémentez setDelegate pendant l'initialisation du SDK.
// AppDelegate.m
...
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
...
// Get the stored settings
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *strMktHost = [defaults objectForKey:@"mktHost"];
NSString *strTckHost = [defaults objectForKey:@"tckHost"];
NSString *strIntegrationKey = [defaults objectForKey:@"integrationKey"];
userKey = [defaults objectForKey:@"userKey"];
// Configure Neolane SDK on first launch
Neolane_SDK *nl = [Neolane_SDK getInstance];
[nl setMarketingHost:strMktHost];
[nl setTrackingHost:strTckHost];
[nl setIntegrationKey:strIntegrationKey];
[nl setDelegate:self]; // HERE
...
...
}
Ajoutez le protocole à l'@interface de votre classe.
// AppDelegate.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import "Neolane_SDK.h"
@class LandingPageViewController;
@interface AppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate, Neolane_SDKDelegate> {
CLLocationManager *locationManager;
NSString *userKey;
NSString *mktServerUrl;
NSString *tckServerUrl;
NSString *homeURL;
NSString *strLandingPageUrl;
NSTimer *timer;
}
Implémentez le délégué dans AppDelegate.
// AppDelegate.m
#import "AppDelegate.h"
#import "Neolane_SDK.h"
#import "LandingPageViewController.h"
#import "RootViewController.h"
...
...
- (void) registerDeviceStatus: (ACCRegisterDeviceStatus) status :(NSString *) errorReason
{
NSLog(@"registerStatus: %lu",status);
if ( errorReason != nil )
NSLog(@"errorReason: %@",errorReason);
if( status == ACCRegisterDeviceStatusSuccess )
{
// Registration successful
...
...
}
else { // An error occurred
NSString *message;
switch ( status ){
case ACCRegisterDeviceStatusFailureUnknownUUID:
message = @"Unkown IntegrationKey (UUID)";
break;
case ACCRegisterDeviceStatusFailureMarketingServerHostnameEmpty:
message = @"Marketing URL not set or Empty";
break;
case ACCRegisterDeviceStatusFailureIntegrationKeyEmpty:
message = @"Integration Key not set or empty";
break;
case ACCRegisterDeviceStatusFailureConnectionIssue:
message = [NSString stringWithFormat:@"%@ %@",@"Connection issue:",errorReason];
break;
case ACCRegisterDeviceStatusFailureUnexpectedError:
default:
message = [NSString stringWithFormat:@"%@ %@",@"Unexpected Error",errorReason];
break;
}
...
...
}
}
@end
Les variables vous permettent de définir le comportement de l'application mobile après réception d'une notification. Ces variables doivent être définies dans le code de l'application mobile et dans la console Adobe Campaign, dans l'onglet Variables du service d'applications mobiles dédié (voir la section Paramétrage de l'application mobile dans Adobe Campaign). Voici un exemple de code qui permet à une application mobile de collecter toutes les variables ajoutées dans une notification. Dans notre exemple, nous utilisons la variable "VAR".
Sous Android :
public void onReceive(Context context, Intent intent) {
...
String event = intent.getStringExtra("VAR");
...
}
Sous iOS :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
....
if( launchOptions )
{
// When application is not already launched, the notification data if any are stored in the key 'UIApplicationLaunchOptionsRemoteNotificationKey'
NSDictionary *localLaunchOptions = [launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"];
if( localLaunchOptions )
{
...
[localLaunchOptions objectForKey:@"VAR"];
...
}
}
}
// Callback called when the application is already launched (whether the application is running foreground or background)
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)launchOptions
{
if( launchOptions )
{
...
[launchOptions objectForKey:@"VAR"];
}
}
Adobe recommande de choisir des noms de variables courts car la taille des notifications est limitée : 4 ko pour iOS et Android.
Pour iOS
Le média doit être téléchargé au niveau de l'extension du service de notification.
#import "NotificationService.h"
@interface NotificationService ()
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@end
@implementation NotificationService
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
NSDictionary *userInfo = nil;
NSString *url = nil;
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
userInfo = request.content.userInfo;
if ( userInfo != nil )
{
url = userInfo[@"mediaUrl"]; // Get the url of the media to download (Adobe Campaign additional variable)
}
...
// Perform the download to local storage
Pour iOS
A ce niveau, vous devez effectuer les opérations suivantes :
Associer votre extension de contenu à la catégorie envoyée par Adobe Campaign :
Si vous souhaitez que l'application mobile affiche une image, définissez la valeur de la catégorie dans Adobe Campaign, par exemple "image". Dans l'application mobile, vous créez une extension de notification avec le paramètre UNNotificationExtensionCategory ayant pour valeur "image". Lorsque la notification push est reçue sur l'appareil, l'extension est appelée selon la valeur de la catégorie définie.
Définir la mise en page de la notification
Vous devez définir une mise en page avec les widgets adéquats. Pour une image, c'est le widget UIImageView.
Afficher le contenu multimédia
Vous devez ajouter du code pour alimenter le widget avec les données multimédia. Voici un exemple de code pour une image :
#import "NotificationViewController.h"
#import <UserNotifications/UserNotifications.h>
#import <UserNotificationsUI/UserNotificationsUI.h>
@interface NotificationViewController () <UNNotificationContentExtension>
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@property (strong, nonatomic) IBOutlet UILabel *notifContent;
@property (strong, nonatomic) IBOutlet UILabel *label;
@end
@implementation NotificationViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any required interface initialization here.
}
- (void)didReceiveNotification:(UNNotification *)notification {
self.label.text = notification.request.content.title;
self.notifContent.text = notification.request.content.body;
UNNotificationAttachment *attachment = [notification.request.content.attachments objectAtIndex:0];
if ([attachment.URL startAccessingSecurityScopedResource])
{
NSData * imageData = [[NSData alloc] initWithContentsOfURL:attachment.URL];
self.imageView.image =[UIImage imageWithData: imageData];
[attachment.URL stopAccessingSecurityScopedResource];
}
}
@end