iOS和Android適用的促銷活動SDK是行動應用程式頻道模組的元件之一。
若要取得Campaign SDK(先前稱為Neolane SDK),請聯絡Adobe客戶服務。
SDK的目標是協助將行動應用程式整合至Adobe Campaign平台。
若要進一步瞭解支援的不同Android和iOS版本,請參閱相容性表。
在Android中:neolane_sdk-release. aarfile必須連結至專案。
下列權限授與Adobe Campaign伺服器的存取權:
Neolane.getInstance().setIntegrationKey("your Adobe mobile app integration key");
Neolane.getInstance().setMarketingHost("https://yourMarketingHost:yourMarketingPort/");
Neolane.getInstance().setTrackingHost("https://yourTrackingHost:yourTrackingPort/");
以下權限允許您恢復電話的唯一ID:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
在SDK 1.0.24版中,此權限僅用於Android 6.0之前的版本。
從SDK 1.0.26版,將不再使用此權限。
在iOS中:libNeolaneSDK. 和 Neolane_SDK. hfiles必須連結至專案。從SDK 1.0.24版啟用ENABLE_BITCODE選項。
對於SDK 1.0.25版,這4種架構皆可在Neolane_SDK.h檔案中取得。
若要將Campaign SDK整合至行動應用程式,功能管理員必須向開發人員提供下列資訊:
整合金鑰:以啟用Adobe Campaign平台來識別行動應用程式。
此整合金鑰是在Adobe Campaign主控台的行動應用程式專用服務的Information標籤中輸入。 請參閱在Adobe Campaign中設定行動應用程式。
追蹤URL:符合Adobe Campaign追蹤伺服器位址的連結。
行銷URL:以啟用訂閱的集合。
在Android中:
Neolane.getInstance().setIntegrationKey("your Adobe mobile app integration key");
Neolane.getInstance().setMarketingHost("https://yourMarketingHost:yourMarketingPort/");
Neolane.getInstance().setTrackingHost("https://yourTrackingHost:yourTrackingPort/");
在iOS中:
Neolane_SDK *nl = [Neolane_SDK getInstance];
[nl setMarketingHost:strMktHost];
[nl setTrackingHost:strTckHost];
[nl setIntegrationKey:strIntegrationKey];
註冊功能使您能夠:
傳送通知ID或推播ID(iOS的deviceToken和Android的registrationID)至Adobe Campaign。
恢復協調密鑰或userKey(例如,電子郵件或帳號)
在Android中:
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使用者行動裝置Token的變更。
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中:
// 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傳訊),當Android系統呼叫onMessageReceived函式時,我們建議您使用notifyReceive函式。
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);
}
}
以下是追蹤開啟通知的實作範例(透過呼叫SDK的notifyOpening函式來執行)。 NotificationActivity類與上例中用於建立notifIntent對象的類相對應。
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中:
追蹤功能可讓您在啟動(開啟)通知時追蹤。
(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);
}
在7.0版中,一旦實作application:didReceiveRemoteNotification:fetchCompletionHandler函式,作業系統就只會呼叫此函式。 因此不會呼叫application:didReceiveRemoteNotification函式。
iOS可讓您傳送無訊息通知、通知或資料,這些通知或資料將直接傳送至行動應用程式,而不會顯示。 Adobe Campaign可讓您追蹤他們。
若要追蹤您的無訊息通知,請遵循下列範例:
// 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);
}
請注意,這是iOS專屬的。
在iOS中,委派通訊協定可讓您取得registerDevice呼叫的結果,並可用來知道註冊期間是否發生錯誤。
registerDeviceStatus原型為:
- (void) registerDeviceStatus: (ACCRegisterDeviceStatus) status:(NSString *) errorReason;
Status 可讓您知道註冊是否成功或發生錯誤。
ErrorReason 提供您有關所發生錯誤的詳細資訊。有關可用錯誤及其說明的詳細資訊,請參閱下表。
狀態 |
說明 |
ErrorReason |
---|---|---|
ACCRegisterDeviceStatusSuccess |
註冊成功 |
EMPTY |
ACCRegisterDeviceStatusFailureMarketingServerHostnameEmpty |
ACC行銷伺服器主機名稱是空的或未設定。 |
EMPTY |
ACCRegisterDeviceStatusFailureIntegrationKeyEmpty |
整合金鑰為空或未設定。 |
EMPTY |
ACCRegisterDeviceStatusFailureConnectionIssue |
ACC 的連線問題 |
詳細資訊(使用作業系統目前語言) |
ACCRegisterDeviceStatusFailureUnknownUUID |
提供的UUID(整合鍵)未知。 |
EMPTY |
ACCRegisterDeviceStatusFailureUnexpectedError |
ACC伺服器返回非預期錯誤。 |
錯誤訊息傳回至ACC。 |
Neolane_ SDKDelegateprotocol and registerDeviceStatusdelegate定義如下:
// 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
若要實作registerDeviceStatus委派,請依照下列步驟進行:
在SDK初始化期間實作setDelegate。
// 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中添加協定。
// 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中實作委派。
// 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中:
public void onReceive(Context context, Intent intent) {
...
String event = intent.getStringExtra("VAR");
...
}
在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建議選擇簡短的變數名稱,因為iOS和Android的通知大小限制為4kB。
適用於iOS
必須在通知服務擴展級別下載介質。
#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
適用於iOS
在此層級,您需要:
將您的內容擴充功能與Adobe Campaign所傳送的類別建立關聯:
如果您想要行動應用程式顯示影像,您可以在Adobe Campaign中將類別值設為"image",在行動應用程式中,您會以UNNotificationExtensionCategory參數設為"image"來建立通知副檔名。 當在裝置上收到推播通知時,會根據所定義的類別值呼叫擴充功能。
定義您的通知配置
您需要使用相關Widget來定義版面。 對於影像,該構件名為UIImageView。
顯示您的媒體
您需要新增程式碼,將媒體資料饋送至介面工具集。 以下是影像的程式碼範例:
#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