AWS Startups Blog

Amazon Cognito & Mobile Apps – Part2: User-state Data Synchronization

By David Behroozi, Software Developer Engineer, AWS


The percentage of people with multiple mobile devices is growing. These people might use their phone on the go and their tablet when they get home. Consequently, they now want to be able to seamlessly transition from one device to another. In previous posts, we’ve talked about how to use Amazon Cognito to provide a consistent identity for your end users and to obtain temporary, limited-privilege credentials bound to that identity. In this post, we show you how you to use Cognito’s sync functionality to synchronize user data across an end users’ devices.

Overview

Cognito1

Imagine you have a game with 100 levels. Your end users will probably get frustrated if they have to beat the same levels over when they switch to another device. To fix this, you want to synchronize the level they are on using Cognito so they can resume where they left off.

Creating an Identity Pool

The first step is to create an identity pool. An identity pool holds your end users’ identities. Each end user has his or her own identity. Most often, the identity pool corresponds to one mobile app, but in cases where you want to share data across multiple apps, you should create one identity pool instead of one identity pool per app.

If you haven’t already created an identity pool, you can do so by going to the Amazon Cognito Console.

In order to sync data across devices, your identity pool must support authenticated identities. Unauthenticated identities are tied to the device, so unless an end user authenticates, no data can be synced across devices. When you are creating your identity pool be sure to configure one or more identity providers. This page guides you through setting up an Amazon, Facebook or Google app to acquire the necessary app id or client id.

During the creation of the identity pool, you will be asked to create a new IAM role or pick an existing one for your end users. This role defines the AWS services and permissions your end users/app will be granted when they acquire temporary credentials. The default policy allows access to the Amazon Cognito sync service and allows you to emit events to Amazon Mobile Analytics. At a minimum, you will need a policy that allows access to the Amazon Cognito sync service.

At the end of the identity pool creation process, you will receive some boilerplate code to put in your app. Save this code since you will use it below.

Syncing data

If you haven’t already, download and install the AWS Mobile SDK. Follow the instructions to setup either Android or iOS.

Once you have installed and configured your development environment, you need to instantiate the Cognito credentials provider in your app. Put the boilerplate code you got from the console above in your app. If you’ve misplaced that code, it looks like this:

Android

import com.amazonaws.android.auth.CognitoCredentialsProvider;

CognitoCredentialsProvider cognitoProvider = new CognitoCredentialsProvider(
myActivity.getContext(), // get the context for the current activity
“AWSACCOUNTID”,
“region:identity-pool-id”,
“arn:aws:iam::AWSACCOUNTID:role/UnauthRole”,
“arn:aws:iam::AWSACCOUNTID:role/AuthRole”

);

iOS

#import <AWSiOSSDKv2/AWSCore.h>

AWSCognitoCredentialsProvider *credentialsProvider = [AWSCognitoCredentialsProvider
credentialsWithRegionType:AWSRegionUSEast1
accountId:@”AWSACCOUNTID”
identityPoolId:@”region:your-identity-pool-id”
unauthRoleArn:@”arn:aws:iam::AWSACCOUNTID:role/UnauthRole”,
authRoleArn:@”arn:aws:iam::AWSACCOUNTID:role/AuthRole”];

AWSServiceConfiguration *configuration = [AWSServiceConfiguration configurationWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];

[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;

The next step is to prompt the user to login with an identity provider and supply the Cognito credentials provider with the login token. The process is different depending on the identity provider you use.

Refer to this guide for Android.

Refer to this guide for iOS.

Now that you have a Cognito identity provider associated with the appropriate end users’ login, you can instantiate a sync client.

Android

import com.amazonaws.android.cognito.*;

//COGNITO_POOL_ID is a constant set to your Cognito Pool Id
//provider is the provider you just initialized
CognitoSyncClient syncClient = new DefaultCognitoSyncClient(myActivity.getContext(), COGNITO_POOL_ID, cognitoProvider);

iOS

#import <AWSiOSSDKv2/AWSCore.h>
#import <AWSCognitoSync/Cognito.h>
AWSCognito *syncClient = [AWSCognito defaultCognito];

With a sync client, you can open a dataset and manipulate it.

Android

Dataset dataset = client.openOrCreateDataset("GameInfo");

//call this once when you open the dataset to get the latest data from the cloud
dataset.synchronize(this, syncCallback);

dataset.put(“playerName”,”David”);
dataset.put(“currentLevel”,”29″);
dataset.put(“highScore”,”120345″);

//now synchronize this data to make it available to other devices
dataset.synchronize(this, syncCallback);

The syncCallback object needs to implement the SyncCallback interface. It gets called during the synchronization process to indicate success, failure, conflicts, or other scenarios. Details about implementing it are here.

iOS

AWSCognitoDataset *dataset = [syncClient openOrCreateDataset:@"GameInfo"];

//call this once when you open the dataset to get the latest data from the cloud
[dataset synchronize];

[dataset setString:@”David” forKey:@”playerName”];
[dataset setString:@”29″ forKey:@”currentLevel”];
[dataset setString:@”120345″ forKey:@”highScore”];

//now synchronize this data to make it available to other devices

So far in this example we’ve saved three key-value pairs into a dataset called GameInfo. How do we synchronize this data on another device? The process for accessing the data on another device is similar. Once you have opened your dataset and synchronized it, you can retrieve the value for a particular key like this:

Android

String playerName = dataset.get("playerName");
String currentLevel = dataset.put("currentLevel");
String highScore = dataset.put("highScore");

iOS

NSString *playerName = [dataset stringForKey:@"playerName"];
NSString *currentLevel = [dataset stringForKey:@"currentLevel"];
NSString *highScore = [dataset stringForKey:@"highScore"];

Because Cognito stores data locally as well as in the service, you can continue to interact with your data even when you are offline. Your offline data may be stale, but anything you put into the dataset, you can immediately retrieve whether you are online or not.

Sample Applications

We have put together sample applications for Android and iOS that demonstrate how to sync data. These are a great reference for incorporating sync into your own apps. They also cover two topics not covered in this post, namely conflict resolution and handling identity merges.

Android

Github Cognito Android Sample

iOS

Github Cognito iOS Sample

Limitations

There are a few limitations to keep in mind when using sync.

  1. Each identity can have up to 20 datasets.
  2. Each dataset can have up to 1024 key-value pairs.
  3. The combined size of the keys and values in a dataset cannot exceed 1 megabyte.

Conclusion

Amazon Cognito makes it easy to sync user data across mobile devices. We are excited to see how you will incorporate it into your apps to provide a seamless experience for your end users. If you get stuck or need help, feel free to comment on this blog or reach us via the Cognito forum.