【Flutter】メモアプリ開発で使ったオススメのパッケージを紹介

# メモアプリ作成で作ったFltutterパッケージ
![iphone11top.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228439/da55ca32-10f5-fe10-6c51-f9f26e56f609.jpeg)

今こそ「ひらめきたい」というあなたに！

6月末にFlutterでアプリ開発を始めてから２作目のアプリ、アイデアを発想するためのメモアプリ「アイデアメモ iX」をリリースしました。

■AppStore
https://apps.apple.com/jp/app/id1517535550

■Google Play
https://play.google.com/store/apps/details?id=com.IdeaShuffleMemoApp&hl=ja

■アプリの詳細記事
  https://yukio.site/idea_shuffle_memo/


１作目は、とりあえずアプリをリリースすることを主眼にしていたため、技術的に実装が難しそうなところは省きました。
２作目はステップアップのために、

- 画面のパスワードロック
- DBのバックアップ・リストア
- 有料課金（サブスクリプション）など

いろいろな機能実装に挑戦的に取り組みました

この３つの機能実装について詳細を書くと、とっても長くなりますので、詳細は別の記事でまた書く予定です 泣汗汗汗

この記事では、メモアプリ作成で使って良かったFlutterパッケージについて紹介していきたいと思います。


### データベースへの保存
#### [moor | Dart Package](https://pub.dev/packages/moor)

Flutter開発でデータベース（DB）が使えるようにするパッケージが、Moorです。
![IMG_9925.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228439/feffe8d7-f4cf-940e-97c7-3b9cb59e61f6.jpeg)

最初に学習したFlutter教材がmoorを採用していたのでDB操作のパッケージはこれ一択だったのですが、一通りやりたいことはやれるので満足しています。

日本語の情報は少ないですが、英語ではしっかりした資料もあったり、Youtubeもあったりと情報は充実していると思います。（Google翻訳があれば問題ありません・・・白目。）

[Getting Started | Moor](https://moor.simonbinder.eu/docs/getting-started/)

ただパッケージを入れたからといって簡単に扱えるわけではなく、プログラミングの完全な初心者だったり、RubyonRailsしかやったことがない人にとってはちょっと難しいも。

Railsのように至れり尽くせりではないので、Rails感覚でやると辛いです。

初期設定やデータの保存・取得など、それなりに資料とにらめっこしながら勉強する必要があるかもしれません。

「DB？余裕っしょ」とナメていると、ヒョードルにタコ殴りされた気分になります。

慣れてくれば、それなりに使いやすいと思います。


### 派手目のダイアログ
#### [awesome_dialog | Flutter Package](https://pub.dev/packages/awesome_dialog)

今まで更新完了などの表示はToastを使っていたのですが、いかんせん地味で、表示されているのに気づかなかったり。

awesome_dialogであれば、簡単に大阪のおばちゃん並の主張をする、派手なダイアログを表示することができます。
![IMG_9924.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228439/7a584c7a-4edc-d0b2-ae6b-8ebda7fd6c27.jpeg)

実装は、公式ドキュメントを見れば簡単にできると思います。

OKやCANCELのボタン、ボタンの色などカスタマイズもかなり自由にできます。

~~ただ・・・ダイアログが自動的に消えてくれる機能がありません。~~
@tepci さんにご指摘頂いたのですが、現在は消せるようになっていました！ありがとうございます。
この記事のコメントに書いて頂いてますので、そちらをご覧ください。

ダイアログを消すために毎回ボタンをを押すのは、メンディーですよね。


〜〜〜〜古い内容です〜〜〜〜
もう、半分が優しさでできていないバファリン並にユーザーにとって好ましい状況でありません。

「作成しました〜」っていう表示をした後に、数秒後に消えてくれるか、ダイアログの外側をタップしたら消えてくれるほうがいいですよね。

```dart
Timer t = null;
AwesomeDialog(context: context,
  dialogType: DialogType.SUCCES,
  animType: AnimType.BOTTOMSLIDE,
  tittle: '追加したぜ〜〜〜',
  desc: '',//何か文章入れたければ
  onDissmissCallback: () async {
    Navigator.pop(context); //編集画面を閉じるため
    t.cancel(); //キャンセル処理
    //やりたい処理
  },
).show();
t = Timer(Duration(seconds: 3), () {
  Navigator.pop(context);//編集画面を閉じるため
  //やりたい処理
});
```
いろいろやり方はあると思いますが、こんな感じにしてみました。
何もしない場合、タイマーで３秒後に消えるようにしています。
ただし、ダイアログの外側をタップ後にタイマーをキャンセルしないと、トラップカードのごとく処理が2重で発動してしまいます。
なので、画面の外側を押した時に、「 t.cancel(); 」でタイマーをキャンセルしています。
〜〜〜〜古い内容終了〜〜〜〜

### アイコン「font_awesome_flutter」
#### [font_awesome_flutter | Flutter Package](https://pub.dev/packages/font_awesome_flutter)
![IMG_9926.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228439/e2c9fc06-fa20-7ed1-17cb-792eca0eaeac.jpeg)

マテリアルアイコンでもいいのですが、ぴったりのアイコンとか見つからないことがあります。
今回バックアップで、GoogleDriveを使ったのですが、アイコンでいちいち画像を表示させるのがメンディーです。
なので、各サービスのアイコンとか使える「font_awesome_flutter」を使ってみました。
使えるアイコンが増えるので、いいですね。
こんな感じで、簡単に呼び出せます。

```dart

icon: FaIcon(FontAwesomeIcons.google),
```

###  バイブレーションの通知「vibrate」 
#### [vibrate | Flutter Package](https://pub.dev/packages/vibrate)

Webサービスだとあまり気にならないのですが、アプリの場合、更新とか保存など、ちょっとした処理の時にフィードバックがないと不安になったりしません？

サバンナの八木さんみたいに「スマホさん動いてますか？」って聞きたくなりますよね。

ユーザーに、「処理しているよ〜」とか、「処理終わったよ〜」って分かりやすくする方が親切なので、バイブレーションの機能を実装しました。
こんな感じで簡単に、よきタイミングでコードを差し込めば、スマホを震わせることができます。

```dart
Vibrate.*feedback*(FeedbackType.medium);
```

バイブレーションのタイプも色々あります。

```
  success,
  error,
  warning,
  selection,
  impact,
  heavy,
  medium,
  light
```

私は面倒なので、mediumオンリーで使ってます。

### スマホを振ると動く機能
#### [shake | Flutter Package](https://pub.dev/packages/shake)

せっかくスマホなので、スマホだからこそできる機能をつけたい。

スマホを振ると、処理を発動できるパッケージが、ブギーな胸騒ぎしそうな「shake」です。

このパッケージを発動する方法が２つあって。
「ShakeDetector.waitForStart」& 「detector.stopListening();」のように任意に終了させるか、「ShakeDetector.autoStart」のように自動を選ぶことになります。

後者は、initState、アプリの開始時に発動させればいいのですが、他のページに移っても発動が続くことがあり、ブルブルと震えてしまうのでチョベリベリ最高でない状態になりました。

なので、前者でinitState、アプリ開始時にスタートさせて、dispose、画面の終了時に止まるようにしています。

```dart
@override
void initState() {
  super.initState();
  detector = ShakeDetector.waitForStart(
      onPhoneShake: () {
	//やりたい処理
      }
  );
}

@override
void dispose() {
  // *TODO: implement dispose*
  super.dispose();
  detector.stopListening(); //振ったら動く処理終了
}
```

※20/0712　追記
１つ問題がありました。disposeで終了だけでは足りません。
アプリが終了ではなく、バックグラウンドに入った場合にも動作が継続してしまうようです。

解決策は以下のパスワードの実装にある状態管理で、バックグランドに入ったタイミングで、ストリームを終了。復帰のタイミングで、戻すという処理をしないといけないです。

### パスワードロック機能
####[passcode_screen | Flutter Package](https://pub.dev/packages/passcode_screen)
パスワードロックの画面を作るパッケージ


#### [shared_preferences | Flutter Package](https://pub.dev/packages/shared_preferences)
DBなしでデータを保存できるパッケージ

#### [local_auth | Flutter Package](https://pub.dev/packages/local_auth)
生体認証を実装する機能。



どれもパッケージ自体の使い方は難しくないです。やりたいことは簡単に実現できます。


ただしこれらを組み合わせて、パスワードロックとして機能させるところが大変でした。

<img width="375" alt="IMG_9928.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228439/9ac39370-063a-9ff4-dd23-6c8496180bae.png">


パスワードロックでは、Flutterのライフサイクル（読み込まれてから、画面のデータが破棄されるまでの過程）などを理解する必要があります。

パスワードロック機能の実装はこちらの記事に書いたので、合わせてお読みください。

###  [Flutterでパスワードロック・生体認証ロック機能を実装する方法](https://qiita.com/YuKiO-OO/items/bf2d1d107d1a66211619)


一つ問題があって、パスワードロックの画面が表示される前に、一瞬だけ閉じた時の画面が表示されます。

ほぼ内容を読み取るが難しいほど一瞬ですが、完璧を目指すなら、すでにアプリを立ち上げた時点でパスワードロック画面が表示されている状態がいいですよね。

しかし、Flutterの仕様なのか、画面を閉じた時、立ち上げた時を感知できるても、どちらにタイミングも処理が走るのが、　画面が完全にたち上がってからでした。

なので、ちょっぴり中身が見えてしまいます。これはどうにも解決できる術が見つかりませんでした。

ネイティブでコードを書けば解決はできるそうなのですが、ネイティブは触れないので、今回はほぼ実害がないだろうという判断で、今回はそこまでの作り込みはしていません。


### バックアップ・リストア機能
バックアップ、リストアの方法はいろいろあると思いますが、GoogleDriveにDBのデータを保存する、ダウンロードして保存することにしました。

Googleドライブを採用した理由は、Googleアカウントはほぼみんな持っているだろうし、個人のアカウントに紐づいた管理の方が安心だろうという配慮、またこちらもストレージ容量のコストを気にする必要がないからです。
またAPIも無料のようなので、一番コストと機能がバランスがありそうです。

ただし、こちらはパッケージをインストールしたら、簡単に実装できるわけではありません。

FirebaseやGoogleDriveのAPIなどの外部サービスとの連携が必要になってきますので、始めて使う方はそれなりにお勉強する覚悟が必要だと思います。

GoogleDriveに保存する方法を記載した記事があまり見つからないのですが、テスト前にいやいやながらもノートをコピーさせてくれそうな優しい感じの方が書いているこちらの記事を参考にしました。パッケージをたくさんインストールするので、下記を参考にしました。(英語)

#### GoogleAPI利用の設定：参考
[Google Firebase Email/Password And Google Login In Flutter](https://www.c-sharpcorner.com/article/how-to-do-simple-login-with-email-id-in-flutter-using-google-firebase/)

#### Googleドライブの実装：参考
https://www.c-sharpcorner.com/article/google-drive-integration-in-flutter-upload-download-list-files/

**詳しい実装方法はこちらに書きましたので、チェックしてみてください。**


### [【Flutter】GoogleDriveへのバックアップ・リストア機能を実装するまでの道のり](https://qiita.com/YuKiO-OO/items/67b471e6be6c4c4c26e9)
こちらのポイントは、概念を理解するまでが時間がかかりました。

![IMG_9929.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228439/43a60cec-132d-b684-82e8-8088876f7c64.jpeg)

大雑把に概要を書くと
- ユーザーにアプリからGoogleDriveにアクセスできるようにログインしてもらう。
- スマホに保存されているDBのファイルを、Googleドライブのユーザーが見えない領域に保存。
- 保存はIDで管理されているので、該当のファイルをダウンロードして、スマホのDBファイルにコピーでリストア

最初はなんのこっちゃよく分からないと思うので、一度まるまる、この方が書いている通りに作ってみてください。

どのコードが何をしているのかを把握してからコードを変更しておくと分かりやすいと思います。



### 有料課金機能
このアプリを開発する上でも最大難所だった有料課金、サブスクのところ。
これはFlutter公式？のin_app_purchaseを使いました。
#### [in_app_purchase | Flutter Package](https://pub.dev/packages/in_app_purchase)
<img width="375" alt="Simulator Screen Shot - iPhone 11 Pro - 2020-06-26 at 08.52.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228439/21e057f0-6b98-002c-5eea-f570d4b5dc1c.png">


この有料課金機能もパッケージ入れたら簡単に導入！というわけにはいかず、有料課金のサービスにする場合レシート（購入履歴）のチェックなどの機能を実装する必要があります。
ただ、レシートのチェックは、アプリ単体で動作させることはセキュリティの観点から推奨されておらず、外部のサービスと連携する必要があります。(Firebaseなど)

そして、現在進行形で世界中で議論されているハマりポイントもあります。

例えば購入操作のキャンセルやエラー時に、きっちりとトランザクション（一連の購入処理）を消しておかないと、Apple様の方に未処理のトランザクションが溜まってしまい、正常に動作しなかったりします。

私の場合、さらに有料課金の仕組みが理解できていなかったので、意味プーさん状態でかなり苦労しました。

もしプログラミング初心者、初めてアプリを作る方で、課金が必須でないのなら、有料課金は飛ばして作ったほうがいいと思います。

もし必須の場合は、ほぼほぼアプリが完成して、最後の仕上げとして取り組むほうがいいと思います。
下記に詳しい導入方法の記事を書きました。

### [【Flutter】もう怖くない！アプリ内課金・定期購入機能を実装する方法を丁寧に説明してみた。](https://qiita.com/YuKiO-OO/items/a0fe8e0a256afbb69fc7)


### チュートリアル機能

#### [introduction_screen | Flutter Package](https://pub.dev/packages/introduction_screen)

アプリをインストールしてくれたユーザーにきっちり機能を伝えることも大切だと思ったので、チュートリアルの画面を初回起動のみ表示するために、上記のパッケージを使いました。
<img width="375" alt="IMG_9930.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228439/234f386e-5639-9db7-2555-450f146da357.png">

初回起動の判断は、パスワードロックでも使った「shared_preferences」で、bool型で保存しておくことで、２回目以降は表示されなくなります。

これもほぼテンプレートが決まっているので、難しくなく導入できると思います。

### バッジ関連
badges
[badges | Flutter Package](https://pub.dev/packages/badges)

有料課金で強調したい部分があったので、バッジ表示として上記のパッケージを利用しました。
簡単にできるので、便利ですね。
分かりづらいですが、You can use~~~のところで使ってます。

<img width="375" alt="Simulator Screen Shot - iPhone 11 Pro - 2020-06-26 at 08.52.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228439/40696f62-9880-a106-97fd-9b875ca9100b.png">


### まとめ
いかがでしたでしょうか？詳しい説明は別の記事でが多かったのですが、今回は、難しい機能の実装に挑戦してみました。

正直1ヶ月で作ろうと思っていましたが、丸々3ヶ月もかかってしまいましたが、自分ではそれなりに実現させたかった機能を作ることができました。

保留にしている、
- パスワード機能
- バックアップ機能
- 有料課金
については、おいおい書いています。

特にFlutterは日本語の資料が少ないので、頑張りたいと思います。

少してもで、Flutter開発者の仲間の参考になれば幸いです。

ツイッターでも色々呟いているので、良かったらチェックください。


■ツイッターアカウント
[YuKiOのツイッター](https://twitter.com/oo_forward)

■YuKiOのブログ（個人開発のこと書いていたりします。）
[YuKiOのアウトプット](https://yukio.site/)

あと、四苦八苦して作ったアプリも是非ともよろしくお願いします。アプリのアイデア出しに使ってみてください。

■AppStore
https://apps.apple.com/jp/app/id1517535550

■Google Play
https://play.google.com/store/apps/details?id=com.IdeaShuffleMemoApp&hl=ja

■アプリの詳細記事
https://yukio.site/idea_shuffle_memo/


あとツイッターもやってますので、ぜひチェックください。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Webサービスやアプリ！<br><br>斬新なアイデアをひらめきたい人に！<br><br>アイデアを発想するためのメモアプリ✍️<br><br>IdeaShuffleMemoをリリースしました！<br><br>■AppStore<a href="https://t.co/gEPzEEJ7mt">https://t.co/gEPzEEJ7mt</a><br><br>■Google Play<a href="https://t.co/w0vTiOanGE">https://t.co/w0vTiOanGE</a><br><br>使ってみてください😁<a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a> <a href="https://twitter.com/hashtag/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0?src=hash&amp;ref_src=twsrc%5Etfw">#プログラミング</a> <a href="https://t.co/gQ0dOMNgGB">pic.twitter.com/gQ0dOMNgGB</a></p>&mdash; YuKiO | 個人開発&amp;Flutter (@oo_forward) <a href="https://twitter.com/oo_forward/status/1278611399749431296?ref_src=twsrc%5Etfw">July 2, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>