もしあなたが急にAndroidアプリを業務で作るはめになった場合の選択肢(2021年初頭版)


本記事は[Android Advent Calendar 2020](https://qiita.com/advent-calendar/2020/android)の2020/12/01分です。


初っ端ということなので、2020年末と2021年頭でのAndroidエンジニアとして初めて業務でやる場合に抑えておいたほうが良い最低限の部分を書いていこうと思います。（ツッコミ待ちです）

# 対象
- 2021年3月ぐらいまでに **!!業務!!** でAndroidアプリを作らされる事になった可愛そうな人が居たとします
- この人は手続き型言語でオブジェクト指向プログラミングができる知識があり、Androidアプリもなんとなく趣味で作ったこともあるぐらいのレベル感です~~（なので上長からいきなりお前Android担当なと言われた）~~
- 最低限のAndroidアプリの作成の知識はあるものとします（画面の表示にはActivityがいるよとかは書かない)
- ゲームは対象外です
- 業務でAndroidアプリを作ることを想定しています（≠趣味)
- toB toCどちらを作るにしても必要な部分だけの抜粋なので特にtoC向けには不足が多いと感じられる方もいるかも知れません
- あくまでこれから新規に作るアプリの話であり、すでに歴史あるアプリは対象外です

# マルチプラットフォーム対応フレームワークは使わない(絶対に死守しましょう)
もし、Android/iOS両方のプラットフォームでアプリをリリースする必要があったとしても、マルチプラットフォーム対応用フレームワークは使ってはいけません。
ちょっと詳しい上長なんかだと、Flutterがどうだとか、Reactがどうだとか言ってくると思いますが絶対に流されてはいけません。
あれはそれぞれのプラットフォームでの開発のプロが居る上での選択肢なので、急でかつ自分ひとりチームのような場合には絶対に使わないことがおすすめです。
取り敢えずネイティブで作ってみて、自分にAndroidの業務用知識がついてから検討してでも遅くはありません。

もしどうしてもマルチプラットフォームでと強く言われたら、PWA（Progressive Web Apps)に話を持っていきましょう。

# 開発用IDEはAndroidStudio一択(基本使用しましょう)
頑張ればいろいろなIDEや最悪テキストエディタでも開発ができますが、よっぽどマゾな行為が好きなのでなければAndroidStudioのリリース版(2020/12/01時点では4.1)を使いましょう。
ベータやRCは痛くても泣かない人用なので、業務で使うには向いていません。業務ではリリースを使うのが安定です。![スクリーンショット 2020-11-30 18.43.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45441/e3d46df5-3190-9e22-6b05-0447e098d436.png)
あと、一度使い始めたら、新しいリリースがでてもぽんぽんとAndroidStudioをアップデートしてはいけません。
アップデートを適応するとビルドができなくなって泣いている人がtwitterなどで複数観測できます。そういうことです。
アップデート後2,3週間してビルドできない問題などへの知見が貯まってからアップデートするのがおすすめです。


# Min SDK versionは26(基本死守しましょう)
基本Android8以上サポートで仕様を詰めましょう。
最悪Android7.1.1までを死守しましょう。
8未満と8以上でバックグラウンドでのアプリの挙動などに大きな違いがあり、最初から8以上を考えて設計・実装・テストを行えるかどうかで、あなたの3ヶ月後の休日の取得率にダイレクトで影響します。


上から「とはいえ古い端末のユーザーさんが〜」みたいなこと言われたら下記のデータを突きつけて納得させましょう。
![スクリーンショット 2020-11-30 18.40.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45441/52b0dffd-7b7b-f278-4998-197dd4669606.png)
これはAndroidStudioで新しいプロジェクトを作る際に"Help me choose"ボタンを押した場合に見れるデータです。
このデータは海外もあわせているので、古いバージョンの割合が高く出がちです。

説得が難しそうであれば、[スマタブ](http://smatabinfo.jp/os/android/index.html)さんのデータを突きつけましょう。
現時点で8以上のユーザーが83%を超えています。

| Android Version | リリース日 | シェア |
|:-:|:-:|:-:|
|  11 | 2020/09/09  |  2.5% |
|  10 | 2019/09/04   | 38.8%  |
|  9 | 2018/08/07  | 25.0%  |
|  8.1 | 2017/12/06  | 6.2%  |
|  8.0 | 2017/08/22   | 10.6%  |

###### リリースから3年も経ってますし、もう2年縛りで買い替えてますよ〜
###### 古いのを使い続けるのは無理やりスマホにされた高齢者がほぼ全てなので僕らのサービスのユーザーにはマッチしないですよ〜
あたりがオススメのワードです。

高齢者が対象のサービスだった場合には諦めてプロを雇いましょう。

# 開発言語はKotlin(なるべく使用しましょう)
2020/12現在、基本的にAndroidアプリ開発において、Javaでできることはほぼ全てKotlinでもできるのでKotlinを使って開発しましょう。
ネットにあるサンプルコードや情報なんかもKotlinが多いので、使用していて損は全く無いです。

# UIの作成はXMLで（基本使用しましょう)
最近[Jetpack Compose](https://developer.android.com/jetpack/compose?hl=ja)なるコードでUIを作れるツールがでましたが、まだ**Alpha**版です。
![jetpack-compose-hero.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45441/7d77b585-4499-86df-066a-af70fd3008c1.png)

これまでの知見の量や、動作の安定性などを鑑みてもXMLでの作成が安全です。
AndroidStudioで新しいプロジェクトを作成した場合も、まだXMLでのUI作成がデフォルトで行われていますので、長いものには巻かれましょう。


# Android Support LibraryはAndroidXに(絶対に使用しましょう)
2年ぐらい前まではAndroidプラットフォームの複数バージョンでの挙動の統一化などを楽にするためにAndroidSupportLibraryというものがありました。
最近になってAndroidXと名前を変え、AndroidSupportLibraryについてはdeprecatedになったので今後作るものについては基本的にAndroidXを使います。

AndroidStudio4.1で新しいプロジェクトを作ると標準でAndroidXを使ったプロジェクトになります。![スクリーンショット 2020-11-30 21.42.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45441/a8e97aaf-ac7e-e541-4ab3-f3f72e8eb0dc.png)
間違ってもこのチェックボックスにチェックを入れてはいけません。

開発もかなり活発的に行われており、すぐに最新バージョンが変わっていくので下記のリリースノートページをブックマークしておくのがおすすめです。
[AndroidX releases https://developer.android.com/jetpack/androidx/versions](https://developer.android.com/jetpack/androidx/versions)





# ちょっとした非同期処理はKotlin Coroutinesで（基本使用しましょう)
Androidはユーザーの操作感を担保するために、UIを更新するスレッドで重い処理を行ってはいけないという確固たるポリシーがあります。
昔は無視できていたんですが、最近は普通にエラーを出したりするので気をつけます。

- ネットワークアクセス
- DB操作
- 重い計算処理

だいたいここら辺は全部非同期処理にします。

Androidで非同期処理は大昔はThreadとかAsyncTaskでした。

ちょっと前はRxJavaが使われてたように思います。
しかし、RxJavaはRxというかなり特殊で難しい概念を理解しなければならず、また、あとからコードを読んだ際に処理がどう行われていくかがすぐに理解しづらいという問題があります。

なので、よっぽどややこしい事をしたいというのでなければ非同期処理は全部[Kotlin Coroutines](https://developer.android.com/kotlin/coroutines?hl=ja)が良いと思います。

かんたんな使い方は、それぞれのモジュールのbuild.gradleでimplementationします。

```build.gradle
dependencies {
    ~~~~~~
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
    ~~~~~~

}

```

すでに最近のASでプロジェクトを作った場合には、Activityクラスなんかでこんな感じに実行できます。
これでActivityのライフサイクルに合わせて処理のキャンセルなんかをしてくれます（実際には色々とあるのでちゃんと調べて使用するのが良いです）

```MainActivity.kt
    private fun doHoge(){
        lifecycleScope.launch(Dispatchers.IO) { 
            //なにか重い処理
            hoge()
            withContext(Dispatchers.Main){
                // UI操作処理
                updateText()
            }
        }
    }

```

Google公式コードラボをやると結構わかっていいと思います。
[Google公式コードラボ](https://codelabs.developers.google.com/codelabs/kotlin-coroutines/?hl=da#0) 

# APIアクセスはRetrofit2ライブラリで(基本使用しましょう)
AndroidでHTTPアクセスする際に、公式標準APIで[HttpUrlConnection](https://developer.android.com/reference/java/net/HttpURLConnection.html)があります。
しかし、使いづらいのでライブラリを使うのが一般的です。

#### Volley
[https://developer.android.com/training/volley/index.html](https://developer.android.com/training/volley/index.html)

- Android developers公式に載っている
- 歴史があるので知見もネット検索ででてくる

```kotlin
val textView = findViewById<TextView>(R.id.text)
// ...

// Instantiate the RequestQueue.
val queue = Volley.newRequestQueue(this)
val url = "https://www.google.com"

// Request a string response from the provided URL.
val stringRequest = StringRequest(Request.Method.GET, url,
        Response.Listener<String> { response ->
            // Display the first 500 characters of the response string.
            textView.text = "Response is: ${response.substring(0, 500)}"
        },
        Response.ErrorListener { textView.text = "That didn't work!" })

// Add the request to the RequestQueue.
queue.add(stringRequest)
```

[Android Developers Volleyサンプルページ https://developer.android.com/training/volley/simple.html](https://developer.android.com/training/volley/simple.html)から抜粋

#### Retrofit
[https://square.github.io/retrofit/](https://square.github.io/retrofit/)

- Squareが作っている
- 最近の人気
- 基本的にRESTに特化しているのでそれ以外は別のものが必要

```kotlin
private val builder: Retrofit.Builder = Retrofit.Builder().baseUrl("https://www.example.com/")
private val okHttpClient = OkHttpClient.Builder().build()

interface Api {
    @GET("users")
    fun getUser(@Query userId: Long):Call<User>
}

builder.client(okHttpClient).build().create(Api::class.java).getUser(1000).enqueue(object : Callback<User>{
    override fun onResponse(call: Call<User>, response: Response<User>) {
        if(!response.isSuccessful){
            return // エラー
        }
        // 正常処理
    }

    override fun onFailure(call: Call<User>, t: Throwable) {
        // エラー処理
    }

})

```
上記のKotlin Coroutineにも対応していてすごく楽にかける。

```kotlin
private val builder: Retrofit.Builder = Retrofit.Builder().baseUrl("https://www.example.com/")
private val okHttpClient = OkHttpClient.Builder().build()

interface Api {
    @GET("users")
    suspend fun getUser(@Query userId: Long):User
}

lifecycleScope.launch {
    val user = try{
        builder.client(okHttpClient).build().create(Api::class.java).getUser(1000)
    }catch (e:Exception){
        // if(e is HttpException) でエラーハンドリングできる
        return@launch 
    }
    // 処理の続き
}

```

最近人気で知見も多くあるので、RESTでのアクセスなら基本Retrofit2を使えばいいと思います。

# ServiceじゃなくてWorkManagerを使いましょう(可能な限り使用しましょう)
ちょっと前まではアプリがユーザーから見えないタイミングで処理をしたい場合、Serviceを使っていました。
しかし、8以降でアプリのバックグラウンド実行に対してかなり厳しい変更が入ったので今後はSeviceではなくWorkManagerを使いましょう。


ただし、音楽再生のような特定の場合にはServiceを使う必要もあります。

バックグラウンドでの処理については8からの変更が非常に多いので、アプリの設計時に[Guide to background processing](https://developer.android.com/guide/background)を読み込むことを強くおすすめします。


# アプリの設計は公式のアプリアーキテクチャガイドを参考に(可能な限り使用しましょう)
Androidは公式で推奨のアーキテクチャがあります。
公式ページの[アプリ アーキテクチャ ガイド](https://developer.android.com/jetpack/guide?hl=ja)で公開されています。
![final-architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45441/22679a39-54c4-04c8-e2f8-acd174ef7175.png)

非常に凝ったアプリを最初から作らない限り、このページで紹介されているアーキテクチャ（及びライブラリ等)を参考に設計するのが楽でかつ安全だと思います。

# 公式で用意されているアーキテクチャコンポーネントに含まれる便利なクラスたち(可能な限り使用しましょう)
上のアプリ設計にも関係しますが、[アーキテクチャコンポーネント https://developer.android.com/jetpack?hl=ja#architecture-components](https://developer.android.com/jetpack?hl=ja#architecture-components)には非常に便利なクラスが多数含まれているのでどんどん使ったほうがいいです。

その中から使用推奨なものをいくつかピックアップします。

#### ViewModel
昔は何でもかんでも処理をActivity（もしくはFragment）クラスに書いてFatActivityなどという蔑称が生まれていました。
そんな中、今までActivity/Fragmentでやっていたような処理を主に置くためのViewModelクラスという便利なものができたので、処理はそっちに分けていくほうが良いです。

画面の回転などで画面内で保持しておいて欲しいデータなどをonSaveInstanceStateなんかで頑張って保持していたのがそういう事をしなくてよいというメリットもあります。

#### LiveData
自身で値を保持しつつ、Androidの~~ややこしい~~ライフサイクルに合わせて値の更新などを通知してくれる便利なクラスです。
ViewModelクラスとDataBinding機能と組み合わせてAPIの返り値から自動でUIの表示を変えるみたいなことが、少ないコードでわかりやすくかつメモリリークの危険性少なくできます。

#### Room
今までデータの永続化に使っていたSQLiteの代わりとなるORMライブラリです。
裏はSQLiteですが、大体はモダンな感じでSQLを意識しなくていいですし、LiveDataと組み合わせてDBの変更通知を受け取れたりと非常に便利なのでローカルにデータを永続化するなら使って損はありません。


まあ、公式ページのアプリ アーキテクチャ ガイドに沿って設計したら全部使うことになると思います。


# 操作ログはGoogle アナリティクスで(可能な限り使用しましょう)
業務で作るアプリである以上、ユーザーの動向調査は必須機能になってきます。
多様なサービスがリリースされていますが、まずはGoogle アナリティクス(旧Firebaseアナリティクス)でいいと思います。

また、Google アナリティクスは取得したデータをそのままBigquery（高速なデータ基盤)に流すことができるので、Googleアナリティクスを使うなら確実に接続設定をしておいたほうがいいです。

あとから操作ログの検索がしたくなった時の楽さが全然違います。

# Hiltを使ってDI(可能な限り使用しましょう)
AndroidでのDIについては[Hilt https://developer.android.com/training/dependency-injection/hilt-android?hl=ja](https://developer.android.com/training/dependency-injection/hilt-android?hl=ja)というライブラリが登場したため非常に使いだしが簡単になりました。

ちょっと前まではDagger+Dagger Androidサポートみたいなのが多かったですが、使い出すまでに大変だしボイラープレートコードみたいなのを延々と書かないとだめで面倒でしたが、大体そういうのがなくなったので、導入が非常に楽になりました。

なので、DIの概念を理解していて、それに沿った設計とコーディングができるならぜひとも使ったほうがいいと思います。
ただ、まだAlpha版までしか無いので、将来入れることを見越して設計コーディングしつつ、今は入れないという選択肢もあるかと思います。


# アプリのテスト配布はGooglePlayConsoleの内部テストでもOK
アプリがある程度できてきて、社内でドッグフーディング的に使って欲しい時に、アプリをどうやって配布するかという課題があります。
取り敢えずそんなに人数が多くなく、取り敢えず触って欲しいみたいなときにはGooglePlayConsoleの内部テストで配布するのもありだと思います。

もしもうちょっとテスターチームが多いとか、課題が出てきたら[DeployGate https://deploygate.com/](https://deploygate.com/)などを検討してもいいかもしれません。

# HW機能を使うアプリ機能は避ける(なるべく死守しましょう)
HW機能を使うアプリ機能はなるべく初回リリースに含めないか、代替手段で実現できないかを検討したほうがいいです。
AndroidでHW機能（カメラ・Bluetooth・GPS等）を使う場合には非常に落とし穴が多く、手持ちのデバイスで動いたからといって他のデバイス・環境でうまく動くかの保証がしづらいです。
ですので、可能な限り代替の手段で機能を実現できないか検討し、もし無理な場合にはテストのための工数を非常に多く持つ・リリース後の不具合対応のためのリソース調整を行っておくなどの下準備をしたほうが良いです。

# まとめ
- とりあえずAndroidDevelopersの開発者ガイドをくまなく読むのがオススメ


もし今自分が業務として初めてAndroidアプリを作るはめになってしまった時に知りたいであろうことをつらつらと書いてみました。