Amplify has re-imagined the way frontend developers build fullstack applications. Develop and deploy without the hassle.

Page updated Feb 21, 2024

Integrate your app

Next you'll use the generated model to read and write data. In this section you'll initialize DataStore, and create and query for Todo items.

Configure Amplify and DataStore

First, you'll add the DataStore plugin and configure Amplify.

Right-click on your namespace (com.example.Todo), click New, and click Java Class or Kotlin Class/File depending on which language you chose.

Configure the new class in New Java Class:

  • Enter MyAmplifyApp in the Name field

  • Press OK

  • Extend MyAmplifyApp from android.app.Application by adding extends Application to your class

Add the following import statements at the top of the file:

import android.app.Application;
import android.util.Log;
import com.amplifyframework.AmplifyException;
import com.amplifyframework.core.Amplify;
import com.amplifyframework.datastore.AWSDataStorePlugin;

Initialize Amplify by adding an onCreate method with the following code:

public void onCreate() {
super.onCreate();
try {
Amplify.addPlugin(new AWSDataStorePlugin());
Amplify.configure(getApplicationContext());
Log.i("Tutorial", "Initialized Amplify");
} catch (AmplifyException error) {
Log.e("Tutorial", "Could not initialize Amplify", error);
}
}

Configure the new class in New Kotlin Class/File:

  • Enter MyAmplifyApp in the Name field

  • Press enter

  • Extend MyAmplifyApp from android.app.Application by adding : Application() to your class

Add the following import statements at the top of the file:

import android.app.Application
import android.util.Log
import com.amplifyframework.AmplifyException
import com.amplifyframework.core.Amplify
import com.amplifyframework.datastore.AWSDataStorePlugin

Initialize Amplify by adding an onCreate method with the following code:

override fun onCreate() {
super.onCreate()
try {
Amplify.addPlugin(AWSDataStorePlugin())
Amplify.configure(applicationContext)
Log.i("Tutorial", "Initialized Amplify")
} catch (error: AmplifyException) {
Log.e("Tutorial", "Could not initialize Amplify", error)
}
}

This overrides the onCreate() to initialize Amplify when your application is launched.

Next, configure your application to use your new custom Application class. Open manifests > AndroidManifest.xml, and add an android:name attribute with the value of your new class name:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Add the android:name attribute to the application node -->
<application
android:name=".MyAmplifyApp"
<!-- ... -->
</application>
</manifest>

Build and run the application. In logcat, you'll see a log line indicating success:

com.example.MyAmplifyApp I/MyAmplifyApp: Initialized Amplify

To make this easier to find, enter the string MyAmplifyApp into the search field

Manipulating data

Create a Todo

Next, you'll create a Todo and save it to DataStore.

  1. Open MainActivity and add the following import statements at the top of the file:
import android.util.Log;
import com.amplifyframework.AmplifyException;
import com.amplifyframework.core.Amplify;
import com.amplifyframework.core.model.temporal.Temporal;
import com.amplifyframework.datastore.AWSDataStorePlugin;
import com.amplifyframework.datastore.generated.model.Priority;
import com.amplifyframework.datastore.generated.model.Todo;
import java.util.*;
import java.util.concurrent.TimeUnit;
import android.util.Log
import com.amplifyframework.AmplifyException
import com.amplifyframework.core.Amplify
import com.amplifyframework.core.model.temporal.Temporal
import com.amplifyframework.datastore.AWSDataStorePlugin
import com.amplifyframework.datastore.generated.model.Priority
import com.amplifyframework.datastore.generated.model.Todo
import java.util.*
import java.util.concurrent.TimeUnit
  1. In the same file ( MainActivity ), add the following code to the bottom of the onCreate() method:
Todo item = Todo.builder()
.name("Build Android application")
.priority(Priority.NORMAL)
.build();
Amplify.DataStore.save(item,
success -> Log.i("Tutorial", "Saved item: " + success.item().getName()),
error -> Log.e("Tutorial", "Could not save item to DataStore", error)
);
val item = Todo.builder()
.name("Build Android application")
.priority(Priority.NORMAL)
.build()
Amplify.DataStore.save(item,
{ Log.i("Tutorial", "Saved item: ${item.name}") },
{ Log.e("Tutorial", "Could not save item to DataStore", it) }
)

This code creates a Todo item with two properties: a name, and a priority, and then calls Amplify.DataStore.save() in order to store it on DataStore.

  1. After making the preceding updates to the MainActivity file, your code should look like the following:
package com.example.todo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.amplifyframework.core.Amplify;
import com.amplifyframework.core.model.query.Where;
import com.amplifyframework.core.model.temporal.Temporal;
import com.amplifyframework.datastore.AWSDataStorePlugin;
import com.amplifyframework.datastore.generated.model.Priority;
import com.amplifyframework.datastore.generated.model.Todo;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Todo item = Todo.builder()
.name("Build Android application")
.priority(Priority.NORMAL)
.build();
Amplify.DataStore.save(item,
success -> Log.i("Tutorial", "Saved item: " + success.item().getName()),
error -> Log.e("Tutorial", "Could not save item to DataStore", error)
);
}
}
package com.example.todo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.amplifyframework.core.Amplify
import com.amplifyframework.core.model.query.Where
import com.amplifyframework.core.model.temporal.Temporal
import com.amplifyframework.datastore.AWSDataStorePlugin
import com.amplifyframework.datastore.generated.model.Priority
import com.amplifyframework.datastore.generated.model.Todo
import java.util.*
import java.util.concurrent.TimeUnit
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val item = Todo.builder()
.name("Build Android application")
.priority(Priority.NORMAL)
.build()
Amplify.DataStore.save(item,
{ Log.i("Tutorial", "Saved item: ${item.name}") },
{ Log.e("Tutorial", "Could not save item to DataStore", it) }
)
}
}
  1. Build and run the application. In logcat, you'll see an indication that the item was saved successfully:
com.example.todo I/Tutorial: Initialized Amplify
com.example.todo I/Tutorial: Saved item: Build Android application
  1. Replace the item with a new Todo to save an additional item. Let's change the name and priority, and add a completedAt:
Date date = new Date();
int offsetMillis = TimeZone.getDefault().getOffset(date.getTime());
int offsetSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(offsetMillis);
Temporal.DateTime temporalDateTime = new Temporal.DateTime(date, offsetSeconds);
Todo item = Todo.builder()
.name("Finish quarterly taxes")
.priority(Priority.HIGH)
.completedAt(temporalDateTime)
.build();
val date = Date()
val offsetMillis = TimeZone.getDefault().getOffset(date.time).toLong()
val offsetSeconds = TimeUnit.MILLISECONDS.toSeconds(offsetMillis).toInt()
val temporalDateTime = Temporal.DateTime(date, offsetSeconds)
val item = Todo.builder()
.name("Finish quarterly taxes")
.priority(Priority.HIGH)
.completedAt(temporalDateTime)
.build()
  1. Build and run the application. In logcat, you'll see an indication that the item was saved successfully:
com.example.todo I/Tutorial: Initialized Amplify
com.example.todo I/Tutorial: Saved item: Finish quarterly taxes

Query Todos

Now that you have some data in DataStore, you can run queries to retrieve those records.

  1. Edit your onCreate method to remove anything related to DataStore and replace it with the following code:
Amplify.DataStore.query(Todo.class,
todos -> {
while (todos.hasNext()) {
Todo todo = todos.next();
Log.i("Tutorial", "==== Todo ====");
Log.i("Tutorial", "Name: " + todo.getName());
if (todo.getPriority() != null) {
Log.i("Tutorial", "Priority: " + todo.getPriority().toString());
}
if (todo.getCompletedAt() != null) {
Log.i("Tutorial", "CompletedAt: " + todo.getCompletedAt().toString());
}
}
},
failure -> Log.e("Tutorial", "Could not query DataStore", failure)
);
Amplify.DataStore.query(Todo::class.java,
{ todos ->
while (todos.hasNext()) {
val todo: Todo = todos.next()
Log.i("Tutorial", "==== Todo ====")
Log.i("Tutorial", "Name: ${todo.name}")
todo.priority?.let { todoPriority -> Log.i("Tutorial", "Priority: $todoPriority") }
todo.completedAt?.let { todoCompletedAt -> Log.i("Tutorial", "CompletedAt: $todoCompletedAt") }
}
},
{ Log.e("Tutorial", "Could not query DataStore", it) }
)
  1. Run the application. In logcat, you'll see both items returned:
com.example.todo I/Tutorial: Initialized Amplify
com.example.todo I/Tutorial: ==== Todo ====
com.example.todo I/Tutorial: Name: Build Android application
com.example.todo I/Tutorial: Priority: NORMAL
com.example.todo I/Tutorial: ==== Todo ====
com.example.todo I/Tutorial: Name: Finish quarterly taxes
com.example.todo I/Tutorial: Priority: HIGH
com.example.todo I/Tutorial: CompletedAt: <DateTime>
  1. Queries can also contain predicate filters. These will query for specific objects matching a certain condition.

The following predicates are supported:

Strings

eq ne le lt ge gt contains notContains beginsWith between

Numbers

eq ne le lt ge gt between

Lists

contains notContains

To use a predicate, pass an additional argument into your query. For example, the following code queries for all high priority items:

Amplify.DataStore.query(Todo.class,
Where.matches(Todo.PRIORITY.eq(Priority.HIGH)),
todos -> {
while (todos.hasNext()) {
Todo todo = todos.next();
Log.i("Tutorial", "==== Todo ====");
Log.i("Tutorial", "Name: " + todo.getName());
if (todo.getPriority() != null) {
Log.i("Tutorial", "Priority: " + todo.getPriority().toString());
}
if (todo.getCompletedAt() != null) {
Log.i("Tutorial", "Description: " + todo.getCompletedAt().toString());
}
}
},
failure -> Log.e("Tutorial", "Could not query DataStore", failure)
);
Amplify.DataStore.query(
Todo::class.java, Where.matches(Todo.PRIORITY.eq(Priority.HIGH)),
{ todos ->
while (todos.hasNext()) {
val todo: Todo = todos.next()
Log.i("Tutorial", "==== Todo ====")
Log.i("Tutorial", "Name: ${todo.name}")
todo.priority?.let { todoPriority -> Log.i("Tutorial", "Priority: $todoPriority") }
todo.completedAt?.let { todoCompletedAt -> Log.i("Tutorial", "CompletedAt: $todoCompletedAt") }
}
},
{ failure -> Log.e("Tutorial", "Could not query DataStore", failure) }
)

In the above code, notice the addition of the predicate parameter as the second argument.

  1. Run the application. In logcat, you'll see only the high priority item returned:
com.example.todo I/Tutorial: Initialized Amplify
com.example.todo I/Tutorial: ==== Todo ====
com.example.todo I/Tutorial: Name: Finish quarterly taxes
com.example.todo I/Tutorial: Priority: HIGH
com.example.todo I/Tutorial: CompletedAt: <DateTime>

Update a Todo

You may want to change the contents of a record. Below, we'll query for a record, create a copy of it, modify it, and save it back to DataStore.

  1. Edit your onCreate method to remove anything related to DataStore and replace it with the following code:
Amplify.DataStore.query(Todo.class, Where.matches(Todo.NAME.eq("Finish quarterly taxes")),
matches -> {
if (matches.hasNext()) {
Todo todo = matches.next();
Todo updatedTodo = todo.copyOfBuilder()
.name("File quarterly taxes")
.build();
Amplify.DataStore.save(updatedTodo,
updated -> Log.i("Tutorial", "Updated item: " + updatedTodo.getName()),
failure -> Log.e("Tutorial", "Update failed.", failure)
);
}
},
failure -> Log.e("Tutorial", "Query failed.", failure)
);
Amplify.DataStore.query(Todo::class.java, Where.matches(Todo.NAME.eq("Finish quarterly taxes")),
{ matches ->
if (matches.hasNext()) {
val todo = matches.next()
val updatedTodo = todo.copyOfBuilder()
.name("File quarterly taxes")
.build()
Amplify.DataStore.save(updatedTodo,
{ Log.i("Tutorial", "Updated item: ${updatedTodo.name}") },
{ Log.e("Tutorial", "Update failed.", it) }
)
}
},
{ Log.e("Tutorial", "Query failed", it) }
)
  1. Build and run the application. In your logcat, you'll see an indication that the item was updated successfully:

    Initialized Amplify
    Updated item: File quarterly taxes

Delete a Todo

To round out CRUD operations, we'll query for a record and then delete it from DataStore.

  1. Edit your onCreate() method to remove anything related to DataStore and replace it with the following code:
Amplify.DataStore.query(Todo.class, Where.matches(Todo.NAME.eq("File quarterly taxes")),
matches -> {
if (matches.hasNext()) {
Todo toDeleteTodo = matches.next();
Amplify.DataStore.delete(toDeleteTodo,
deleted -> Log.i("Tutorial", "Deleted item: " + toDeleteTodo.getName()),
failure -> Log.e("Tutorial", "Delete failed.", failure)
);
}
},
failure -> Log.e("Tutorial", "Query failed.", failure)
);
Amplify.DataStore.query(Todo::class.java, Where.matches(Todo.NAME.eq("File quarterly taxes")),
{ matches ->
if (matches.hasNext()) {
val toDeleteTodo = matches.next()
Amplify.DataStore.delete(toDeleteTodo,
{ Log.i("Tutorial", "Deleted item: ${toDeleteTodo.name}") },
{ Log.e("Tutorial", "Delete failed.", it) }
)
}
},
{ Log.e("Tutorial", "Query failed.", it) }
)
  1. Build and run the application. In the console output, you'll see an indication that the item was deleted successfully:
Initialized Amplify
Deleted item: File quarterly taxes

Almost done

We just reached a very cool checkpoint. We have a fully featured CRUD application that saves and retrieves data in the local device, which means the app works without an AWS account and even without internet connection.

Next, let's connect it to AWS and make sure the data available in the cloud.