clusterのAndroidアプリ開発状況2021版

この記事は クラスター Advent Calendar 2021 20日目の記事です。
昨日は、@ryoya_ino の「2021年の振り返りと2022年に向けて」でした。

https://note.com/inotch247/n/na6e684228e54

これで抜粋なんですよねぇ、並べてみると本当にすごい色々イベントやってたな〜と改めて感じます。

このイベントでほしい！と言われた機能を**そのイベントだけで使える機能**ではなく、**プラットフォームの機能として落とし込む**ことはできないか？みたいなのを考えたり設計するのも楽しいし、我々の腕の見せ所って感じですね。
引き続きやっていき！ :muscle: :muscle: :muscle: 

## はじめに
[クラスター株式会社](https://recruit.cluster.mu/engineer/)で、clusterのプラットフォーム事業部に所属しています。
バックエンドServer（Go）とモバイルアプリ(Android)の開発を担当をしているkyokomi（きょこみ）です！！

https://qiita.com/kyokomi/items/67bf126ec0398bc81853

早いもので、この記事（↑）を書いてからもう一年が過ぎているようですね。
「まだ一年なのか〜」という感覚もあり、とても複雑な気持ちになっています。

そんな感じで現状を確認したので、今回は一年経ってclusterのAndroidアプリ開発にどのような変化があったのかなどを紹介をしたいと思います！！

## メンバー構成
3人 -> 4人 :tada:

最近Unityと兼務してくれる人が増えました！が、
現状、4人とも何かしら兼務している状況でAndroidの専任という人はいない状況で、まだまだパワーが不足しています。

引き続き募集しておりますので、[こちら](https://recruit.cluster.mu/engineer/)でテンションをあげてから、[こちら](https://herp.careers/v1/clustervr/iOLOT1x-jBxs)でエントリーをお待ちしてます！！！

## アプリの全体構成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40887/975bb320-56fc-0adb-6789-29abd0baf739.png)

Bridge周りなどは安定していて、ほとんど1年前変わってないです。
細かい機能追加はたくさんあるんですが、以下の主要な機能について紹介したいと思います。

- BackgroundService: メッセージ機能の裏側。WebSoket通信を使ってアプリ起動中にリアルタイムで新着メッセージなどの通知を受け取る仕組みとして導入
- [ピクチャー イン ピクチャー（PIP）](https://developer.android.com/guide/topics/ui/picture-in-picture?hl=ja): Inroomで探索メニュー経由で別のワールドやイベントなどに移動/ポータルの設置などを行う際に利用してます
- [Jetpack Compose](https://developer.android.com/jetpack/compose): 新規で作成する画面は基本的にJetpack Composeを利用して開発しています


### BackgroundService
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40887/b141887c-2f6d-ee4a-80d1-a3f4841128b9.png)

Backgroundで動いているサービスがWebSocket通信を常時行っていて、新着のメッセージがあればRoom Database（SQLite）を更新します。
Messageを表示する画面等は、予めRoom Database（SQLite）からmessage一覧をLiveDataでobserveしてUIを表示しているので、新しいメッセージがきたら反映されるという仕組みになっています。

### ピクチャー イン ピクチャー（PIP）
PiPに関してはAndroid OS標準機能をそのまま使っているだけです。

導入時に困った点としては、PIPモード中というのをProcess1側だけでは判定できず、一定時間おきにProcess２はいまPIPモードか？をRoom Database（SQLite）に書き込んでProcess1に伝えたりしています。

#### それぞれ別で起動したとき。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40887/b8414d24-38db-14b3-c0a9-92a7368dbd3c.png)

#### PIPモードのときにこうなる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40887/7f9f6a2f-46d2-3a4c-345d-7417b6ed571b.png)


### Jetpack Compose
新規で作る画面は基本的にJetpack Composeで組んでいるんですが、次々と「こういう時はどうしたらいいかな？」というのが出てきて、まだまだ模索中という感じです！

以下は、NavHostControllerを使った画面の切り替えなどをどう扱っていくといいかな〜というのを議論したときの図です。
（いい感じの形ができたらまた記事を書きたいと思います）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40887/56202303-6bd5-4ea2-198c-845a6c62d3df.png)

#### 使った感想
リスト表示する画面を実装するのが圧倒的に楽になりましたね〜。
RecyclerViewを設置してViewHolderをつくってうんぬんかんぬんが、コード量1/10くらいになったような感じがします。

あとはViewBinding周りの小難しさというか、コードから切り離されてしまい考えることが増えていた感じがなくなったのも良かったと思います。
ただその反面、ButtonのComponent自体がonClickの処理で特定のActivityをstartしてたりとかしてしまうコードを書けてしまい、そのButtonを配置してる画面からどの画面に遷移するのかが見通し悪かったりします。
この辺はうまいことActivity側などにonClickのcallbackやButtonを押したEventなどをStateFlowなどで渡してやらないとな〜という感じで試行錯誤してます。

## module構成
こちらは、特に変わってないです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40887/59067737-90b6-c685-63d4-c0eef1db27bf.png)

ぼちぼちmodule切り出してもいいかも？みたいな話がちょいちょい出てるんですが（主に自分かもしれないｗ）、チーム構成的にもどういうルールで切り分けるのがベストなのかわかってなくて、踏み出せてないです。

現状だとRoom Database（SQLite）用で用意してるEntityやDaoだけ別のモジュールにして、Databaseのmigrationを安全にしたいな〜とかぼんやりと考えてます。


## ライブラリの利用状況

1年前のbuild.gradleと比較してみました。（以下抜粋）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40887/63ae0005-74c2-6fe2-ad7d-2cbdd125a5d9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40887/914b965c-e70a-5c41-bd2b-7186317a3eea.png)

- compileSdkVersion/targetSdkVersion 29 -> 31
- kotlin 1.4.20 -> 1.6.0
- [Jetpack Compose](https://developer.android.com/jetpack/compose?hl=ja)が導入された :tada: 
- [lottie](https://airbnb.design/lottie/)が導入された :tada: 

### targetSdkVersion 29 -> 31

こちらは、結構苦戦した記憶があります。使っているライブラリが `android:exported` を指定していなくてbuildが通らなくなりました。
`androidx.test:core` あたりが結構色々なライブラリに含まれていたので特に大変でしたね...

https://developer.android.com/about/versions/12/behavior-changes-12?hl=ja

AndroidManifest.xmlをAndroidStudioで開いたときに 以下のMerged Manifestのタブを開くとどのライブラリが原因なのか見つけるヒントになったりします。
あとは `./gradlew dependencies` で、grepして調べたりですかね。。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40887/40339936-74bc-97f2-04e2-9a5105fb038f.png)


## Test/CI

殆どアップデートがないです！!!
現状は、単体テスト（kotlinで完結するロジック）とRoom Databaseのmigrationだけgithub actionsでtestをしてます。

ViewModelのテストやComposeのテストを書いていこうかなとは思っていて、ぼちぼちテストコード増えていくと思いますので来年？をお楽しみください！（どっかでブログとか書くかもしれない）

## おわり
という感じで?怒涛の一年でした。serverの開発が忙しかったりしてなかなかAndroidの開発環境の改善やUIの改善などできてなかったので、2022年は本腰入れて改善していって、開発を加速させていきたいと思ってます！

明日は @compile3 の「仕事内容で振り返るcluster3年の歴史」です！！！