【個人開発】旅行記録を簡単に作成できるアプリを作りました

# アプリ作りました
iPhone/Androidアプリ**「かんたん旅行記」**をリリースしました。
**写真を読み込ませるだけで、いい感じの地図付き旅行記を作成**してくれます。

[**かんたん旅行記(iPhone版)**](https://apps.apple.com/jp/app/%E3%81%8B%E3%82%93%E3%81%9F%E3%82%93%E6%97%85%E8%A1%8C%E8%A8%98/id1584974094)

[**かんたん旅行記(Android版)**](https://play.google.com/store/apps/details?id=com.tmasuko.smartTripDiary)

<img width="300" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607181/836302a2-137b-92c0-cb3e-2e26acba9201.png">

一人旅の記録や、散歩の記録をつけるのに活用できると思います。
~~今のところAndroid版はありませんが、近日中に配信したいです。~~

[2021/10/29追記]
Android版リリースしました！ヒャッフゥ！


# きっかけ
僕自身一人旅によく出かけるのですが、ちゃんとした旅行記をつけたことがありません。
旅行記と聞くと、写真だけでなく文章をいっぱい書かなきゃいけないイメージがあり、ずぼらな自分にはなかなか手が出ない領域でした。
**文章入力をほとんどせず、写真を読み込ませるだけで旅行の道筋を追体験できるアプリ**があればいいのにな…と思ったのが開発のきっかけです。

# Why Flutter ?
もともとはpython+djangoでWeb開発していましたが、スマホアプリ開発にもチャレンジしたいという思いもありました。色々とフレームワークを試していく中、

* 書きやすそう
* 学習しやすそう
* クロスプラットフォームだからiOS/Android問わず使えるものができそう

ということでFlutterに興味を持ち、Flutterで初めてのスマホアプリ開発だ！と意気込んだのがスタートでした。

# 機能
## 写真を選択するだけ！
使い方は至ってシンプル。カメラロールの写真を選択するだけです！
シンプルな操作で地図付きアルバムを作成してくれます。

## 地図を見ながら旅行を振り返れる！
写真に記録された位置情報を読み取って、地図上にマッピングしてくれます。

<img width="300" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607181/1c09231d-124a-4994-cb2f-3ac275ad1153.png">

iPhoneのカメラロールにも撮影位置をマッピングする機能はありますが、旅行ごとに/時系列順にまとめられる点が強みです。

## 地図と連動するスライドショー！
選択した写真は画面下部のカルーセル内に表示されます。
このカルーセルをスワイプすることで写真を切り替えることができますが、それに連動して地図のカメラ位置も移動します。

<img width="300" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607181/d41fc969-eaa8-c96b-22fa-870273eb955c.gif">

また、下記の操作も有効。

* 地図のピンをタップすればその場所で撮られた写真のスライドに移動
* スライダーを移動すればその日時に撮られた写真のスライドに移動

このように、インタラクティブな地図付き旅行記を作成することが可能です。

## コメントをつけられる！
文章を入力しなくてもある程度のものはできますが、もちろん写真にタイトルや説明文をつけることも可能。

<img width="300" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607181/2757ff68-f796-972e-4053-e8b3756a20cd.png">


## 色々あって実装しなかった機能

* 旅行記のシェア機能
最初は作った旅行記をWebページとして公開できるようにしようと思っていました。
しかしそれをやるにはデータをローカルではなくFirebaseなどクラウド/サーバー上に保持する必要があります。また、ユーザーに紐づくデータとなるため、会員登録(またはソーシャルログイン)が必須になります。
AppStoreへの配信は初めてだったので、勉強も兼ねて構成はミニマムにしたかったのと、もともとが一人旅や散歩の記録用というコンセプトなので削っても構わないだろうと思い、今回は実装しないことにしました。

* バックアップ機能
機種変更をした際にもデータを引き継げるよう、クラウドバックアップ機能を搭載しようとしていました。
しかしこちらも実装するにはユーザー登録が必要になると思い、今回は削りました。
今後のアップデートで実装できればと思っています。

## 実装すべきだった機能

* 強制アップデート機能

これだけはちゃんとやるべきでした。Qiitaの記事を見ていても、この機能は大切だと色々な方が仰っていました。先に皆様の記事を見るべきでした。
アップデートをしていない状態でアプリを起動したら、「アップデートしてください」と表示されて強制終了するという、あの機能です。すなわちユーザーに対して強制的にアップデートを促すことができるのです。
この機能を持たせなかったがために、v 1.0.0での初期不良がそのまま残ってしまう危険性を孕んでしまうことになりました。~~次のアップデートで必ず実装します。~~

[2021/10/29追記]
機能実装しました！強制終了ではなく、画面上部に「最新バージョンがあります」というアップデートを促す文言を表示するようにしました。

# 大変だったこと

## 全般
2018年末に発表された比較的新しいフレームワークということもあり、ドンピシャな情報を見つけるのが結構大変でした。Flutter自身がどんどんアップデートされていくので、探して見つけた情報がOut-of-dateだったりもしばしば。
しかし勢いのあるフレームワークなので、これからエコシステムも充実していくと思います。きちんとキャッチアップしていくために、開発は継続して行いたい！

## 構成面
Flutterでの初めてのアプリ、かつ自身にとって初めての自作スマホアプリということで、簡単な構成にしようと考えていました。
データはローカルのみに保持することにしたので、Firebase連携を伴うアプリよりは開発難度はぐっと下がりましたが、それでも課金処理などはつまづく部分が多かったです。
結果として、**外部サービスと連携する**ことで実装しなければならない項目を減らし、スピーディにAppStore審査に持っていくことができました。

* [RevenueCat](https://www.revenuecat.com/?utm_source=google&utm_medium=cpc&utm_campaign=brand&gclid=Cj0KCQjwqp-LBhDQARIsAO0a6aIbcbbFZAzQ-L-CqrrO6xnjRHLS-9fw1F-Vh637F5EvqDfuKMi7nGEaAiMREALw_wcB)
  * 課金処理が正常に通ったかを確認するコールバックを実装する必要がありますが、自分でサーバーを立てて実装したり、Firebase上に実装したりが少し手間でした。RevenueCatはそういった**コールバック処理・課金管理を代行してくれる**サービスです。flutterのパッケージもあるので連携は容易。これのおかげで爆速で課金処理が実装できました。
* [Formspree](https://formspree.io/)
  * **フォームの送受信処理を代行してくれる**サービスです。審査に当たってお問い合わせページを実装しないといけないのですが、こちらも自分でサーバーを立てるのが面倒だったので、github pagesに静的ページとしてお問い合わせフォームを実装し、Formspree側でお問い合わせ内容の受信管理をしてもらうことで解決しました。 

## 実装面
各種パッケージの選定は少し悩みました。
欲しい機能が網羅されているだけでなく、

* 継続して更新がなされている
* 評価が高い
* ドキュメントが充実している

などの観点で下記を選定しました。公式パッケージ多めです。

* 写真選択 : [image_picker](https://pub.dev/packages/image_picker)
* カルーセル : [carousel_slider](https://pub.dev/packages/carousel_slider)
* Google Map : [googlemaps_flutter](https://pub.dev/packages/google_maps_flutter)
* AdMob : [google_mobile_ads](https://pub.dev/packages/google_mobile_ads)
* 状態管理 : [riverpod](https://pub.dev/packages/riverpod), [shared_preferences](https://pub.dev/packages/shared_preferences)
* DB : [sqflite](https://pub.dev/packages/sqflite)
* 課金 : [purchases_flutter](https://pub.dev/packages/purchases_flutter)

そのほか、Widgetのリビルドが多すぎてメモリ使用量過多になったり、非同期処理を並列でやり過ぎて落ちたりと、色々失敗しました…。いつかこの辺りのノウハウも記事にできたらと思います。

# さいごに
反省点はありますが、とりあえずアイデアを形にできてよかったです。
使ってみての感想やバグ報告などお待ちしています！

[**かんたん旅行記(iPhone版)**](https://apps.apple.com/jp/app/%E3%81%8B%E3%82%93%E3%81%9F%E3%82%93%E6%97%85%E8%A1%8C%E8%A8%98/id1584974094)

[**かんたん旅行記(Android版)**](https://play.google.com/store/apps/details?id=com.tmasuko.smartTripDiary)