本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
如果您是 Amazon Cognito Sync 的新用户,请使用 AWS AppSync
它允许同步用户数据,如应用程序首选项或游戏状态。它还通过允许多个用户实时同步和协作处理共享的数据,来扩展这些功能。
Amazon Cognito 会自动跟踪身份和设备之间的关联。使用推送同步功能,您可以确保在身份数据发生更改后向给定身份的每个实例发送通知。推送同步可以确保,无论特定身份的同步存储数据何时发生更改,与该身份关联的所有设备都会收到一个静音推送通知,通知它们所发生的更改。
注意
推送同步不支持 JavaScript、Unity 或 Xamarin。
您必须首先设置用于推送同步的账户,并在 Amazon Cognito 控制台中启用推送同步,然后才可使用推送同步。
创建 Amazon Simple Notification Service(Amazon SNS)应用程序
为支持的平台创建并配置 Amazon SNS 应用程序,如 SNS 开发人员指南中所述。
在 Amazon Cognito 控制台中启用推送同步
您可以通过 Amazon Cognito 控制台启用推送同步。从控制台主页
-
单击您需要启用推送同步的身份池的名称。此时将显示身份池的 Dashboard(控制面板)页。
-
在Dashboard(控制面板)页的右上角,单击 Manage Identity Pools(管理身份池)。此时将显示 Federated Identities(联合身份)页。
-
向下滚动并单击 Push synchronization(推送同步)以将其展开。
-
在 Service role(服务角色)下拉菜单中,选择授予 Cognito 发送 SNS 通知的权限的 IAM 角色。在 AWS IAM 控制台
中,单击 Create role (创建角色) 以创建或修改与您身份池关联的角色。 -
选择一个平台应用程序,然后单击 Save Changes(保存更改)。
-
为应用程序授予 SNS 访问权限
在 AWS Identity and Access Management 控制台中,将您的 IAM 角色配置为具有完整 Amazon SNS 访问权限,或创建一个具有完整 Amazon SNS 访问权限的新角色。以下示例角色信任策略授予 Amazon Cognito Sync 有限代入 IAM 角色的能力。Amazon 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 服务。您可以通过 Android SDK Manager
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
:已更新的数据集的名称。这可用于 openOrCreateDataset 调用。syncCount
:远程数据集的同步计数。您可以使用此方法来确保本地数据集已过期,并且传入同步是新的。
在您的应用程序中使用推送同步:iOS – Objective-C
要获取应用程序的设备令牌,请参阅 Apple 有关注册远程通知的文档。收到来自 APN 的作为 NSData 对象的设备令牌之后,您需要立即使用同步客户端的 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
之前,请确保在每个数据集上至少同步一次,以便数据集存在于服务器上。
要对推送通知做出反应,您需要在应用程序委托上实施 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 有关注册远程通知的文档。收到来自 APN 的作为 NSData 对象的设备令牌之后,您需要立即使用同步客户端的 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
之前,请确保在每个数据集上至少同步一次,以便数据集存在于服务器上。
要对推送通知做出反应,您需要在应用程序委托上实施 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
:远程数据集的同步计数。您可以使用此方法来确保本地数据集已过期,并且传入同步是新的。