

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# プッシュ同期の実装
<a name="push-sync"></a>

****  
Amazon Cognito Sync を初めて使用する場合は、[AWS AppSync](https://aws.amazon.com/appsync/) を使用してください。Amazon Cognito Sync と同様に、 AWS AppSync はデバイス間でアプリケーションデータを同期するためのサービスです。  
このサービスは、アプリの設定やゲームステートといったユーザーデータの同期化を可能にします。また、複数のユーザーが同期し、共有されたデータでリアルタイムにコラボレートできるようにすることで、これらの機能を拡張します。

Amazon Cognito は自動的にアイデンティティとデバイス間の関係を追跡します。プッシュ同期機能を使用すると、ID データが変更されたときに、特定の ID のすべてのインスタンスに確実に通知されます。プッシュ同期は、特定のアイデンティティの同期ストアデータが変更されるたびに、そのアイデンティティに関連付けられているすべてのデバイスが、この変更を伝えるサイレントプッシュ通知を受け取ることを確実にします。

**注記**  
プッシュ同期は JavaScript、Unity、Xamarin ではサポートされません。

プッシュ同期を使用する前に、まずプッシュ同期用にアカウントをセットアップし、Amazon Cognito コンソールでプッシュ同期を有効にする必要があります。

## Amazon Simple Notification Service (Amazon SNS) アプリケーションを作成する
<a name="create-an-amazon-SNS-app"></a>

[SNS デベロッパーガイド](https://docs.aws.amazon.com/sns/latest/dg/SNSMobilePush.html)の説明に従って、サポートされているプラットフォーム用の Amazon SNS アプリを作成し、設定します。

## Amazon Cognito コンソールでプッシュ同期を有効にする
<a name="enable-push-sync-in-the-amazon-cognito-console"></a>

プッシュ同期は Amazon Cognito コンソールを使って有効にできます。[コンソールのホームページ](https://console.aws.amazon.com/cognito/home)から、次の操作を行います。

1. プッシュ同期を有効にする ID プールの名前をクリックします。アイデンティティプールの [**Dashboard**] (ダッシュボード) ページが表示されます。

1. [**ダッシュボード**] ページの右上にある、[**ID プールの管理**] をクリックします。[**フェデレーティッドアイデンティティ**] ページが表示されます。

1. 下にスクロールし、**同期をプッシュします**をクリックして展開します。

1. [**Service role**] (サービスロール) ドロップダウンメニューで、SNS 通知を送信するアクセス許可を Cognito に付与する IAM ロールを選択します。[**Create role**] (ロールの作成) をクリックして、[AWS IAM コンソール](https://console.aws.amazon.com/iam/home)で ID プールに関連付けられたロールを作成または変更します。

1. プラットフォームアプリケーションを選択し、[**Save Changes**] (変更の保存) をクリックします。

1. アプリケーションへの SNS アクセスの許可

 AWS Identity and Access Management コンソールで、完全な Amazon SNS アクセスを持つように IAM ロールを設定するか、完全な Amazon SNS アクセスを持つ新しいロールを作成します。次のロール信頼ポリシーの例では、Amazon Cognito Sync に IAM ロールを引き受ける制限付きの機能を付与しています。Amazon Cognito Sync は、条件 `aws:SourceArn` の ID プールと条件 `aws:SourceAccount` のアカウントの両方に代わり行う場合にのみ、その役割を担うことができます。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "cognito-sync.amazonaws.com"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceAccount": "123456789012"
                },
                "ArnLike": {
                    "AWS:SourceArn": "arn:aws:cognito-identity:us-east-1:123456789012:identitypool/us-east-1:177a950c-2c08-43f0-9983-28727EXAMPLE"
                }
            }
        }
    ]
}
```

------

IAM ロールの詳細については、「[ロール (委任とフェデレーション) ](https://docs.aws.amazon.com/IAM/latest/UserGuide/WorkingWithRoles.html)」を参照してください。

## アプリケーションでのプッシュ同期の使用: Android
<a name="push-sync-1.android"></a>

アプリケーションは、Google Play サービスをインポートする必要があります。[Android SDK マネージャー](http://developer.android.com/tools/help/sdk-manager.html)から、最新バージョンの Google Play SDK をダウンロードできます。Android のドキュメントの「[Android Implementation](https://developers.google.com/instance-id/guides/android-implementation)」に従ってアプリを登録し、GCM から登録 ID を受け取ります。登録 ID を取得したら、以下のスニペットにあるように、デバイスを Amazon Cognito に登録する必要があります。

```
String registrationId = "MY_GCM_REGISTRATION_ID";
try {
    client.registerDevice("GCM", registrationId);
} catch (RegistrationFailedException rfe) {
    Log.e(TAG, "Failed to register device for silent sync", rfe);
} catch (AmazonClientException ace) {
    Log.e(TAG, "An unknown error caused registration for silent sync to fail", ace);
}
```

これで、デバイスをサブスクライブして、特定のデータセットから更新を受け取ることができます。

```
Dataset trackedDataset = client.openOrCreateDataset("myDataset");
if (client.isDeviceRegistered()) {
    try {
        trackedDataset.subscribe();
    } catch (SubscribeFailedException sfe) {
        Log.e(TAG, "Failed to subscribe to datasets", sfe);
    } catch (AmazonClientException ace) {
        Log.e(TAG, "An unknown error caused the subscription to fail", ace);
    }
}
```

データセットからプッシュ通知の受け取りを中止するには、unsubscribe メソッドを呼び出します。`CognitoSyncManager` オブジェクトのすべてのデータセット (または特定のサブセット) にサブスクライブするには、`subscribeAll()` を使用します。

```
if (client.isDeviceRegistered()) {
    try {
        client.subscribeAll();
    } catch (SubscribeFailedException sfe) {
        Log.e(TAG, "Failed to subscribe to datasets", sfe);
    } catch (AmazonClientException ace) {
        Log.e(TAG, "An unknown error caused the subscription to fail", ace);
    }
}
```

[Android BroadcastReceiver ](http://developer.android.com/reference/android/content/BroadcastReceiver.html)オブジェクトの実装で、最新バージョンの変更されたデータセットを確認して、アプリをもう一度同期する必要があるかどうか判断できます。

```
@Override
public void onReceive(Context context, Intent intent) {

    PushSyncUpdate update = client.getPushSyncUpdate(intent);

    // The update has the source (cognito-sync here), identityId of the
    // user, identityPoolId in question, the non-local sync count of the
    // data set and the name of the dataset. All are accessible through
    // relevant getters.

    String source = update.getSource();
    String identityPoolId = update.getIdentityPoolId();
    String identityId = update.getIdentityId();
    String datasetName = update.getDatasetName;
    long syncCount = update.getSyncCount;

    Dataset dataset = client.openOrCreateDataset(datasetName);

    // need to access last sync count. If sync count is less or equal to
    // last sync count of the dataset, no sync is required.

    long lastSyncCount = dataset.getLastSyncCount();
    if (lastSyncCount < syncCount) {
        dataset.synchronize(new SyncCallback() {
            // ...
        });
    }

}
```

プッシュ通知のペイロードでは、次のキーを利用できます。
+ `source`: cognito-sync。これは、通知間の差別化要素として機能します。
+ `identityPoolId`: ID プールの ID。これは検証や追加の情報用に使用できますが、レシーバーの観点からは不可欠ではありません。
+ `identityId`: プール内のアイデンティティ ID。
+ `datasetName`: 更新されたデータセットの名前。これは openOrCreateDataset 呼び出しの目的で利用できます。
+ `syncCount`: リモートデータセットの同期カウント。これは、ローカルデータセットが古くなっていないこと、および入力同期が新しいことを確認する方法として使用できます。

## アプリケーションでプッシュ同期を使用する: iOS - Objective-C
<a name="push-sync-1.ios-objc"></a>

アプリ用のデバイストークンを取得するには、Apple ドキュメントの「Registering for Remote Notifications」を参照してください。APN から NSData オブジェクトとしてデバイストークンを受け取ったら、以下のように、Sync クライアントの `registerDevice:` メソッドを使用して、デバイスを Amazon Cognito に登録する必要があります。

```
AWSCognito *syncClient = [AWSCognito defaultCognito];
    [[syncClient registerDevice: devToken] continueWithBlock:^id(AWSTask *task) {
        if(task.error){
            NSLog(@"Unable to registerDevice: %@", task.error);
        } else {
            NSLog(@"Successfully registered device with id: %@", task.result);
        }
        return nil;
      }
    ];
```

デバッグモードでは、デバイスは APN サンドボックスで登録されます。リリースモードでは、APN で登録されます。特定のデータセットからアップデートを受けるには、`subscribe` メソッドを使用します。

```
[[[syncClient openOrCreateDataset:@"MyDataset"] subscribe] continueWithBlock:^id(AWSTask *task) {
        if(task.error){
            NSLog(@"Unable to subscribe to dataset: %@", task.error);
        } else {
            NSLog(@"Successfully subscribed to dataset: %@", task.result);
        }
        return nil;
      }
    ];
```

データセットからプッシュ通知の受け取りを中止するには、`unsubscribe` メソッドを呼び出します。

```
[[[syncClient openOrCreateDataset:@”MyDataset”] unsubscribe] continueWithBlock:^id(AWSTask *task) {
        if(task.error){
            NSLog(@"Unable to unsubscribe from dataset: %@", task.error);
        } else {
            NSLog(@"Successfully unsubscribed from dataset: %@", task.result);
        }
        return nil;
      }
    ];
```

`AWSCognito` オブジェクトのすべてのデータセットをサブスクライブするには、`subscribeAll` を呼び出します。

```
[[syncClient subscribeAll] continueWithBlock:^id(AWSTask *task) {
        if(task.error){
            NSLog(@"Unable to subscribe to all datasets: %@", task.error);
        } else {
            NSLog(@"Successfully subscribed to all datasets: %@", task.result);
        }
        return nil;
      }
    ];
```

`subscribeAll` を呼び出す前に、少なくとも各データセットで 1 回同期を行い、データセットがサーバー上に存在するようにします。

プッシュ通知に応答するには、アプリの代理で `didReceiveRemoteNotification` メソッドを実装する必要があります。

```
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"CognitoPushNotification" object:userInfo];
    }
```

通知ハンドラを使用して通知を投稿する場合は、データセットへのハンドルがある、アプリケーションの他の場所で通知に応答することができます。次のように通知にサブスクライブしているとします。

```
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceivePushSync:)
    name: :@"CognitoPushNotification" object:nil];
```

その場合は、次のように通知に応答できます。

```
- (void)didReceivePushSync:(NSNotification*)notification
    {
        NSDictionary * data = [(NSDictionary *)[notification object] objectForKey:@"data"];
        NSString * identityId = [data objectForKey:@"identityId"];
        NSString * datasetName = [data objectForKey:@"datasetName"];
        if([self.dataset.name isEqualToString:datasetName] && [self.identityId isEqualToString:identityId]){
            [[self.dataset synchronize] continueWithBlock:^id(AWSTask *task) {
                if(!task.error){
                    NSLog(@"Successfully synced dataset");
                }
                return nil;
            }];
        }
    }
```

プッシュ通知のペイロードでは、次のキーを利用できます。
+ `source`: cognito-sync。これは、通知間の差別化要素として機能します。
+ `identityPoolId`: ID プールの ID。これは検証や追加の情報用に使用できますが、レシーバーの観点からは不可欠ではありません。
+ `identityId`: プール内のアイデンティティ ID。
+ `datasetName`: 更新されたデータセットの名前。これは `openOrCreateDataset` 呼び出しの目的で利用できます。
+ `syncCount`: リモートデータセットの同期カウント。これは、ローカルデータセットが古くなっていないこと、および入力同期が新しいことを確認する方法として使用できます。

## アプリケーションでプッシュ同期を使用する: iOS - Swift
<a name="push-sync-1.ios-swift"></a>

アプリ用のデバイストークンを取得するには、Apple ドキュメントの「Registering for Remote Notifications」を参照してください。APN から NSData オブジェクトとしてデバイストークンを受け取ったら、以下の のように、Sync クライアントの registerDevice: メソッドを使用して、デバイスを Amazon Cognito に登録する必要があります。

```
let syncClient = AWSCognito.default()
syncClient.registerDevice(devToken).continueWith(block: { (task: AWSTask!) -> AnyObject! in
    if (task.error != nil) {
        print("Unable to register device: " + task.error.localizedDescription)

    } else {
        print("Successfully registered device with id: \(task.result)")
    }
    return task
})
```

デバッグモードでは、デバイスは APN サンドボックスで登録されます。リリースモードでは、APN で登録されます。特定のデータセットからアップデートを受けるには、`subscribe` メソッドを使用します。

```
syncClient.openOrCreateDataset("MyDataset").subscribe().continueWith(block: { (task: AWSTask!) -> AnyObject! in
  if (task.error != nil) {
      print("Unable to subscribe to dataset: " + task.error.localizedDescription)

  } else {
      print("Successfully subscribed to dataset: \(task.result)")
  }
  return task
})
```

データセットからプッシュ通知の受け取りを中止するには、`unsubscribe` メソッドを呼び出します。

```
syncClient.openOrCreateDataset("MyDataset").unsubscribe().continueWith(block: { (task: AWSTask!) -> AnyObject! in
  if (task.error != nil) {
      print("Unable to unsubscribe to dataset: " + task.error.localizedDescription)

  } else {
      print("Successfully unsubscribed to dataset: \(task.result)")
  }
  return task
})
```

`AWSCognito` オブジェクトのすべてのデータセットをサブスクライブするには、`subscribeAll` を呼び出します。

```
syncClient.openOrCreateDataset("MyDataset").subscribeAll().continueWith(block: { (task: AWSTask!) -> AnyObject! in
  if (task.error != nil) {
      print("Unable to subscribe to all datasets: " + task.error.localizedDescription)

  } else {
      print("Successfully subscribed to all datasets: \(task.result)")
  }
  return task
})
```

`subscribeAll` を呼び出す前に、少なくとも各データセットで 1 回同期を行い、データセットがサーバー上に存在するようにします。

プッシュ通知に応答するには、アプリの代理で `didReceiveRemoteNotification` メソッドを実装する必要があります。

```
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
  fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
        NSNotificationCenter.defaultCenter().postNotificationName("CognitoPushNotification", object: userInfo)
})
```

通知ハンドラを使用して通知を投稿する場合は、データセットへのハンドルがある、アプリケーションの他の場所で通知に応答することができます。次のように通知にサブスクライブしているとします。

```
NSNotificationCenter.defaultCenter().addObserver(observer:self,
   selector:"didReceivePushSync:",
   name:"CognitoPushNotification",
   object:nil)
```

その場合は、次のように通知に応答できます。

```
func didReceivePushSync(notification: NSNotification) {
    if let data = (notification.object as! [String: AnyObject])["data"] as? [String: AnyObject] {
        let identityId = data["identityId"] as! String
        let datasetName = data["datasetName"] as! String

        if self.dataset.name == datasetName && self.identityId == identityId {
          dataset.synchronize().continueWithBlock {(task) -> AnyObject! in
              if task.error == nil {
                print("Successfully synced dataset")
              }
              return nil
          }
        }
    }
}
```

プッシュ通知のペイロードでは、次のキーを利用できます。
+ `source`: cognito-sync。これは、通知間の差別化要素として機能します。
+ `identityPoolId`: ID プールの ID。これは検証や追加の情報用に使用できますが、レシーバーの観点からは不可欠ではありません。
+ `identityId`: プール内のアイデンティティ ID。
+ `datasetName`: 更新されたデータセットの名前。これは `openOrCreateDataset` 呼び出しの目的で利用できます。
+ `syncCount`: リモートデータセットの同期カウント。これは、ローカルデータセットが古くなっていないこと、および入力同期が新しいことを確認する方法として使用できます。