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

本記事はAndroid Advent Calendar 2020の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
あと、一度使い始めたら、新しいリリースがでてもぽんぽんとAndroidStudioをアップデートしてはいけません。
アップデートを適応するとビルドができなくなって泣いている人がtwitterなどで複数観測できます。そういうことです。
アップデート後2,3週間してビルドできない問題などへの知見が貯まってからアップデートするのがおすすめです。

Min SDK versionは26(基本死守しましょう)

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

上から「とはいえ古い端末のユーザーさんが〜」みたいなこと言われたら下記のデータを突きつけて納得させましょう。
スクリーンショット 2020-11-30 18.40.19.png
これはAndroidStudioで新しいプロジェクトを作る際に"Help me choose"ボタンを押した場合に見れるデータです。
このデータは海外もあわせているので、古いバージョンの割合が高く出がちです。

説得が難しそうであれば、スマタブさんのデータを突きつけましょう。
現時点で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なるコードでUIを作れるツールがでましたが、まだAlpha版です。
jetpack-compose-hero.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
間違ってもこのチェックボックスにチェックを入れてはいけません。

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

ちょっとした非同期処理はKotlin Coroutinesで(基本使用しましょう)

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

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

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

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

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

なので、よっぽどややこしい事をしたいというのでなければ非同期処理は全部Kotlin Coroutinesが良いと思います。

かんたんな使い方は、それぞれのモジュールの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公式コードラボ

APIアクセスはRetrofit2ライブラリで(基本使用しましょう)

AndroidでHTTPアクセスする際に、公式標準APIでHttpUrlConnectionがあります。
しかし、使いづらいのでライブラリを使うのが一般的です。

Volley

https://developer.android.com/training/volley/index.html

  • Android developers公式に載っている
  • 歴史があるので知見もネット検索ででてくる
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から抜粋

Retrofit

https://square.github.io/retrofit/

  • Squareが作っている
  • 最近の人気
  • 基本的にRESTに特化しているのでそれ以外は別のものが必要
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にも対応していてすごく楽にかける。

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を読み込むことを強くおすすめします。

アプリの設計は公式のアプリアーキテクチャガイドを参考に(可能な限り使用しましょう)

Androidは公式で推奨のアーキテクチャがあります。
公式ページのアプリ アーキテクチャ ガイドで公開されています。
final-architecture.png

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

公式で用意されているアーキテクチャコンポーネントに含まれる便利なクラスたち(可能な限り使用しましょう)

上のアプリ設計にも関係しますが、アーキテクチャコンポーネント 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というライブラリが登場したため非常に使いだしが簡単になりました。

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

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

アプリのテスト配布はGooglePlayConsoleの内部テストでもOK

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

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

HW機能を使うアプリ機能は避ける(なるべく死守しましょう)

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

まとめ

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

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

Gazyu
ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
  • 開発言語はKotlin(なるべく使用しましょう)
  • UIの作成はXMLで(基本使用しましょう)
  • Android Support LibraryはAndroidXに(絶対に使用しましょう)
  • ちょっとした非同期処理はKotlin Coroutinesで(基本使用しましょう)
  • APIアクセスはRetrofit2ライブラリで(基本使用しましょう)
  • ServiceじゃなくてWorkManagerを使いましょう(可能な限り使用しましょう)
  • アプリの設計は公式のアプリアーキテクチャガイドを参考に(可能な限り使用しましょう)
  • 公式で用意されているアーキテクチャコンポーネントに含まれる便利なクラスたち(可能な限り使用しましょう)
  • 操作ログはGoogle アナリティクスで(可能な限り使用しましょう)
  • Hiltを使ってDI(可能な限り使用しましょう)
  • アプリのテスト配布はGooglePlayConsoleの内部テストでもOK
  • HW機能を使うアプリ機能は避ける(なるべく死守しましょう)
  • まとめ
  • コメント

    コメント失礼します。最初だとTimber も 入れておくといいかもしれません。

    @shinya-tk

    ありがとうございます!確かにTimberも入れておくといいかもです!ちょっと最近更新が無いので不安なところですが・・・

    @Gazyu
    確かに...更新ないですね(7月が最後)。https://github.com/JakeWharton/timber
    十分に枯れてるとも言えそうですが、もうちょっと機能アップデートしても良さそう..

    @shinya-tk
    あれ。。。最終リリース2018年ぐらいだった気がしたんですが最近アップデートされたんですね

    コメント失礼します。

    Volleyに関しては確か以前にdeprecatedになった気がします。(今はどうかよくわかりませんが)
    https://qiita.com/Reyurnible/items/33049c293c70bd9924ee

    XMLを使った画面UIは機種ごとの挙動の差が非常に大きいのでおすすめできない…(ただし10年前の話)
    Android8以降に絞ったら少しはましになるんでしょうか。

    特にスマフォ~タブレットの表示差が激しかったですね。
    DPI設定が無茶苦茶な機種とか昔は結構あったんですよ。

    結局自前でUIのレイアウトを作るプログラムを書いたほうがマシなくらいでした。

    @hiesiea
    私もその認識だったんですが、少なくとも公式のGuideにまだ載ってるので紹介として入れました。

    @kanryu
    たしかにXMLも初期の頃はだいぶひどかったですね・・・・
    とはいえタブレットはほぼほぼ死滅してしまいましたし、日本国内の公式機種に限って言えばDPI設定が変なのも基本居ないのでXML安定だと思いますよ。

    SDK の組み込み以外だと何か思いつきます?
    https://twitter.com/ttanimichi/status/1333921134857707520?s=21

    @ttanimichi
    SDKの組み込みとかまさにそうだと思います。

    twitterの流れを読みましたが、

    業務でも、まだ失うものがない 0 -> 1 のスタートアップだったら「Flutter で出来ないことは諦める」って割り切って Flutter or die で突き進んでも良さそう?

    これは私も賛成です。
    ただまあ、Androidの知識が十分にあるがFlutterなどの知識がないという前提であればiOSのリリースをせずにAndroidでまずはサービス検証とか言うのも手だと思います。
    やはり自分でもやってみましたがどうしてもそれぞれのプラットフォームのUIのお約束事などをきれいにやろうとするとFlutter/React+Android/iOSの細かい知識とテクニックが必要で、1ソースコードを書けば両方分できるというコストメリットがあまり・・・・という体感でした。

    あくまでここで書いたのは、自分(達)に作るものの生死権限がない人向けという理解でいただけるとありがたいです。

    @Gazyu
    返信ありがとうございます。承知しました。

    もう1点別で気になったのですが、

    ただ、まだAlpha版までしか無いので、将来入れることを見越して設計コーディングしつつ、今は入れないという選択肢もあるかと思います。

    DIのところに関してAlpha版が気になる場合は「Koin」を使うのもひとつ選択肢としてはありなのではないでしょうか(ご存知でしたらすみません)。
    https://insert-koin.io/

    よく使われているライブラリの紹介やアーキテクチャはここ見たらいいという紹介わかりやすかったです!!
    社内でAndroid書いてみたいという人がいたらこの記事一度見てみてと言おうと思いました!

    あと、一意見程度ですが、AndroidDevelopersの一部のCodeLabで一通り学ぶことができるので、それは特筆で言及してもいいかなと思いました😊
    https://developers-jp.googleblog.com/2019/01/android-codelab-courses-are-here.html

    @hiesiea
    はい、DIに関しては理解があるのであればKoinを使うのもありかもです。
    ただ、
    1. 現在GoogleはDagger(及びHilt)をDI使用の場合のスタンダードとみなしている点
    2. AndroidStudio4.2からHiltが公式サポートされると発表済み
    3. AndroidStudio4.2がもう少しでリリースされそう
    ということで、Koinを入れてもコードの修正をまたする可能性が高い&その時はコード全体に及ぶのでコストが高いといった点を鑑みてあえて外しております。

    @muttsu-623
    ありがとうございます。

    確かにCodeLabはかなり便利かつ理解の手助けにすごい役立つので、もう少し言及しても良かったかもです。指摘ありがとうございます。

    @shinya-tk ありがとうございます。普通にリンク構文全部ミスってますね^^;

    リンク切れの修正(私の手元環境だけかもしれません) by shinya-tk 2020/12/02 09:27

    マルチプラットフォーム対応フレームワークは使わない(絶対に死守しましょう)

    なんか極論すぎる気がしますけど・・・
    マルチプラットフォーム対応フレームワークの固有のつらみやできないことはあるのですが、
    ネイティブはネイティブのつらみもあるので
    (OSバージョン依存の実装や機種依存系の実装も含め基本的に自前で全部実装しないといけない)
    要件次第(HW機能が少なかったり)ではマルチプラットフォーム対応フレームワークのほうが工数かからない場合があります。

    (編集済み)

    本当の初心者だと、固有のツラミとか出来ないこと以前に、なんかハマったときにFWの制約なのか自分の書き方の問題なのか判断できないのが困りました
    似たような経緯でAndroidアプリちょっと作りましたけど、欲しかった機能をFWで実装出来るのか出来ないのかもよく分からないのがメンタルに結構来ました
    ネイティブも固有のツラミはありましたが、少なくとも出来る・出来ないの部分で疑心暗鬼にならなかったので、その点気楽だと思います

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

    PWAもっと流行ってほしいですねぇ。

    あなたもコメントしてみませんか :)
    すでにアカウントを持っている方は
    ユーザーは見つかりませんでした