本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
实现推送同步
如果您是 Amazon Cognito Sync 的新用户,请使用 AWS AppSync
它允许同步用户数据,如应用程序首选项或游戏状态。它还通过允许多个用户实时同步和协作处理共享的数据,来扩展这些功能。
Amazon Cognito 会自动跟踪身份和设备之间的关联。使用推送同步功能,您可以确保在身份数据发生更改后向给定身份的每个实例发送通知。推送同步可以确保,无论特定身份的同步存储数据何时发生更改,与该身份关联的所有设备都会收到一个静音推送通知,通知它们所发生的更改。
注意
Unity 或 Xamarin 不支持推送同步。 JavaScript
您必须首先设置用于推送同步的账户,并在 Amazon Cognito 控制台中启用推送同步,然后才可使用推送同步。
创建亚马逊简单通知服务 (AmazonSNS) 应用程序
按照SNS开发者指南中所述,为您支持的平台创建和配置 Amazon SNS 应用程序。
在 Amazon Cognito 控制台中启用推送同步
您可以通过 Amazon Cognito 控制台启用推送同步。从控制台主页
-
单击您需要启用推送同步的身份池的名称。此时将显示身份池的 Dashboard(控制面板)页。
-
在Dashboard(控制面板)页的右上角,单击 Manage Identity Pools(管理身份池)。此时将显示 Federated Identities(联合身份)页。
-
向下滚动并单击 Push synchronization(推送同步)以将其展开。
-
在服务角色下拉菜单中,选择授予 Cognito 发送通知权限的IAM角色。SNS单击 “创建角色”,在AWS IAM控制台
中创建或修改与您的身份池关联的角色。 -
选择一个平台应用程序,然后单击 Save Changes(保存更改)。
-
授予对您的应用程序的SNS访问权限
在 AWS Identity and Access Management 控制台中,将您的IAM角色配置为拥有完全的亚马逊SNS访问权限,或者创建一个具有完全亚马逊SNS访问权限的新角色。以下示例角色信任策略授予 Amazon Cognito Sync 担任角色的有限能力。IAMAmazon Cognito Sync 只能在代表 aws:SourceArn
条件中的身份池和 aws:SourceAccount
条件中的账户时才能代入该角色。
{ "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角色的更多信息,请参阅角色(委托和联合)。
在您的应用程序中使用推送同步:Android
您的应用程序需要导入 Google Play 服务。你可以SDK通过安卓SDK管理
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
@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。这可用于验证或获取其他信息,但从接收方的角度来看,这并不是不可或缺的。identityId
:池中的身份 ID。datasetName
:已更新的数据集的名称。这是为了调用 openOrCreate数据集而提供的。syncCount
:远程数据集的同步计数。您可以使用此方法来确保本地数据集已过期,并且传入同步是新的。
在您的应用程序中使用推送同步:iOS – Objective-C
要获取应用程序的设备令牌,请参阅 Apple 有关注册远程通知的文档。收到作为NSData对象的设备令牌后APNs,您需要使用同步客户端的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; } ];
在调试模式下,您的设备将在APNs沙盒中注册;在发布模式下,设备将在沙盒中注册。APNs要接收来自特定数据集的更新,请使用 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
之前,请确保在每个数据集上至少同步一次,以便数据集存在于服务器上。
要对推送通知做出反应,您需要在应用程序委托上实施 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。这可用于验证或获取其他信息,但从接收方的角度来看,这并不是不可或缺的。 -
identityId
:池中的身份 ID。 -
datasetName
:已更新的数据集的名称。这可用于openOrCreateDataset
调用。 -
syncCount
:远程数据集的同步计数。您可以使用此方法来确保本地数据集已过期,并且传入同步是新的。
在您的应用程序中使用推送同步:iOS – Swift
要获取应用程序的设备令牌,请参阅 Apple 有关注册远程通知的文档。收到作为NSData对象的设备令牌后APNs,您需要使用同步客户端的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 })
在调试模式下,您的设备将在APNs沙盒中注册;在发布模式下,设备将在沙盒中注册。APNs要接收来自特定数据集的更新,请使用 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
之前,请确保在每个数据集上至少同步一次,以便数据集存在于服务器上。
要对推送通知做出反应,您需要在应用程序委托上实施 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。这可用于验证或获取其他信息,但从接收方的角度来看,这并不是不可或缺的。identityId
:池中的身份 ID。datasetName
:已更新的数据集的名称。这可用于openOrCreateDataset
调用。syncCount
:远程数据集的同步计数。您可以使用此方法来确保本地数据集已过期,并且传入同步是新的。