DMM.com Advent Calendar 2018 9日目の記事です。
動画サービスのAndroid系の動画プレイヤーを開発しているエンジニアで、@pinkienortです。今年2018年に入社し、Android開発を初めて約5ヶ月になりました。
ひょんなこと(↓の理由)から、AppSyncのを使うことがあったので、Androidでの使い方をざっくり紹介したいと思います。
経緯: Amazonアプリの公開で困った
DMMの動画サービスでは、動画視聴プレイヤーとして数多くのでデバイをサポートとしています。Android/iOS系のスマホや、レグザやブラビアなどテレビ、PS4などなどあります。
そのデバイスの1つAmazon FireTVもあります。そんなFireTV向けのアプリを公開するときに、次のエラーが出くわしました。
Caution: Google Cloud Messaging Detected
(えー。gcm使っちゃだめなのー。)
調べたところ、、、
Migrating An Existing App to the Amazon Appstore | Appstore Submission
↑の理由から、Amazonアプリストアでアプリを公開するときに、ワーニングが表示され、審査が思うどおりに進まない!ということがあったので、AppSyncを使うことになりました。
本題: AndroidでAppSync
AppSyncはAWSの1つで、GraphQLでAPIを記述し、バックエンドとしてLambdaやDynamoDBなどに接続できるようになってます。今回はDynamoDBを想定して進めていきます。
API/GraphQL作成
では、実際に作っていきましょー。
AWSのコンソールからAppSyncのダッシュボードに移動します。次にCreate APIをクリックすると、作成画面になります。今回はBuild from scratchを選択します。
これでAPIが作成できました!、、、が、肝心のAPIを呼び出すGraphQLがありません!なので、データを取得するQueryやデータを作成するMutationやデータそのものを定義するスキーマを作成していきます。
左側のメニューからSchemaを選択すると、何も定義されてないスキーマファイルが出てきます。
Create ResourcesからDyanamoDBのテーブルとスキーマの両方を作成します。
ここでは、データ型を1つ定義する(例ではMyCustomType
)と、それに対応するテーブルが作成できます。さらに、そのテーブルにアクセスするためのGraphQLが自動生成されます(Query, Mutation, Subscription)。
ページ下部にあるCreateを押すと、定義したデータ型に対応するDynamoDBのテーブルと、そのデータ型のMutationやQuery, Subscriptionも自動生成されます。
Android Proejctのセットアップ
セットアップを始める前に、configファイルをダウンロードします。
左メニューから、名前をつけたAPIのアイテムをクリックすると、Getting startedが表示されます。そして、Download Configurationからawsconfiguration.json
をダウンロードして、./app/src/main/res/raw
に置いておきます。
AppSyncのコンソールの指示に沿って、AWS Amplifyの設定をします。
AmplifyがWeb上からAppSyncの設定データを取得するために、Amplify用のユーザを作成するように言われるので、そのまま従ってください。
ユーザ作成が完了したら、Webに表示されるaccessKeyId
とsecretAccessKey
をコンソールに入力して、Enterを押して進めばユーザが作成されます。
npm install -g @aws-amplify/cli
cd <Android Projectのrootディレクトリ>
amplify init
GraphQLをAndroid側で使用できるようにするため、コード生成します。このときに、AppSyncのWEBコンソールで作成したSchemaを元にGraphQLのクエリ(Schemaファイルにあるtype Query
でない)が自動で生成されます。
amplify add codegen --apiId <API_ID>
最後に、Androidのビルドコンフィグにライブラリを追加すれば、セットアップ完了です。
classpath 'com.amazonaws:aws-android-sdk-appsync-gradle-plugin:2.6.+'
apply plugin: 'com.android.application'
apply plugin: 'com.amazonaws.appsync'
android {
// Typical items
}
dependencies {
// Typical dependencies
implementation 'com.amazonaws:aws-android-sdk-appsync:2.6.+'
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.0'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
}
Androidで動かす
ようやく疎通チャレンジです。
まず、AppSyncのクライアントインスタンスを生成します。認証やリージョンなどの設定として、ダウンロードしたコンフィグファイルを読み込ませます。
import com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient
import com.amazonaws.mobile.config.AWSConfiguration
lateinit var appSyncClient: AWSAppSyncClient
private fun initAppSyncClient() {
appSyncClient = AWSAppSyncClient.builder()
.context(applicationContext)
.awsConfiguration(AWSConfiguration(applicationContext))
.build()
}
クライアントの生成後に、query
を実行してデータを取得します(builder
では、limit
やfilter
で取得数を制限したり、で特定のものだけ取ってきたりするカスタマイズがデフォルトで生成されています)。エラーがでなければ、ログに取得したデータが吐き出されます。response.data
にnextToken
も入ってるので、追いロードもできます。
import com.apollographql.apollo.exception.ApolloException
import com.amazonaws.amplify.generated.graphql.ListMyCustomTypesQuery
import com.apollographql.apollo.GraphQLCall
import com.amazonaws.mobileconnectors.appsync.fetcher.AppSyncResponseFetchers
import com.apollographql.apollo.api.Response
import android.util.Log
private fun query() {
appSyncClient.query(ListMyCustomTypesQuery.builder().build())
.responseFetcher(AppSyncResponseFetchers.CACHE_AND_NETWORK)
.enqueue(listMyCustomTypeCallback)
}
private val listMyCustomTypeCallback = object : GraphQLCall.Callback<ListMyCustomTypesQuery.Data>() {
override fun onResponse(response: Response<ListMyCustomTypesQuery.Data>) {
Log.i("Results", response.data()?.listMyCustomTypes()?.items()?.mapNotNull {
it -> it.content()
}?.joinToString())
}
override fun onFailure(e: ApolloException) {
Log.e("ERROR", e.toString())
}
}
query
だけではデータ作成していないため、空データが返却されます。
mutation
でデータを作成しましょう。データ作成できれば、id
が出力されます。
import com.apollographql.apollo.exception.ApolloException
import com.amazonaws.amplify.generated.graphql.CreateMyCustomTypeMutation
import com.apollographql.apollo.GraphQLCall
import com.amazonaws.mobileconnectors.appsync.fetcher.AppSyncResponseFetchers
import com.apollographql.apollo.api.Response
import android.util.Log
import type.CreateMyCustomTypeInput
private fun mutation() {
appSyncClient.mutate(CreateMyCustomTypeMutation.builder().input(
CreateMyCustomTypeInput.builder()
.content("cola")
.price(120)
.title("My custom Title")
.build())
.build())
.enqueue(createMyCustomTypeCallback)
}
private val createMyCustomTypeCallback = object : GraphQLCall.Callback<CreateMyCustomTypeMutation.Data>() {
override fun onResponse(response: Response<CreateMyCustomTypeMutation.Data>) {
Log.i("Results", response.data()?.createMyCustomType()?.id())
}
override fun onFailure(e: ApolloException) {
Log.e("ERROR", e.toString())
}
}
}
おわりに
今回紹介では、AppSyncでAPIを作成してAndroidから動かしてみる!でした。AppSyncはバックエンドとしてDynamoDB以外にもLambdaがあり、認証方法もAPI_KEYだけでなく、CognitoやIAM、OpenIDも利用できます。
次はそちらも紹介できればと思います。