Android App

Example applications are a great way to explore the headless capabilities of Adobe Experience Manager (AEM). An Android application is provided that demonstrates how to query content using the GraphQL APIs of AEM. The AEM Headless Client for Java is used to execute the GraphQL queries and map data to Java objects to power the app.

View the source code on GitHub

Prerequisites

The following tools should be installed locally:

AEM Requirements

The application is designed to connect to an AEM Publish environment with the latest release of the WKND Reference site installed.

We recommend deploying the WKND Reference site to a Cloud Service environment. A local setup using the AEM Cloud Service SDK or AEM 6.5 QuickStart jar can also be used.

How to use

  1. Clone the aem-guides-wknd-graphql repository:

    git clone git@github.com:adobe/aem-guides-wknd-graphql.git
    
  2. Launch Android Studio and open the folder android-app

  3. Modify the file config.properties at app/src/main/assets/config.properties and update contentApi.endpoint to match your target AEM environment:

    contentApi.endpoint=http://10.0.2.2:4502
    contentApi.user=admin
    contentApi.password=admin
    
  4. Download an Android Virtual Device (min API 28)

  5. Build and deploy the app using the Android emulator.

Connecting to AEM environments

10.0.2.2 is a special alias for localhost when using the emulator. So 10.0.2.2:4502 is equivalent to localhost:4502. If connecting to an AEM publish environment (recommended), no authorization is required and contentAPi.user and contentApi.password can be left blank.

If connecting to an AEM author environment authorization is required. By default the application is set up to use basic authentication with a username and password of admin:admin. The AEMHeadlessClientBuilder provides the ability to use token-based authentication. To use token-based authentication update client builder in AdventureLoader.java and AdventuresLoader.java:

/* Comment out basicAuth
 if (user != null && password != null) {
   builder.basicAuth(user, password);
  }
*/

// use token-authentication where `token` is a String representing the token
builder.tokenAuth(token)

The code

Below is a brief summary of the important files and code used to power the application. The full code can be found on GitHub.

Fetching Content

The AEM Headless Client for Java is used by the app to execute the GraphQL query against AEM and load the adventure content into the app.

AdventuresLoader.java is the file that fetches and loads the initial list of Adventures on the home screen of the application. It makes use of Persisted Queries which is pre-packaged with the WKND reference site. The endpoint is /wknd/adventures-all. AEMHeadlessClientBuilder instantiates a new instance based on the api endpoint set in config.properties.

//AdventuresLoader.java

public static final String PERSISTED_QUERY_NAME = "/wknd/adventures-all";
...
AEMHeadlessClientBuilder builder = AEMHeadlessClient.builder().endpoint(config.getContentApiEndpoint());
// optional authentication for basic auth
String user = config.getContentApiUser();
String password = config.getContentApiPassword();
if (user != null && password != null) {
    builder.basicAuth(user, password);
}

AEMHeadlessClient client = builder.build();
// run a persistent query and get a response
GraphQlResponse response = client.runPersistedQuery(PERSISTED_QUERY_NAME);

AdventureLoader.java is the file that fetches and loads the Adventure content for each of the detail views. Again the AEMHeadlessClient is used to execute the query. A regular graphQL query is executed based on the path to the Adventure content fragment. The query is maintained in a separate file named adventureByPath.query

AEMHeadlessClientBuilder builder = AEMHeadlessClient.builder().endpoint(config.getContentApiEndpoint());
String user = config.getContentApiUser();
String password = config.getContentApiPassword();
if (user != null && password != null) {
    builder.basicAuth(user, password);
}
AEMHeadlessClient client = builder.build();

// based on the file adventureByPath.query
String query = readFile(getContext(), QUERY_FILE_NAME);

// construct a parameter map to dynamically pass in adventure path
Map<String, Object> params = new HashMap<>();
params.put("adventurePath", this.path);

// execute the query based on the adventureByPath query and passed in parameters
GraphQlResponse response = client.runQuery(query, params);

Adventure.java is a POJO that gets initialized with the JSON data from the GraphQL request.

RemoteImagesCache.java is a utility class that helps prepare remote images in a cache so that they can be used with Android UI elements. The Adventure content references images in AEM Assets via a URL and this class is used to display that content.

Views

AdventureListFragment.java - when called triggers the AdventuresLoader and displays the returned adventures in a list.

AdventureDetailFragment.java - initializes AdventureLoader and displays the details of a single adventure.

Additional Resources

On this page