适用于iOS和Android的活动SDK是移动应用程序渠道模块的组件之一。
要获取活动SDK(以前称为Neolane SDK),请与Adobe客户服务联系。
SDK的目标是促进将移动应用程序集成到Adobe Campaign平台。
要进一步了解支持的不同Android和iOS版本,请参阅兼容性矩阵。
在Android中:neolane _sdk-release.aar 文件必须链接到项目。
以下权限授予对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. h文件链接到项目。从SDK的1.0.24版中,选项ENABLE_BITCODE被激活。
对于SDK版本1.0.25,Neolane_SDK.h文件中提供了这四种架构。
要将活动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用户移动设备令牌的更改。
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 Messaging),我们建议您在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;
“ 状态”允许您了解注册是否成功或是否出错。
ErrorReason 为您提供有关所发生错误的详细信息。有关可用错误及其说明的详细信息,请参阅下表。
状态 |
说明 |
ErrorReason |
---|---|---|
ACCRegisterDeviceStatusSuccess |
注册成功 |
空 |
ACCRegisterDeviceStatusFailureMarketingServerHostnameEmpty |
ACC营销服务器主机名为空或未设置。 |
空 |
ACCRegisterDeviceStatusFailureIntegrationKeyEmpty |
集成密钥为空或未设置。 |
空 |
ACCRegisterDeviceStatusFailureConnectionIssue |
ACC 的连接问题 |
更多信息(使用操作系统当前语言) |
ACCRegisterDeviceStatusFailureUnknownUUID |
提供的UUID(集成密钥)未知。 |
空 |
ACCRegisterDeviceStatusFailureUnexpectedError |
ACC服务器返回意外错误。 |
返回到ACC的错误消息 |
Neolane_SDKelegate 协议和 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”,创建通知扩展。 在设备上接收推送通知时,将根据定义的类别值调用扩展。
定义通知布局
您需要使用相关构件定义布局。 对于图像,该构件名为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