Your Android app and Amazons' DynamoDB database in the cloud: a tutorial

Android and DynamoDB

DynamoDB

Amazon DynamoDb is a nonrelational database that is fast and flexible. It is a NoSQL database service with consistent, single-digit millisecond latency at any scale. DynamoDB is a managed cloud database supporting both document and key-value store models

You can use DynamoDB in your Android apps.

Android and DynamoDB: The two options

DynamoDB Object Mapper API

Using the DynamoDB Mapper API you would define a model in your app matching the model of your DynamoDB table. You then use the DynamoDBMapper class as the entry point to DynamoDB to access your data.

Document API

The Document API lets you access the individual attributes within data objects directly. You don’t have to map the DynamoDB table properties to your apps’ class members. The Document API acts as an interface between your app and the returned data.

The Document API has new data types to assist in the serialization and deserialization process.

So what’s the difference?

Both APIs have methods enabling you to perform create, update and delete operations as well as executing queries on your DynamoDB tables.

The difference between the two APIs is how the data is represented in your app. You can choose which API to use and you can even mix and match the two depending on your needs.

This tutorial uses the Document API to interact with our DynamoDB table.

Working with the Document Object

When using the Document API, your data is contained within a Document object which you pass to and from your DynamoDB table.

Documents and JSON

You can convert your Document objects to and from JSON objects however not all DynamoDB data types can be represented in JSON.

Use the Document.fromJson() and Document.toJson() methods to perform the conversion.

The Document object accepts the standard JSON types:

String

Number

Boolean

JSON arrays

JSON maps

The Document object also accepts the Amazon DynamoDB types:

binary data

null

ordered lists

The Document API does not support:

data types such as:

S3Link

Date

Calendar, etc.

Batch operations

Conditional expressions

Practical examples

For this tutorial, we assume that you have:

A DynamoDB table – if you don’t, see more on tables in the documentation. Or simply login to the Console and create a table. Choose your own Table name and enter Telephone as the Primary key (Partition key) and leave the data type as String. Leave the Use default settings box selected and press Create to create the table

A Cognito Identity Pool – users of your app will need credentials to access any AWS service. We won’t implement logging in but will allow guest users to get Cognito credentials so that we can access the DynamoDB data. So, if you don’t already have a Cognito Identity Pool, then create one. You can see our youtube tutorials on how to do that

credentialsProvider – this provides the credentials for the given Identity Pool

dbClient – we use this client to access our DynamoDB table using the credentials provided by the credentialsProvider. As we are not handling signed-in users, these would be the credentials for a guest user

setRegion() – we must set the region for our DynamoDB table here else it will default to the US_EAST_1 region

dbTable – we get an instance of our table, configured for the given client and table name

Roles and Policies

You’ll also need a Policy for your Identity Pools’ unauthenticated role. Your Identity Pool gives your unauthenticated users credentials, which enables them to assume a Role. The role has a permissions policy attached to it which determines which AWS services and resources the guest users may access and what actions they may perform.

Here’s the important part of the policy that’s attached to our unauthenticated role:

An overview of the app

Our app has one Activity, the MainActivity. It displays a number of buttons and a text view:

Get all contacts – gets all the items out of the table

Delete contact – deletes an item in the table

Add contact – adds an item in the table

Get contact – gets an item out the table

Update contact – updates an item in the table

The text view displays a message while busy and the result when finished

Clicking a button performs the relevant operation in an AsyncTask. Busy, result and error messages are displayed in the logCat.

Interacting with the DynamoDB table

Let’s look at the methods we use to create, update, delete and query items in the DynamoDB table. All our DynamoDB methods are contained in the DatabaseAccess class.

We use an AsyncTask for all the DynamoDB methods as they need to be run off the main thread.

Adding a single item

Pressing the Add contact button gets a dummy contact and starts an AsyncTask to get the matching item out the table.

We need to pass a Document object containing the contact when we execute the AsyncTask so we convert the contact to a document object using Gson and the Documents’ fromJson() method. You could of course simply have used the Contact class’ getters to get the name and telephone numbers and then used the Document class’ put() method to add them to a new Document object.

We use the dummy contacts’ telephone number as our primary key.

To add an item, we use the DatabasAccess’ addContact() method. We pass it the dummy contact which contains the primary key, the telephone number and a name.

We use the Document APIs put() method to add attributes to the document object, which in this case is the dummyContact.

putItem() - a method of the com.amazonaws.mobileconnectors.dynamodbv2.document.Table class

dummyContact - our Document object containing all our attributes

putItemOperationConfig – allows us to configure the putItem operation. We use the withReturnValues() option to specify that we want the completed operation to return ALL_OLD values. This will return any existing attributes content if they are overwritten (i.e. the old data). Supported values are:

NONE - This is the default. Nothing is returned

ALL_OLD – returns the old content of any overwritten attributes

result – this is a Document object containing the result of the operation. In this case it would be any old data but only if these attributes content were overwritten

The result document is then passed back to the AsyncTasks’ onPostExecute() method where it is processed.

Getting a single item

We need the primary key of the item that we want to get from the table. When pressing the Get item button, we get a random telephone number (our primary key) and pass it to an AsyncTask which uses our DatabaseAccess class’ getItem() method to get the matching item for the given primary key (the telephone number).

The DatabaseAccess method, getItem() then gets the item using this line of code:

Document result = dbTable.getItem(new Primitive(telephone));

Note:

result - we get the requested item result in the form of a Document object

dbTable – a reference to our DynamoDb table

getItem – gets the item in the table for the given primary key and returns it as a Document object

DeleteItemOperationConfig – enables us to configure the deletItem() operation

withReturnValues – specifies which values we want returned. The deletItem() method only supports these return values:

ALL_OLD – returns the deleted items’ content

NONE – this is the default. Nothing is returned

Updating an item

We need the primary key of the item that we want to update. Pressing the Update item button gets a random telephone number which we pass to an AsyncTask.

We call the DatabaseAccess class’ updateContact() method, passing the telephone number as a parameter.

In the updateContact() method, we get the matching item for the telephone primary key as a Document object. We then update a number of attributes in the retrieved document. Note that you can only update existing attributes.