7 実装
ここでは、FANSHIP SDK の標準的な組み込み方法をご説明します。
具体的なファイル名やクラス名が登場する箇所については、実際に組み込むAppの構造などに応じて、適宜読み替えてください。
説明の途中で登場するソースコードについては、SampleAppプロジェクト内のAppDelegate.h および .m にて詳細をご確認いただけます。
SDK が提供するクラス、メソッド、プロパティの詳細については、document フォルダ内の html をご参照ください。
7.1 初期設定
最初の手順として、 PopinfoConfiguration.m において、値の設定が必要です。
popinfoApplicationID に対して、アプリケーション ID 文字列 を代入してください。
アプリケーション ID 文字列は、 FANSHIP 配信管理画面 からご確認ください。
位置情報などを利用する場合は、他の定数も変更する必要があります。
詳細は「9. 実装に関する特記事項」にて説明します。
7.2 ライフサイクルイベント
このセクションでは、AppDelegate 上において必要な実装について説明します。
Xcode 11 以降で利用できる SceneDelegate において実装する場合は、一部のメソッドを UIWindowSceneDelegate プロトコルに実装されているものに読み替える必要があります。
なお、本バージョンのSDKにおいては、 SceneDelegate を用いる App 上の組み込みに関して、各種検証等が十分行えていないことから、サポート対象外とさせていただきます。
UserNotifications フレームワークと PopinfoReceiver を import し、PopinfoReceiver クラスのインスタンスとプロトコルの宣言をしてください。
#import <UserNotifications/UserNotifications.h>
#import "PopinfoReceiver.h"
@interface AppDelegate : NSObject <UIApplicationDelegate, UNUserNotificationCenterDelegate, PopinfoReceiverDelegate> {
PopinfoReceiver *popinfoReceiver;
}
import UserNotifications
import PopinfoReceiver
@UIApplicationMain
class AppDelegate: UIApplicationDelegate, UNUserNotificationCenterDelegate, PopinfoReceiverDelegate {
var popinfoReceiver: PopinfoReceiver?
// 以下省略
}
Swift コード上で import エラーが発生する場合は、本ドキュメントの 5.3 Swift プロジェクト向けセットアップ における設定をご確認ください。
application:didFinishLaunchingWithOptions: 内で、PopinfoReceiver クラスのインスタンスを生成するため、以下のように記述を行ってください。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
popinfoReceiver = [PopinfoReceiver sharedReceiver];
popinfoReceiver.delegate = self;
// ...省略...
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
self.popinfoReceiver = PopinfoReceiver.shared
self.popinfoReceiver.delegate = self
// ...省略...
}
applicationDidBecomeActive: 内で、以下の記述を行ってください。
updateMessages: メソッドの引数のブロック内の記述については、SampleApp プロジェクト AppDelegate.m をご参照ください。
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[popinfoReceiver loadSettings];
[popinfoReceiver updateMessages:^(BOOL isOk, NSString *errorCode, NSArray *newMessages) {
// プッシュ通知受信後、Appアイコンをタップした際に、お知らせ詳細画面への遷移するような処理を記述します。
// SampleApp プロジェクト `AppDelegate.m` を参考に記述してください。
}];
}
func applicationDidBecomeActive(_ application: UIApplication) {
self.popinfoReceiver.loadSettings()
self.popinfoReceiver.updateMessages{ (isOK, errorCode, newMessages) in
// プッシュ通知受信後、Appアイコンをタップした際に、お知らせ詳細画面への遷移するような処理を記述します。
// SampleSwiftApp プロジェクト `AppDelegate.swift` を参考に記述してください。
}
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)dataToken
{
[popinfoReceiver registerToken:dataToken];
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
self.popinfoReceiver.registerToken(deviceToken)
}
UNUserNotificationCenterDelegate メソッドを以下のように記述し、その中に FANSHIP の処理を記述してください。
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler
UNNotificationTrigger *trigger = response.notification.request.trigger;
if ([trigger isMemberOfClass:[UNPushNotificationTrigger class]]) {
UNNotificationContent *content = response.notification.request.content;
[popinfoReceiver receiveNotification:content.userInfo];
}
completionHandler();
}
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let trigger = response.notification.request.trigger
if trigger is UNPushNotificationTrigger {
let content = response.notification.request.content
self.popinfoReceiver.receiveNotification(content.userInfo)
}
completionHandler();
}
なお、引数 payload からキー名 has_detail で整数値を取得できますが、この値は 受け取ったプッシュ通知の配信タイプ を表しています。
has_detail の値 |
受け取ったプッシュ通知の配信タイプ |
|---|---|
| 0 | Push通知のみ |
| 1 | Push通知&コンテンツ配信 |
コンテンツ配信やプッシュのみ配信を使い分ける場合は、 has_detail を用いた分岐処理を忘れずに実装してください。
- (void)popinfoReceiver:(PopinfoReceiver *)pr didReceivePopinfoMessage:(NSInteger)messageId popup:(NSString *)popup payload:(NSDictionary *)payload
{
BOOL hasDetail = payload && [payload objectForKey:@"has_detail"] && [payload[@"has_detail"] integerValue] == 1;
if (hasDetail) {
// お知らせ詳細画面を表示させる記述など
} else {
// PUSH 通知のみ配信時の処理を記述する
}
}
func popinfoReceiver(_ popinfoReceiver: PopinfoReceiver, didReceivePopinfoMessage messageId: Int, popup: String, payload: [AnyHashable : Any]) {
let hasDetail = (payload["has_detail"] as? Int) == 1
if hasDetail {
// お知らせ詳細画面を表示させる記述など
} else {
// PUSH 通知のみ配信時の処理を記述する
}
}
App 起動中のプッシュ通知受信について
通知センターから行われるプッシュ通知は、Appがバックグラウンドにある場合にのみ発生します。
そのため、 Appがフォアグラウンド時にプッシュ通知が届いた場合、iOS からバナーやダイアログは表示されません 。
いきなりお知らせ詳細画面を表示するのではなく、ダイアログを表示してユーザーに知らせたい場合は、ここでフォアグラウンド状態かどうかを確認した上でダイアログを表示させる実装を行う必要があります。
7.3 バックグラウンドタスク
本 SDK は下記の目的のために、エンドユーザーが App を起動していないときもバックグラウンドタスクを実行させる必要があります。
- ユーザーが App を起動していないときもGPS配信またはBluetooth配信を実施する
- ユーザーの App 利用状況を集計し、FANSHIP 管理画面から確認できるようにする
バックグラウンドタスクを実行するための方法として、下記の3つの方法があります
- Background Tasks API の Background App Refresh Tasks (以下 BGAppRefresh) を利用する
- Background Tasks API の Background Processing Tasks (以下 BGProcessing) を利用する
- 旧バックグラウンドフェッチを利用する
BGAppRefresh と BGProcessing について
BGAppRefresh と BGProcessing はどちらも iOS 13 から追加された Background Tasks API に属する機能ですが、発動タイミングやタスクを実行可能な制限時間等が両者間で異なります。
Appleのドキュメント Choosing Background Strategies for Your App をご覧の上、ご利用のプロジェクトにおいて適切なものをお選びください。
なお、Background Tasks API の仕様に関するお問い合わせは、お手数ですが Apple Developer サポート にて行っていただきますようお願い致します。
iOS 13 未満では Background Tasks API は利用できません
Background Tasks API は、 iOS 13 から導入された機能であるため、iOS 12 以下においては動作いたしません。
そのため、 App のサポートOSバージョンに iOS 12 以下が含まれる場合は、「iOS 12 以下の端末で実行された場合に限り、旧バックグラウンドフェッチ処理を実行する」といった実装をご検討ください。
以下、各方法の実装手順をご説明します。
7.3.1 Background App Refresh Tasks を利用する
- Background fetch
- Info.plist 内のキー Permitted background task scheduler identifiers に対する値
- SdkSettings 内のキー FanshipBGTaskSchedulerPermittedIdentifiers に対する値
-[AppDelegate applicationDidEnterBackground:] 内部にて、-[PopinfoReceiver scheduleAppRefreshTask] をコールします。
- (void)applicationDidEnterBackground:(UIApplication *)application {
if (@available(iOS 13.0, *)) {
[popinfoReceiver enterBackgroundTask];
}
}
func applicationDidEnterBackground(_ application: UIApplication) {
if #available(iOS 13.0, *) {
popinfoReceiver.enterBackgroundTask()
}
}
7.3.2 Background Processing Tasks を利用する
- Background fetch
- Background processing
- Info.plist 内のキー Permitted background task scheduler identifiers に対する値
- SdkSettings 内のキー FanshipBGTaskSchedulerPermittedIdentifiers に対する値
FANSHIP_BG_PROCESSING_TASK_USE を有効にします。以下のいずれかを実施してください。
- Build Settings > Apple Clang - Processing > Preprocessor Macros に
FANSHIP_BG_PROCESSING_TASK_USE=1をセットする。 - ビルド時の引数に
OTHER_CFLAGS="-DFANSHIP_BG_PROCESSING_TASK_USE=1"をセットする
-[AppDelegate applicationDidEnterBackground:] 内部にて、-[PopinfoReceiver enterBackgroundTask] をコールします。
- (void)applicationDidEnterBackground:(UIApplication *)application {
if (@available(iOS 13.0, *)) {
[popinfoReceiver enterBackgroundTask];
}
}
func applicationDidEnterBackground(_ application: UIApplication) {
if #available(iOS 13.0, *) {
popinfoReceiver.enterBackgroundTask()
}
}
Background Tasks API 間の同時利用
一般に一つの App 内で BGAppRefresh と BGProcessing は同時に利用できますが、本SDKのバックグラウンドタスクは動作を安定させるために BGAppRefresh または BGProcessing のいずれか一方を利用して実装する形式となっています。
7.3.3 旧バックグラウンドフェッチを利用する
バックグラウンドフェッチ発動時にコールされるアプリケーションデリゲートメソッドを以下のように記述してください。
これは SDK バージョン 5.2.2 以下における標準的な実装方法でした。2020年11月時点ではiOS14においても問題なく動作します。
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[popinfoReceiver enterBackgroundFetch];
completionHandler(UIBackgroundFetchResultNewData);
}
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
popinfoReceiver.enterBackgroundFetch()
completionHandler(.newData)
}
iOS 13 以降の Background Fetch API について
iOS 13 以降、 BackgroundTasks の追加にともない、旧バックグラウンドフェッチは deprecated となりました。
ただし、 Apple は上記に関して廃止までの詳細なロードマップを発表しておらず、また iOS13 以上の OS のみで利用できることから、数年ほど(少なくともXcodeのサポートデバイス一覧から iOS12 以下が消失するまで)は引き続き利用できるものと予想されます。
Background Tasks API と旧バックグラウンドフェッチとの同時起動
Background Tasks API と旧バックグラウンドフェッチは、一般には同時に作動させるような利用が想定されていないと考えられており、SDKの動作不安定を招く可能性がありますので、推奨されません。
7.4 お知らせ一覧画面
受信したメッセージの一覧を表示するには、PopinfoListViewController クラスを利用します。
- このビューコントローラを表示すると、「受信したメッセージの一覧」を表示するテーブルビュー が描画されます。
- ユーザーがこのテーブルビューのセル(行)をタップすると、お知らせ詳細画面 に遷移します。
なお、この画面は ナビゲーションコントローラ がある状態でご利用ください。
詳細な組み込み例は、SampleApp/SampleSwiftApp プロジェクト内の AppDelegate をご参照ください。
PopinfoListViewController *listVC = [[PopinfoListViewController alloc] initWithNibName:@"PopinfoListViewController" bundle:[NSBundle mainBundle]];
[navigationController pushViewController:listVC animated:NO];
let listVC = PopinfoListViewController(nibName:"PopinfoListViewController", bundle:Bundle.main)
navigationController.pushViewController(listVC, animated: false)
クラスは継承してお使いください
FANSHIP SDK が提供する標準 UI は、適宜改良されていく可能性があります。
App 側でお知らせ一覧画面の UI をカスタマイズする場合は、 PopinfoListViewController クラスをそのまま修正するのではなく、これを継承した独自クラス で行っていただくことをおすすめします。
Storyboard を利用する場合
Storyboard を用いて実装する場合 は、 Custom Class に PopinfoListViewController を指定することも可能ですが、上記と同じ理由から PopinfoListViewController クラスを継承した独自クラス を指定することをおすすめします。
7.5 お知らせ詳細画面
受信したメッセージの詳細を表示するには、PopinfoDetailViewController クラスを利用します。
- このビューコントローラは、表示する前に メッセージ ID の指定が必要です。
- 表示すると受信したメッセージの詳細が描画されます。
詳細な組み込み例は、SampleApp/SampleSwiftApp プロジェクト内の AppDelegate をご参照ください。
PopinfoDetailViewController *detailVC = [[PopinfoDetailViewController alloc] initWithNibName:@"PopinfoDetailViewController" bundle:[NSBundle mainBundle]];
detailVC.messageId = messageId;
[navigationController pushViewController:detailVC animated:NO];
let detailVC = PopinfoDetailViewController(nibName:"PopinfoDetailViewController", bundle:Bundle.main)
detailVC.messageId = messageId
navigationController.pushViewController(detailVC, animated: false)
クラスは継承してお使いください
FANSHIP SDK が提供する標準 UI は、適宜改良されていく可能性があります。
App 側でお 知らせ詳細画面の UI をカスタマイズする場合は、PopinfoDetailViewController クラスを継承した独自クラス で行っていただくことをおすすめします。
Storyboard を利用する場合
Storyboard を用いて実装する場合 は、 Custom Class に PopinfoDetailViewController を指定することも可能ですが、上記と同じ理由から PopinfoDetailViewController クラスを継承した独自クラス を指定することをおすすめします。
7.6 ユーザー属性登録
この実装は必須ではありません。
PopinfoSegmentSettingsViewController を使い、エンドユーザーの属性を設定することができます。
FANSHIP では、性別や年齢層、趣味などといった属性をエンドユーザーに設定することができます。
設定された属性は、「 属性絞り込み配信 」などで利用することができます。
ご利用には申請が必要です
エンドユーザーに提示する属性および選択肢は、利用開始時に申請 する必要があります。
SDK側から変更することはできません 。
エンドユーザーに属性を設定する方法は2通りあり、API を経由して設定する方法と、エンドユーザーが属性設定画面から視覚的に設定する方法があります。
7.6.1 API として設定する方法
PopinfoReceiver の setSegments:forKey:completion: メソッドを利用します。詳細は「iPhone 用 SDK 組み込みガイド_追加機能」をご参照ください。
7.6.2 属性設定画面からユーザーが視覚的に設定する方法
属性設定画面 PopinfoSegmentSettingsViewController を表示し、ユーザーに視覚的に属性を選択してもらう方法です。
この画面の実装例は SampleApp/SampleSwiftApp プロジェクト内の AppDelegate に記述していますので、ご参照ください。
PopinfoSegmentSettingsViewController *segmentVC = [[PopinfoSegmentSettingsViewController alloc] initWithNibName:@"PopinfoSegmentSettingsViewController" bundle:[NSBundle mainBundle]];
segmentVC.delegate = self;
let segmentVC = PopinfoSegmentSettingsViewController(nibName:"PopinfoSegmentSettingsViewController", bundle:Bundle.main)
segmentVC.delegate = self;