Campaign SDK とアプリの統合 integrating-campaign-sdk-into-the-mobile-application

CAUTION
アドビでは、データ収集 UI で Adobe Campaign 拡張機能を設定して、Adobe Experience Platform Mobile SDK を使用することを強くお勧めします。Adobe Experience Platform Mobile SDK は、モバイルアプリでアドビの Experience Cloud のソリューションとサービスを強化するのに役立ちます。SDK の設定はデータ収集 UI を通じて管理され、柔軟な設定と拡張可能なルールベースの統合を実現します。詳しくは、Adobe Developer のドキュメントを参照してください。

Campaign SDK(旧 Neolane SDK)を入手するには、アドビカスタマーケアにお問い合わせください。

サポートされている様々な Android および iOS バージョンについて詳しくは、互換性マトリックスを参照してください。

Campaign SDK の統合手順を以下に示します。

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 ファイルに 4 つのアーキテクチャがあります。
統合設定の宣言

Campaign SDK をモバイルアプリケーションに統合するには、担当の管理者がデベロッパーに次の情報を提供する必要があります。

  • 統合キー:Adobe Campaign プラットフォームでモバイルアプリケーションを特定できるようにします。

    note note
    NOTE
    この統合キーは、Adobe Campaign コンソールのモバイルアプリケーション専用サービスの「情報」タブに入力されます。詳しくは、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 の registrationID)を 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 関数を呼び出して Adobe Campaign にユーザーのモバイルデバイストークンの変更を通知するときに、registerDevice 関数を使用することをお勧めします。

    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
// 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);
}
RegisterDeviceStatus デリゲート
note note
NOTE
これは iOS 専用です。

iOS では、このデリゲートプロトコルを使用すると、registerDevice 呼び出しの結果を取得でき、登録時にエラーが発生したかどうかを把握できます。

registerDeviceStatus のプロトタイプは次のとおりです。

code language-none
- (void) registerDeviceStatus: (ACCRegisterDeviceStatus) status:(NSString *) errorReason;

status を使用すると、登録が成功したかどうかやエラーが発生したかどうかを把握できます。

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 との接続の問題 (OS の現在の言語での)詳細情報
ACCRegisterDeviceStatusFailureUnknownUUID 指定された UUID(統合キー)が不明です。
ACCRegisterDeviceStatusFailureUnexpectedError 予期しないエラーが ACC サーバーに返されました。 エラーメッセージが ACC に返されました。

Neolane_SDKDelegate プロトコルと registerDeviceStatus デリゲートの定義は次のとおりです。

code language-none
//  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 デリゲートを実装するには、以下の手順を実行します。

  1. 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
    ...
    ...
    }
    
  2. クラスの @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;
    }
    
  3. 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 コンソールのモバイルアプリケーション専用の「変数」タブで定義する必要があります(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
iOS と Android では通知のサイズが 4 KB に制限されているので、短い変数名を選択することをお勧めします。
通知サービス拡張

iOS の場合

メディアは通知サービス拡張レベルでダウンロードする必要があります。

code language-none
#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 とモバイルアプリケーションでカテゴリの値を「画像」に設定し、通知拡張を作成して 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
    
recommendation-more-help
601d79c3-e613-4db3-889a-ae959cd9e3e1