【Flutter×Firebase】東海オンエア好きすぎて聖地マップ共同作成アプリ作った話【個人開発】

## はじめに
Flutter初心者がクロスプラットフォームでアプリ作りたくなったのでFlutterを0から勉強しながら作ったアプリを使用技術とともに紹介してみる記事です。

## アプリ作りました！

iOS/Androidアプリ、**「TokaiGo！」**をリリースしました。
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/db7a850b-fe91-17e4-f7eb-68d58d11b8ef.png"><img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/367cb20f-4ab2-95e4-9003-89e8818cfdbe.png">

[**TokaiGo!(iOS版)**](https://apps.apple.com/jp/app/TokaiGo!/id1601486685)
[**TokaiGo!(Android版)**](https://play.google.com/store/apps/details?id=tokai.go.app)

東海オンエアファンの東海オンエアファンによる東海オンエアファン向けの**聖地巡礼マップアプリ**です。
東海オンエアのYoutube動画に出てきた場所を、そのYoutube動画と共に地図上で**閲覧**することができます。
また、未登録の場所があればYouTube動画と紐付けて**登録**することができます。

## アプリの発端
### きっかけ
東海オンエアが大好きなので毎日のように動画を見ているのですが、その中でメンバーの一人であるりょうが「ファンがメンバーの位置が近づくと通知をくれる、メンバー発見アプリ」を作るのはどうか、という提案をしていました。
さすがに動画内では却下されてましたが、**「岡崎を訪れるほどの東海オンエアファンが楽しめるアプリ」**という点から着想を得ました。

https://www.youtube.com/channel/UCutJqz56653xV2wwSvut_hQ

### アプリの具体化
**「岡崎を訪れるほどの東海オンエアファンが楽しめるアプリ」**として思いつくのが、**「聖地マップ」**。

岡崎に行ったとしてもどこをどう回ればいいとか、そもそもどの場所がどの動画の場所でどの場所を回ればいいとか、そういうのを全て個人で調べるのは大変。
だからマップあった方がいいよね！

でもそれだと開発者がデータ入れるの大変。
だったら**ファンみんなで完成させていけばいいじゃないか！**

というわけで、マップ上に東海オンエアの聖地を動画のリンク付きで投稿して、**ファンみんなで聖地マップを作れるアプリ**を作ろうと考えました。

ちなみに、初期データとして以下の場所を投入しています。

https://www.okazaki-trip.com/entry/osusumebetsu

https://yamucollege.com/entry/tokaionair-okazaki-spot-root/

## 使用技術
アプリ側の実装として、クロスプラットフォームであるFlutterを利用。
また、バックエンドの処理はFirebaseを利用。

### Flutter(for App)
元々はSwiftでiOSアプリ開発を行なっていたが、せっかくなのでAndroidアプリも作成しようと思い
クラスプラットフォームフレームワークの中から選択。

Flutterに決めたのは、オリジナルUIを使っていて**AndroidとiOSで見た目が変わらない**という点からだ。
自分が業務で用いているのは`Vue.js`なので、`Vue Native`を採用しようか迷った。
ただしこちらはより新しいフレームワークで**情報が少なそう**であったので、最終的には`Flutter`を採用。
(自分が業務で`React`を用いていたら、`React Native`を利用していたかもしれない)

> [クロスプラットフォームフレームワーク比較 2022（Flutter, React Native, Xamarin, Unity）](https://qiita.com/nskydiving/items/c13c949cc17c6f980a67)


### Firebase(for BackEnd)
Flutter開発のバックエンドを調べていると、大体Firebaseとの連携方法を教えてくる。
本当はAWSのAPIGateWayとLambda使ってAPI作ったりしてもいいかもと思ったが、Flutterへの導入のしやすさとユーザ認証の設定の簡単さ、という点でFirebaseを選択。

> 検討材料：
> [あなたに最適なmBaaSはどれ？AWS Mobile HUB / Firebase / ニフクラ mobile backend 三社を比較検証！](https://press.monaca.io/atsushi/2667)
> [サーバーレスで作るモバイルアプリ向けBackend For Frontend](https://pages.awscloud.com/rs/112-TZM-766/images/G-2.pdf)

最初は以下の記事に書いたように、本を一冊買って勉強した。

https://qiita.com/ninoko1995/items/722ae744c853e087f267

ただ、FirebaseだとDatabaseがNoSQLで検索に激弱で実装できる機能が制限されてしまうため、将来的には構成は要検討。

### 外部サービスたち
`Twitter Developer Platform`: Twitter連携ログインのため

https://developer.twitter.com/en


`Google Cloud Platform`: `Youtube api`/`google map api`の利用、googleアカウント連携ログインのため

https://cloud.google.com/gcp/?utm_source=google&utm_medium=cpc&utm_campaign=japac-JP-all-en-dr-bkws-all-all-trial-e-dr-1009882&utm_content=text-ad-none-none-DEV_c-CRE_540823009828-ADGP_Hybrid%20%7C%20BKWS%20-%20EXA%20%7C%20Txt%20~%20GCP%20~%20General_%20Core%20Brand-KWID_43700063054080148-kwd-26415313501-userloc_1009282&utm_term=KW_google%20cloud%20platform-ST_google%20cloud%20platform&gclid=CjwKCAiAo4OQBhBBEiwA5KWu_34HvIXF3B36i97Mq5NyPIdp6MqlPe7nA_b4Bb3xZrFgDBDgCR5DtBoC0i4QAvD_BwE&gclsrc=aw.ds

## 機能

東海オンエアのYoutube動画に出てきた場所と紐付いたYoutube動画を**地図上で閲覧**
未登録の場所があればYouTube動画と**紐付けて登録**

### 地図と連動する聖地情報!
東海オンエアの聖地が、マップ上でマーカー表示されます。
また、画面上部の詳細表示窓をスライドすることで、マップもそれと共に連動して動きます。
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/c38eeabf-45c3-2a74-fa6a-daecea214c6b.png">

### リスト形式でも確認可能！
詳細全文を見比べたいときはリスト表示に切り替え可能！
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/59519071-a080-6b79-7b00-9dd4ae473b55.png">

### 撮影されたYouTubeの動画もわかる！
聖地詳細画面では、その場所で撮影された動画を確認できたり、聖地のお気に入り・行きたいリスト登録などができます。
<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/4faa62c1-fbe0-89a1-1488-9d1cd95cdf86.png">

###グルーピングが可能!
「行きたい」「お気に入り」などでグルーピングした聖地は、マップ上やリスト上で簡単に確認できます！
<img width=230 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/31fb71fd-2b19-ad92-3354-accb3bb0ac5c.png"> <img width=230 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/ec5b2a8e-e8c4-d01d-419e-10d5ae470602.png"> <img width=230 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/2f6f63de-31cb-1fdd-b6e0-fac8407aec72.png">

### 自分で聖地を登録できる！
まだ登録されていない聖地があったら、自分で登録しましょう！
聖地名から住所を選択し、動画名からYouTube動画を検索して紐づけることができます。

<img width=230 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/ddef3826-0311-ac3a-2377-02156635c49d.png"> <img width=230 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/fc37577a-4bf2-6f4f-4b2c-81811f664f71.png">　<img width=230 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/c6385ac5-1840-b14b-1828-657e3d9c782a.png">

## 第一弾リリースで実装しなかった機能
### スポットへのコメント機能
**実装コストがかかりそう**だったので、優先度をさげ第一弾リリースからは除外。
スポットの詳細表示画面のUIをきちんと考えてコメントを表示する場所が見つかれば、実装するかも。
YouTubeアプリのようにデフォルトだと折り畳まれる状態にしておく、とかだと良いかも？

### 聖地の新規登録数によるユーザランキング機能
**アイデアの煮詰めが甘く**、実装まで行けず。

表題の機能に限らず、**ユーザが自発的に聖地を登録してくれる機能**を追加したかった。
そもそもユーザが聖地を登録できるようにしたのには、以下の理由から自分で全部データを用意するのは大変かと思ったからだ。

- 現時点でメインチャンネル・サブチャンネル合わせて投稿動画数は4000本を超えており、単純に考えると**4000以上の聖地**が存在している。
- 東海オンエアはメインチャンネル・サブチャンネルで毎日のように動画を投稿しており、それに伴い聖地も**毎日のように増加**している。

ゆえに、ユーザが自発的に聖地を登録してもらえるように、何かしらのゲーミフィケーション要素を加えたかった。

第一弾リリースでは**ユーザ登録機能のみ追加**しており、誰がどの聖地を登録したかを記録はしている。
今後のリリースで、そのデータを持ちいてどのように登録モチベーションを上げさせるか、という点を考え実装していく。

### 非登録者の聖地編集機能
本アプリでは、荒らし対策として**聖地は聖地を登録した人しか編集できない**ようになっている。
そのため、すでに登録された聖地で撮影された他の動画があった場合に、その動画を誰でもその聖地に紐付けることはできない。
ただしそれだと完璧な聖地マップは作れない。
うまいこと**荒らし対策と利便性の妥協点**を探っていきたい。

### 広告表示・課金
第二弾リリースで導入予定。
まずは　MVP(Most Valuable Product)として、機能のみを実装したものをリリースしてみる。

## 大変だったこと
### 構成面
**状態管理パターンの大切さ**
本で勉強したサンプルアプリをそのまま発展させ、状態管理に関して深く勉強せずに作ってしまったので、コードが煩雑となってしまっている。
現状は`StatefulWidget` + `provider` + `repository`パターンとなっている。
本当は`state_notifier` + `riverpod` + `repository`パターンにしたい、今となっては。
が、書き換えは大変だから多分しない。。

### 実装面
苦労したポイントを一応箇条書きで書いておく。
ここら辺の話題もそのうち記事にするかもしれない。

- google map上の吹き出しと画面上部のカルーセルの動きを合わせる部分。
- google map apiを利用して場所のplaceIdなどを取得する部分。
- YouTube apiを利用して東海オンエアのチャンネルから動画を検索する部分。
- Flutterのstableなchannelを使ってなくて、リリース用のbuildでエラーが何度も発生したこと。

## 気づいたこと・やってよかったこと
**噂通りgogle審査ゆるい**
初・Android版のアプリリリースであったが、Appleの方でリジェクトされたデータもGoogleの方ではリリースできたりして、審査の緩さを実感。

**Flutter + Firebaseがめちゃ簡単**
FirebaseとFlutterの親和性が高い。サクッと動くコードが書ける。
また、各種ユーザ認証もお手軽に実装できて便利！

**Packageのソースコード読む**
READMEが充実しているパッケージならそれを読めば導入までは簡単。
できるだけそういうものを使う。
処理の意味がわからなくて困ったら、定義に飛んでコード読めば何やりたいのかがわかる。
使い方を紹介している記事を探すばかりでなく、**自分でコード読む意識大事**だと思った。

**Packageのカスタマイズ**
コード読んでみて、**足りないものがあったら作っちゃおう**。
YouTubeAPIにアクセスして動画を検索するパッケージを用いていたのだが、APIには実装されているのにそのパッケージでは実装がなされていない機能があった。
実際にその機能を実装してGithubレポジトリにPRを作っておいたが、未だ更新されていない。
詳細は以下。

https://qiita.com/ninoko1995/items/ec7c286df3dac2af2958

**プロジェクト管理大事**
会社でのプロジェクトと同じように、要件の洗い出し・機能の優先度付け・実装・進捗確認を行っていくと良い。

- 作業の効率化
    - 行動の目的が意識できるので、個人開発でありがちな「なんとなく関係してそうな記事読んでる」という時間がなくなる。
    - 「何やればいいか分からない」といった無駄な時間がなくなる。
- モチベーションの維持
    - 今日はこれだけはやろう、と思えて中弛みしにくくなる。
    - 終了タスク残タスクが見えると、やる気が出る。


個人プロジェクト用にJIRAも導入しようと試みたが、デザインなども同時に管理したかったので紙のノートを一冊個人開発用に作成した。


## 今後の展望
まずは以下の機能実装リリースしていきたい。

- 非登録者の聖地編集機能
- ゲーミフィケーション要素
- 広告・課金

また、そのためにデータベース周りの仕組みをもう少し考えて改善していきたい。


## 最後に
とりあえずのお試しでFlutterとFirebaseを使って作ってみて、便利だったこと大変だったことがわかった。
次は最初からデザイン・設計・構成などをちゃんと考えて、練習用じゃないきちんとしたアプリを作成する！

[**TokaiGo!(iOS版)**](https://apps.apple.com/jp/app/TokaiGo!/id1601486685)
[**TokaiGo!(Android版)**](https://play.google.com/store/apps/details?id=tokai.go.app)