Windows から AWS Amplify で Android アプリの作成体験

# 背景
AWS Amplify を使って、GCP からのアプリ移植をやる必要に迫られてきたので学習とその記録

# 自身の状況
- AWS ほぼ初心者。6年ぐらい前に C# でアプリ開発してた環境で少し触った程度
- Web ほぼ初心者。10年ぐらい前に C# でバックエンドの開発に数年関わった程度。
    - 正直、[blazor](https://dotnet.microsoft.com/ja-jp/learn/aspnet/blazor-tutorial/intro) をやりたい・・
- スマフォ 完全初心者

こんな状況でもなんとかするしかない、という危機的状況のおっさん :older_man_tone1: 

# 把握
https://aws.amazon.com/jp/amplify/

まずは、以下動画を見て、なんとなくわかった気になる

https://youtu.be/uRbGMZ9oPjw/

# 準備
## AWS すら素人なので、無償環境を用意
カード入力が嫌だったのでこの手のは自宅ではやらない方針だったんだけど・・諦め :sob: 

https://portal.aws.amazon.com/billing/signup?redirect_url=https%3A%2F%2Faws.amazon.com%2Fregistration-confirmation&language=ja_jp#/start/email

## Windows Terminal インストール
CLI 動かすなら、便利なはず、と

https://learn.microsoft.com/ja-jp/windows/terminal/install


# Amplify でアプリ構築
## 試行を開始
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/49de433e-da79-e8d4-d43a-75c1c7a8925c.png)

- Sample を作成？
    1. アプリタイプを選んで（といっても、二種類しかないが・・
    1. Flamework を選んで
    1. 作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/d09af255-d8c3-a476-e012-cbd065bd6887.png)

- DataModel を作成？ 
    - ToDo 用だから、 Post 1-* Comment って関係もあって理解しやすいね
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/ec3d1121-4443-2abb-eb35-735a72a1e909.png)

## Amplify CLI のインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/ea40fe3c-3eee-89dd-8a1a-8db74def05ae.png)

Amplify CLI インストールの説明は[ここ](https://docs.amplify.aws/cli/start/install/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/b10b7f03-1cff-4c2a-15f2-4cfff88feffd.png)

Windows 版のとこと一緒なので、どちらでもよいのでコピーをして、コマンドプロンプトでインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/3e8cec41-0cd9-fc54-039e-88554f656698.png)

### 動作と version 確認
> amplify -v

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/18190b25-993a-17dd-b272-87d185a3c89b.png)

## pull Data Model
> amplify pull --sandboxId 8c682c7d-f6a9-4f51-85b5-13c351e96231

type は、android を選択して進めたのが以下

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/d62b9b6e-bfd0-1be7-5cc9-0cf9cb320f84.png)

## Install Amplify library and initialize
```gradle: compileOptions build.gradle (Module: app)
    compileOptions {
        // Support for Java 8 features
        coreLibraryDesugaringEnabled true
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
```

```gradle: dependencies build.gradle (Module: app)
    // Amplify plugins
    implementation 'com.amplifyframework:core:1.6.5'
    implementation 'com.amplifyframework:aws-api:1.6.5'
    implementation 'com.amplifyframework:aws-datastore:1.6.5'

    // Support for Java 8 features
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'
```
```gradle: AppCompatActivity (MainActivity.kt)
         try {
            //Amplify.addPlugin(AWSApiPlugin()) // UNCOMMENT this line once backend is deployed
            Amplify.addPlugin(AWSDataStorePlugin())
            Amplify.configure(applicationContext)
            Log.i("Amplify", "Initialized Amplify")
        } catch (e: AmplifyException) {
            Log.e("Amplify", "Could not initialize Amplify", e)
        }
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/f009ee4d-4cbc-d38c-0d47-ca3c6a02d349.png)

## test CRUD

```gradle: Create 
val item: Post = Post.builder()
    		.title("Lorem ipsum dolor sit amet")
		.comments([])
		.content("Lorem ipsum dolor sit amet")
                .build()
Amplify.DataStore.save(
        item,
        { success -> Log.i("Amplify", "Saved item: " + success.item().name) },
        { error -> Log.e("Amplify", "Could not save item to DataStore", error) }
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/008d32ad-56c3-38a8-fdee-dfb8cf19d474.png)

で、Dploy o AWS へと進む

## アプリの作成?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/4114dd18-a329-c29d-65eb-d8c3be5bc1f3.png)

- アプリケーション名を入力
- リージョン選択
で、Confirm Deployment 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/95d89405-caa2-efb4-20ee-7ea93e785927.png)

こんな感じで進んでいって
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/1302202e-5245-3ae6-36f9-f24e6331d2ab.png)

暫し待つと完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/d5fe95ac-66b1-ded8-896c-fc33d0061d96.png)

右上のアクションで、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/9288a525-fa8d-54a4-46a3-2710a49569f6.png)

- アプリ設定
    - リポジトリの再接続
    - 環境の追加
- 削除
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/eb0ebd27-70ec-eb98-f1dc-74eb1f137b45.png)

右下のアクションで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/e3514336-f99d-581d-826c-bdd9d4ccea2e.png)

- Studio を起動する<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/3c244542-837d-ce53-4a73-5cb5d5a8c2b0.png)
- 詳細を表示<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/f76ae7bb-ce3c-7dbf-89d7-8336a6ca7ce6.png)
- クローンを作成
- 削除

この先 Authentication と UI を設定すると完成？

なんかよくわからないので、立ち止まったら、チュートリアル発見・・ :sob: 

チュートリアルやり直してみよう

# チュートリアル
https://aws.amazon.com/jp/getting-started/hands-on/build-android-app-amplify/?trk=gs_card

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/186cdbd1-7dab-676f-b1bf-017d0c1b532b.png)


## 前提条件が違うことを踏まえて・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/7ae8c40d-93f0-ebad-21e4-6e35ecc42f7d.png)

Windows でもだいたい同じでしょと信じて

項目は以下
## Android プロジェクトを作成する
### Android Studio インストール
やっぱり必要なのね、ということで、準備。

https://developer.android.com/studio/install?hl=ja

### 新規プロジェクト作成
チュートリアルの指示に従って
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/88fe64cf-1aef-fbf7-dffb-4f9a7ed7f093.png)
Basic Activityで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/68905b10-3e0e-0517-f589-ae1abf4bbed4.png)
Default の Kotlin のままで、Project Nameをチュートリアルのままにつけて
Minimum SDK も指示通り 8.0 にして Finish
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/0dd5f1e8-d073-a736-e96f-fd778c7005f0.png)
暫く待つと完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/fa5a3989-d056-1ce9-9dfe-b198431d732f.png)

### IDE のエラー対処
起動直後以下エラーが出てるが、色々DLしてるので、暫く待機
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/0784dbc4-20c2-bc50-5d08-73dea1da1810.png)

Firewall 系は適宜対処

再起動したら、一応全部消えてたので良しとする

## 不要なファイルを削除して、プラグインを追加する
Kotlinのプラグイン追加だけ対処
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/0584154c-9597-6e45-33fa-b952c929d79b.png)

## UserData データクラスを作成する
チュートリアルに従って、新規Class File を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/977c0460-a1a0-fa15-c9f5-ea7f78cabad4.png)
UserData として
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/50fa93cc-b566-1774-5161-5ed2f282d52c.png)

:::note info
Singleton として object 定義にしたので、以下のアイコン変化が出る
class 青アイコン ⇒　object 橙アイコン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/051d8de4-02f4-c4de-c6a2-5507c0f09fbc.png)
:::

## リストの各セルにGUIを追加する
指示通り リソースファイルを content_note として作成

で、コードを貼り付けるとこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/a6670ecf-ea09-eea0-950f-40f5a918f0ad.png)

NoteRecyclerViewAdapter も指示通り作成

::: note info
Desing → Code View の変更はこことかで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/9065bb96-18d2-3ede-e31f-857560e74a7f.png)
:::


::: note warn
ファイル名コピーの際に、半角空白等を入れると、以下のようなメッセージが出て作れない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/db6d3574-82b5-5bc4-54a1-83ce3bfccb00.png)
:::

## メインアクティビティを更新する
指示通り MainActivity を更新すると・・以下のようにエラーになる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/face8ea9-d2d9-3bd8-e51b-3038ca2707e2.png)
エラーは以下四件
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/2694515e-9187-044c-95ce-23e2c6822566.png)

### MainActivity.kt のエラー：kotlinx.android.synthetic が廃止されている・・
チュートリアル放置されてるのね :laughing: 

https://developers-jp.googleblog.com/2020/11/the-future-of-kotlin-android-extensions.html

ってことで、回避策は、以下を使ってやればよさげ

https://developer.android.com/topic/libraries/view-binding?hl=ja

具体的には
1. build.gradle の修正<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/ec1ff1ed-8ee7-90f0-7034-61372874f0d4.png)
1. build.gradle(app)に追加した定義も削除<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/348db76d-c352-8ad9-799a-01810a13049b.png)
1. MainActivity.kt での参照方法の変更
変更してみたのが以下

```kotlin: MainActivity.kt 改修版
package com.example.androidgettingstarted

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.example.androidgettingstarted.databinding.ActivityMainBinding
import com.example.androidgettingstarted.databinding.ContentMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var rootBinding: ActivityMainBinding
    private lateinit var contentMainBinding: ContentMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        rootBinding = ActivityMainBinding.inflate(layoutInflater)
        contentMainBinding = ContentMainBinding.inflate(layoutInflater)

        setSupportActionBar(rootBinding.toolbar)

        // prepare our List view and RecyclerView (cells)
        setupRecyclerView(contentMainBinding.itemList)
    }

    // recycler view is the list of cells
    private fun setupRecyclerView(recyclerView: RecyclerView) {

        // update individual cell when the Note data are modified
        UserData.notes().observe(this, Observer<MutableList<UserData.Note>> { notes ->
            Log.d(TAG, "Note observer received ${notes.size} notes")

            // let's create a RecyclerViewAdapter that manages the individual cells
            recyclerView.adapter = NoteRecyclerViewAdapter(notes)
        })
    }

    companion object {
        private const val TAG = "MainActivity"
    }
}
```

無事エラーは消去
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/3e2a71c8-6689-22f5-d0f4-82e713b27765.png)

## ビルドの依存関係を検証する
ん－、チュートリアル自体が古いから、ここはパス

https://developer.android.com/studio/build/dependencies?hl=ja#:~:text=%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E4%BE%9D%E5%AD%98%E9%96%A2%E4%BF%82%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%E3%80%81%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%AE%20build.gradle%20%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE,dependencies%20%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%81%A7%E3%80%81%20implementation%20%E3%81%AA%E3%81%A9%E3%81%AE%E4%BE%9D%E5%AD%98%E9%96%A2%E4%BF%82%E3%82%B3%E3%83%B3%E3%83%95%E3%82%A3%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

## ビルドとテスト
Run (Shift + F10) で実行してみると・・
無事動いたけど、最初の段階なので全く面白みもない :sob: 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/54891f90-d9a2-40ba-ccf9-47127b80e01e.png)

# あとがき
今日の収穫
- Windows でもチュートリアルを進められそう
- Android Studio を初めて使ってみて、VS 並みに使いやすそうだと実感
- チュートリアルが古くても、広い意味で同じソフトウェアだし、公式ドキュメントが詳しいのでなんとかなる

また週末に、モジュール２をやろう

https://aws.amazon.com/jp/getting-started/hands-on/build-android-app-amplify/module-two/

前提条件にあるものを何一つ満たしていないこともあったけど、10分じゃ初心者には出来ませんでした。
分かっててサクサク実施するならいけるんでしょうけど、初心者にとっては何故？っていう疑問が沢山あるので :laughing: 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/e490bebc-930e-fa9f-063a-8ce04c07e6b7.png)