将Campaign SDK与您的应用程序集成 integrating-campaign-sdk-into-the-mobile-application
要获取Campaign SDK(以前称为Neolane SDK),请联系Adobe客户关怀。
要了解有关支持的其他Android和iOS版本的更多信息,请参阅兼容性矩阵。
您可以在下面找到Campaign SDK的集成步骤。
-
在Android 中: neolane_sdk-release.aar 文件必须链接到项目。
以下权限授予对Adobe Campaign服务器的访问权限:
code language-none Neolane.getInstance().setIntegrationKey("your Adobe mobile app integration key"); Neolane.getInstance().setMarketingHost("https://yourMarketingHost:yourMarketingPort/"); Neolane.getInstance().setTrackingHost("https://yourTrackingHost:yourTrackingPort/");
以下权限允许您恢复移动设备的唯一ID:
code language-none <uses-permission android:name="android.permission.READ_PHONE_STATE" />
从SDK版本1.0.24开始,此权限仅用于Android 6.0之前的版本。
从SDK版本1.0.26开始,不再使用此权限。
-
在iOS 中: libNeolaneSDK.a 和 Neolane_SDK.h 文件必须链接到项目。 从SDK 1.0.24版本开始,激活选项 ENABLE_BITCODE。
note note NOTE 对于SDK版本1.0.25,Neolane_SDK.h 文件中提供了四种体系结构。
要将Campaign SDK集成到移动应用程序,功能管理员必须向开发人员提供以下信息:
-
集成键:用于启用Adobe Campaign平台以识别移动应用程序。
note note NOTE 此集成密钥输入到Adobe Campaign控制台中,该控制台位于专用于移动应用程序的服务的 Information 选项卡中。 请参阅在Adobe Campaign中配置移动应用程序。 -
跟踪URL:与Adobe Campaign跟踪服务器的地址匹配。
-
营销URL:启用订阅集合。
-
在Android 中:
code language-none Neolane.getInstance().setIntegrationKey("your Adobe mobile app integration key"); Neolane.getInstance().setMarketingHost("https://yourMarketingHost:yourMarketingPort/"); Neolane.getInstance().setTrackingHost("https://yourTrackingHost:yourTrackingPort/");
-
在iOS 中:
code language-none Neolane_SDK *nl = [Neolane_SDK getInstance]; [nl setMarketingHost:strMktHost]; [nl setTrackingHost:strTckHost]; [nl setIntegrationKey:strIntegrationKey];
注册功能使您能够:
-
将通知ID或推送ID(iOS的deviceToken和Android的注册ID)发送到Adobe Campaign。
-
恢复协调密钥或userKey(例如,电子邮件或帐号)
-
在Android 中:
code language-none void registerInNeolane(String registrationId, String userKey, Context context) { try{ Neolane.getInstance().registerDevice(registrationToken, userKey, null, context); } catch (NeolaneException e){ //... } catch (IOException e){ //... } }
如果您使用FCM (Firebase Cloud Messaging),我们建议您在调用 onTokenRefresh 函数时使用 registerDevice 函数来通知Adobe Campaign用户的移动设备令牌发生了更改。
code language-none 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) { ... } }); ... ... } }
-
在iOS 中:
code language-none // 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]; }
-
在Android 中:
利用跟踪函数,可跟踪通知激活(打开)和通知显示(屏幕快照)。
要跟踪通知显示(通过调用SDK的 notifyReceive 函数来完成),请遵循以下实施。 请注意,如果您使用FCM (Firebase Cloud Messaging),我们建议您在Android系统调用 onMessageReceived 函数时使用 notifyReceive 函数。
code language-none 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); } }
code language-none 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); } }
以下是跟踪通知打开的实施示例(通过调用SDK的 notifyOpening 函数来执行)。 NotificationActivity 类对应于上一个示例中用于创建 notifIntent 对象的类。
code language-none 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) { // ... } } } } }
-
在iOS 中:
跟踪函数允许您跟踪何时激活通知(打开)。
code language-none (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); }
note note NOTE 从版本7.0开始,一旦实现** application:didReceiveRemoteNotification:fetchCompletionHandler
函数,操作系统将仅调用此函数。 因此,未调用application:didReceiveRemoteNotification
**函数。
iOS允许您发送静默通知、通知或数据,这些信息或数据将直接发送到移动应用程序,而不会显示通知。 Adobe Campaign允许您跟踪他们。
要跟踪静默通知,请按照以下示例操作:
code language-none |
---|
|
note note |
---|
NOTE |
请注意,这仅供iOS使用。 |
在iOS中,委派协议允许您获取 registerDevice 调用的结果,并可用于了解注册过程中是否出现错误。
registerDeviceStatus 原型为:
code language-none |
---|
|
状态 允许您知道注册是否成功或发生错误。
ErrorReason 为您提供有关所发生错误的详细信息。 有关可用错误及其说明的更多信息,请参阅下表。
table 0-row-3 1-row-3 2-row-3 3-row-3 4-row-3 5-row-3 6-row-3 | ||
---|---|---|
状态 | 说明 | ErrorReason |
ACCRegisterDeviceStatusSuccess | 注册成功 | 空 |
ACCRegisterDeviceStatusFailureMarketingServerHostnameEmpty | ACC营销服务器主机名为空或未设置。 | 空 |
ACCRegisterDeviceStatusFailureIntegrationKeyEmpty | 集成键为空或未设置。 | 空 |
ACCRegisterDeviceStatusFailureConnectionIssue | 与ACC 的连接问题 |
更多信息(以操作系统当前语言表示) |
ACCRegisterDeviceStatusFailureUnknownUUID | 提供的UUID(集成密钥)未知。 | 空 |
ACCRegisterDeviceStatusFailureUnexpectedError | 返回到ACC服务器的意外错误。 | 错误消息返回到ACC。 |
Neolane_SDKDelegate 协议和 registerDeviceStatus 委托定义如下:
code language-none |
---|
|
要实施 registerDeviceStatus 委派,请执行以下步骤:
-
在SDK初始化期间实施 setDelegate。
code language-none // 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 ... ... }
-
在类的 @interface 中添加协议。
code language-none // 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; }
-
在 AppDelegate 中实施委托。
code language-none // 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
利用变量,可定义在收到通知后的移动应用程序行为。 必须在移动设备应用程序代码和Adobe Campaign控制台中,在专用移动设备应用程序的 Variables 选项卡中定义这些变量(请参阅在Adobe Campaign中配置移动设备应用程序)。 下面是一个代码示例,该代码允许移动应用程序收集通知中添加的任何变量。 在我们的示例中,我们使用“VAR”变量。
-
在Android 中:
code language-none public void onReceive(Context context, Intent intent) { ... String event = intent.getStringExtra("VAR"); ... }
-
在iOS 中:
code language-none - (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"]; } }
note caution |
---|
CAUTION |
Adobe建议选择短变量名称,因为iOS和Android的通知大小限制为4kB。 |
用于iOS的
介质必须在通知服务扩展级别下载。
code language-none |
---|
|
用于iOS的
在此级别,您需要:
-
将您的内容扩展关联到Adobe Campaign发送的类别:
如果您希望移动设备应用程序显示图像,则可以在Adobe Campaign中将类别值设置为“图像”,并在移动设备应用程序中创建将 UNNotificationExtensionCategory 参数设置为“图像”的通知扩展。 当在设备上收到推送通知时,根据定义的类别值调用扩展。
-
定义通知布局
您需要使用相关构件定义布局。 对于图像,该构件名为 UIImageView。
-
显示您的媒体
您需要添加代码以将媒体数据馈送到构件。 以下是图像的代码示例:
code language-none #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