Skip to content

Instantly share code, notes, and snippets.

@jamesonwilliams
Last active March 4, 2021 21:58
Show Gist options
  • Save jamesonwilliams/d3344008eebcb46ee7774ad33ac6ef6c to your computer and use it in GitHub Desktop.
Save jamesonwilliams/d3344008eebcb46ee7774ad33ac6ef6c to your computer and use it in GitHub Desktop.
Using AWS AppSync with Apollo Android 2.2.0

Hitting AWS AppSync from Apollo Android 2.2.0

This document describes howto setup an AppSync endpoint, and talk to it using the Apollo Android 2.2.0 client.

Deploy an AppSync endpoint

In the AWS AppSync console, I created a new endpoint here, by selecting the "Event app" under "Start from a sample project."

Under the Settings tab, I make note of the URL for the endpoint, and its API key. I use these in the MainActivity.kt, below.

Under the Schema tab, I download schema.json and include it into a fresh, Kotlin-based Android project.

Client Setup

For the most part, I follow the instructions in the Apollo README.md.

I create two additional files, CreateEvent.graphql, and ListEvents.graphql. For the timebeing, I write these by hand, as:

mutation CreateEvent {
  createEvent(
    name: "My First Event"
    when: "Today"
    where: "My House"
    description: "Very first event"
  ) {
    id
    name
  }
}
query ListEvents {
  listEvents {
    items {
      id
      name
    }
  }
}

Sample Code

MainActivity.kt:

(Be sure to update the endpoint URL and API key.)

package apollo.sample

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity

import apollo.test.CreateEventMutation
import apollo.test.ListEventsQuery

import com.apollographql.apollo.ApolloClient
import com.apollographql.apollo.rx3.rxMutate
import com.apollographql.apollo.rx3.rxQuery

import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers

import okhttp3.OkHttpClient

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        tryItOut()
    }

    private fun tryItOut() {
        createClient()
            .flatMapCompletable { client ->
                createEvent(client)
                    .andThen(listEvents(client))
            }
            .subscribeOn(Schedulers.io())
            .observeOn(Schedulers.io())
            .blockingAwait()
    }

    private fun listEvents(client: ApolloClient): Completable {
        return client.rxQuery(ListEventsQuery())
            .doOnNext { response ->
                response?.data?.listEvents?.items?.forEach { item ->
                    Log.i("Apollo", "Found an item: $item")
                }
            }
            .doOnError { failure ->
                Log.w("Apollo", "Failed to list items.", failure)
            }
            .ignoreElements()
    }

    private fun createEvent(client: ApolloClient): Completable {
        return client
            .rxMutate(CreateEventMutation())
            .doOnSuccess { response ->
                Log.i("Apollo", "Created an event: $response")
            }
            .doOnError { failure ->
                Log.w("Apollo", "Failed to create an event.", failure)
            }
            .ignoreElement()
    }

    private fun createClient(): Single<ApolloClient> {
        return Single.just(ApolloClient.builder()
            .serverUrl("https://alphanumeric-string-here.appsync-api.us-east-1.amazonaws.com/graphql")
            .okHttpClient(OkHttpClient.Builder()
                .addInterceptor { chain ->
                    chain.proceed(chain.request().newBuilder()
                        .addHeader("X-API-Key", "da2-alphanumeric-string-here")
                        .build())
                }
                .build()
            )
            .build())
    }
}

In my project-level build.gradle, I have:

buildscript {
    ext.kotlin_version = "1.3.72"
    
    repositories {
        google()
        jcenter()
    }
    
    dependencies {
        classpath "com.android.tools.build:gradle:4.0.0"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

In my app-level build.gradle I have:

plugins {
    id("com.apollographql.apollo").version("2.2.0")
}

repositories {
    jcenter()
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.apollographql.apollo'

android {
    compileSdkVersion 29

    defaultConfig {
        applicationId "apollo.sample"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    
    implementation 'androidx.core:core-ktx:1.3.0'
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

    implementation 'com.apollographql.apollo:apollo-runtime:2.2.0'
    implementation 'com.apollographql.apollo:apollo-rx3-support:2.2.0'
}

apollo {
    generateKotlinModels.set(true) // or false for Java models
}

Output

After I run the above code a few times, I see this output in logcat:

I: Created an event: Response(operation=apollo.test.CreateEventMutation@1302b72, data=Data(createEvent=CreateEvent(__typename=Event, id=00c8731b-9fc6-468f-89ce-92ddbaef0963, name=My First Event)), errors=null, dependentKeys=[], fromCache=false, extensions={}, executionContext=com.apollographql.apollo.http.OkHttpExecutionContext@aeb6bc3)
I: Found an item: Item(__typename=Event, id=00c8731b-9fc6-468f-89ce-92ddbaef0963, name=My First Event)
I: Found an item: Item(__typename=Event, id=94c76e2a-191f-45da-bf22-bce7740b2429, name=My First Event)
I: Found an item: Item(__typename=Event, id=0415f4ee-b057-4eb0-ae8c-a0d3fa6ccfeb, name=My First Event)
I: Found an item: Item(__typename=Event, id=35cd28d0-b732-4be6-8805-3a5b0d664d5f, name=My First Event)
I: Found an item: Item(__typename=Event, id=1999bfb5-ad32-43de-a204-ac01b81a374d, name=My First Event)
@jamesonwilliams
Copy link
Author

jamesonwilliams commented Jun 16, 2020

Open questions

WebSocket subscriptions?

Supply a WebSocketSubscriptionTransport or custom implementation via the ApolloClient builder's subscriptionTransportFactory(...) builder method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment