將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 若是1.0.25版的SDK,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雲端通訊),建議您在呼叫 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 | ||
---|---|---|
狀態 | 說明 | 錯誤原因 |
ACCRegisterDeviceStatusSuccess | 註冊成功 | 空白 |
ACCRegisterDeviceStatusFailureMarketingServerHostnameEmpty | ACC行銷伺服器主機名稱是空的或未設定。 | 空白 |
ACCRegisterDeviceStatusFailureIntegrationKeyEmpty | 整合金鑰為空白或未設定。 | 空白 |
ACCRegisterDeviceStatusFailureConnectionIssue | ACC 的連線問題 |
詳細資訊(目前的OS語言) |
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中將類別值設為"image",並在行動應用程式中,使用 UNNotificationExtensionCategory 引數設定為"image"來建立通知擴充功能。 在裝置上收到推播通知時,會根據定義的類別值呼叫擴充功能。
-
定義您的通知配置
您必須使用相關Widget來定義版面。 對於影像,Widget的名稱為 UIImageView。
-
顯示您的媒體
您需要新增程式碼,以將媒體資料摘要至Widget。 以下是影像的程式碼範例:
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