AWS
Xamarin
Pinpoint

XamarinでAmazon Pinpointを使う(iOS編)

基本的な知識はあることが前提です。

オフィシャルページを見ながらやって詰まったところを中心に書いています。

Amazon Pinpointのセットアップ

Mobile HubからセットアップしてたのですがNotificationで詰まりました。

Mobile HubにNotification用の証明書の設定があるのですが、そこの設定だけではPinpointからNotificationが投げれなかったです。

PinpointのSettings画面のChannelsと言う項目からも証明書の設定をする必要があります。
そうしないと、Notificationを投げても届かず、エラーも教えてくれず途方に暮れます。

スクリーンショット 2018-01-31 10.10.23.png

SDKの取り込み

PinpointのXamarin SDKは存在しません(2018年1月時点)。

必要な機能だけをラップしたiOSライブラリを準備しました。

Cocoa Touch Static Library の準備

オフィシャルサイトからAWSのSDKをダウンロードしてきて、それをラップするライブラリプロジェクトを作ります。

#import "AWSSDK.h"

@implementation AWSSDK

- (void)Initialize:(NSDictionary *)launchOptions
{
    AWSCognitoCredentialsProvider *cognitoCredentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionAPNortheast1 identityPoolId:@"IdentityPoolIdを設定"];
    AWSServiceConfiguration *pinpointConfig = [[AWSServiceConfiguration
                                                alloc] initWithRegion:AWSRegionUSEast1
                                               credentialsProvider:cognitoCredentialsProvider];
    [[AWSServiceManager defaultServiceManager]
     setDefaultServiceConfiguration:pinpointConfig];
    AWSPinpointConfiguration *configuration = [[AWSPinpointConfiguration
                                                alloc] initWithAppId:@"AppIdを設定" launchOptions:launchOptions];
    _pinpoint = [AWSPinpoint pinpointWithConfiguration:configuration];
}

- (void)Regist:(NSData *)deviceToken
{
    [_pinpoint.notificationManager interceptDidRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

- (void)didReceiveNotificationResponse:(UNNotificationResponse *)response 
{
    [_pinpoint.notificationManager interceptDidReceiveRemoteNotification:response.notification.request.content.userInfo fetchCompletionHandler:^(UIBackgroundFetchResult result) {}];
}
@end

必要な機能だけを呼び出してます。
”XXXを設定”と言う箇所は各人の環境に合わせて変更します。
今回は呼び元から設定する方が良いのでしょうが、このアプリ専用でしか考えてなかったので埋め込んでます。

スクリーンショット 2018-01-31 10.16.06.png

Frameworkも必要なものだけ設定してます。

 Xamarinにバインディングプロジェクトの追加

スクリーンショット 2018-01-31 10.23.18.png

プロジェクトの追加からバインディングライブラリを追加し、追加したプロジェクトに、先ほどのXcode側のプロジェクトから出力した .a のファイルをドラッグ&ドロップします。

スクリーンショット 2018-01-31 10.22.55.png

そうすると、 .a ファイルが取り込まれ、展開ボタンを押すと .linkwith.cs と言う拡張子のファイルが見えます。

スクリーンショット 2018-01-31 10.24.43.png

.linkwith.csのファイルを編集します。

using ObjCRuntime;

[assembly: LinkWith(
    "libAWSSDK.a",
    LinkTarget.Arm64,
    SmartLink = true,
    ForceLoad = true,
    Frameworks = "CoreFoundation UserNotifications Foundation SystemConfiguration AWSCore AWSPinpoint",
    LinkerFlags = "-lz -lsqlite3",
    IsCxx = true
)]

このように内容を修正しました。
自分の場合は、めんどくさいので Arm64 だけをターゲットにしてます。
また、AWS SDKが依存しているフレームワークも指定してます。(1個1個本当に必要かどうかは検証してません。不要なものもあるかもしれません。)
オフシャルページに SQLite 使ってると書いてたのでリンクの設定も書いて見ました。

注意: ここまでの手順は実機むけです。シミュレーターの場合はシミュレーター向けのライブラリを作って統合する必要があるはずです。

using System;

using Foundation;
using UserNotifications;

namespace aws.ios
{
    [BaseType(typeof(NSObject))]
    interface AWSSDK
    {
        [Export("Initialize:")]
        void Initialize([NullAllowed] NSDictionary launchOptions);
        [Export("Regist:")]
        void Regist([NullAllowed] NSData token);
        [Export("didReceiveNotificationResponse:")]
        void didReceiveNotificationResponse([NullAllowed] UNNotificationResponse response);
    }
}

ApiDefinition.csにも呼び出すメソッドのシグニチャを書きます。

iOSプロジェクトから呼び出す

        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();

            LoadApplication(new App());

#if !DEBUG
            _aws = new AWSSDK();
            _aws.Initialize(options);

            var settings = UIUserNotificationSettings.GetSettingsForTypes(UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound, null);
            app.RegisterUserNotificationSettings(settings);
            app.RegisterForRemoteNotifications();
            UNUserNotificationCenter.Current.Delegate = new UserNotificationCenterDelegate();
#endif
            return base.FinishedLaunching(app, options);
        }

こんな感じで呼び出すところを書きます。
自分の場合はDEBUGモードの時はデバイス登録したくなかったので処理をオフにしてます。
DeviceTokenの登録やNotification受信時の処理も他に書く必要があります。

Pinpointコンソールで結果確認

Segmentを作って見て、デバイスが登録されているか確認