Flutterでぶつかった色んな問題の解決まとめ

誰かの助けになったら嬉しいなぁ。
初心者なので間違っていたらご指摘いただけると幸甚です。

## エラーで困ったこと
### -bash: flutter: command not foundっていわれた!

PATHが通ってなくて起きる現象(Flutter固有じゃないけど)。PC新しくしたときとか。
元Windowsユーザー的に一番カンタンだったMacでPath通す手段↓
Flutterをインストールしたフォルダを探す

Command + Space で terminal ってタイプして、ターミナル開く
ターミナルで open ~/.bash_profile  コピペして.bash_profile 開く
export PATH="$PATH:/flutter/bin"

###Googleログイン時にエラー
Googleアカウント使ってログインする時に以下のエラー。

```
PlatformException (PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null))
```
SHA1フィンガープリントの設定してなくて起きてた。
https://developers.google.com/android/guides/client-auth
FirebaseのProject SettingいってAndroid > Add Finger Print する。

はじめての認証ログイン時や、PC新しくした時とかに起きて焦った。

### 久しぶりにFlutter doctor打ったら Android license status unknown. が出た
ありがたやありがたや。
[flutter doctorで「✗ Android license status unknown.」が出た場合](https://qiita.com/ko2ic/items/8d36bcc50dc62a07936c)

(2020年5月追記)
上記で直らーん、って場合はこちら
[flutterの環境構築しようとしたらハマった話](https://qiita.com/pe-ta/items/e5a1813b21de8d446407)

###久しぶりにFlutter runしたら動かんかった
```
failed to install/home/jedaa/workspace/flutter_apps/studio/flutter_apprescue/build/app/outputs/apk/app.apk: cmd: Can't find service: package
```
こんなエラー。
一旦これで直った
Open AVD Manager
Wipe Data (delete datas from emulator)
Open emulator
Try to run app

https://stackoverflow.com/questions/53532810/error-launching-application-on-android-sdk-built-for-x86

### XcodeでHot Reloadが効かなくなった！
よくみたらDebug実行時に表示される、⚡マークが表示されなくなっていた。
これでていないとHot Reload効いてないでっせ、という証みたい。
Flutterのエクステンションをアンインストールして再インストールしたら直った。ふぅ。

### エラー [type 'List<dynamic>' is not a subtype of type 'List<String>']
エラー箇所特定できなくてちょっと手間取った
cloud firestoreからデータ取るときに`DocumentSnapshot snapshot`みたいな形で取り回すと思うのだが、
その際`snapshot.data`は `Map<String, dynamic> map`となるはず。
この子要素をListで格納してる際に、

```BEFORE.
List<String> hogeList;
piyoMethod(Map<String, dynamic> map, {this.reference})
  :hogeList = map['リストのKey'];
```

とすると該当のエラーが発生する。
解決法は、リストをStringにキャストすること。

```AFTER.
List<String> hogeList;
piyoMethod(Map<String, dynamic> map, {this.reference})
  :hogeList = map['リストのKey'].cast<String>(); //castする
```

### エラー google sign inで App with name __FIRAPP_DEFAULT does not exist. 
```
331
[        ]      1   libobjc.A.dylib                     0x000000010b42dac5 objc_exception_throw +
48
[        ]      2   CoreFoundation                      0x000000010be89555 +[NSException
raise:format:] + 197
[        ]      3   Runner                              0x000000010555068d -[GIDSignIn
signInWithOptions:] + 242
[        ]      4   Runner                              0x000000010554cc82 -[GIDSignIn signIn]+ 64
[        ]      5   Runner                              0x000000010545c68f -[FLTGoogleSignInPlugin
handleMethodCall:result:] + 2223
[   +1 ms]      6   Flutter                             0x000000010869223a
__45-[FlutterMethodChannel setMethodCallHandler:]_block_invoke + 115
[        ]      7   Flutter                             0x00000001086b07b2 _ZNK7flut<…>
```
でこんなエラーになってた。
ios側のinfo.plistの設定がおかしかったから起きてた。もう一度、以下ページのiOS integrationをきちんとやり直すこと。
https://github.com/flutter/plugins/tree/master/packages/google_sign_in
あと、ios側のGoogleService-Info.plistは手動で足すとエラーになるかも。Xcodeから足すこと。

https://github.com/flutter/flutter/issues/16871

### google ログインしたあとにError 403 Restricted Client with Google Signin in Flutter エラー
https://console.firebase.google.com/ 
コンソールから自分のプロジェクト飛んで、設定アイコン＞プロジェクトの設定＞サポートメール 
にて、メールアドレスを入力すればいける

### エラー I/flutter (18403): PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 16: , null)
iosではGoogle sign inできたのに、Android側でできないエラー。

SHA1発行せねばならん。
windowsは以下
keytool -list -v -keystore "C:\Users\ユーザー名\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
で発行したSHA-1をコピってFirestore＞Andoroid＞設定 SHA 証明書フィンガープリント  にコピペ
参考: https://developers.google.com/android/guides/client-auth

更新した後、google-services.jsonダウンロードして配置し直すの忘れないように～

### windowsでSHA1だそうとして bash: keytool: command not found エラー

環境変数にjdkのPATH通そう。(パスの通しかたは以下URLに書いてある)

C:\自分のjdkまでのPATH\oracle-jdk-1.8.0_121\bin
(カスタムしてなければC:\Program Files\Java以下にあるよ！)

そもそもjavaつかってなかったら→jdkのインストールからしよう。
https://nobuo-create.net/java-beginner-1/

(またはもうだるいからMacの購入を考えよう)

### バージョンエラーもろもろ
```
ERROR: [TAG] Failed to resolve variable '${animal.sniffer.version}'
ERROR: [TAG] Failed to resolve variable '${junit.version}'
```
→ `flutter clean`でかいけつした(常にそうとは思わないけど、、、)

###エラー _InternalLinkedHashMapはMap<String, double>のサブタイプではない

```
Unhandled Exception: type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, double>'
```

### firebaseでupdate文を打つと、アプリが落ちる (documentId空だった)

```
Firestore.instance
          .collection('コレクション')
          .document(log.documentID)
          .updateData({'logs': log.logs});
```
当たり前っちゃ当たり前なんですが、このlog.documentIDのデータが空の状態でupdateかけたらアプリが落ちた。
アプリ落ちると原因調査するために再度立ち上げなきゃいけないので割と解消するまでに時間くってうざかったw

##実装で困ったこと

### AppBarなくしたら上の網掛け部分とアプリがかぶっちゃってうざい。
SafeAreaつかうといい感じになるよ
https://www.youtube.com/watch?v=lkF0TQJO0bA&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=2

```
@override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Column(
       // コンポーネントのソース
      ),
    );
  }
```

変更前(Scaffordの上においてた)
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171514/69f97d7b-a734-e768-f9bf-af222eb354c7.png)

変更後(SafeArea使った。いいね)
![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171514/1aab0a41-4db2-b814-9401-f8c476366aa4.png)

###ColumnとRowってなんぞ？
わかりやすいブログをみようず。

「FlutterのColumnとRowを使ってみた」
https://dev.classmethod.jp/smartphone/flutter_column_row_1/

###ページ遷移するコード
```
Navigator.of(context).pushReplacement(MaterialPageRoute(
      builder: (context) {
        return {{遷移したいページ}}();
      },
    ));
```

### DocumentSnapShotとQuerySnapshotの違い
DocumentSnapShot : FirestoreからDocumentId指定してデータ取得した際の返り値
QuerySnapShot : FirestoreからwhereとかOrderByとか指定してデータ取得した際の返り値

というイメージ。。。あってんのかな、、？
このお二方の記事を読んだ。
[Cloud FirestoreのCollectionとDocumentからデータを取得する際の違い](https://qiita.com/sosmii/items/010e9a2d1b5e7698bf77)

[firestoreを使うときに理解しておきたいいろんなクラスを整理する](https://qiita.com/muijp/items/86a4573fdce800221b72)

###firestoreで今日の日付のみのデータを取得する方法がわからない
以下やりたかったこと

* datetime.now()で今日の日付を取得する
* 使用するのは「(時間を含まない)日付のみのデータ」
* しかしdatetime.now()だと、firestoreから今日日付のデータ（複数ある）を取得する際にうまく取得できなかった

以下やったこと

* firestoreに挿入する日付を作成する際、無理やり時間を含めない形にした
＊ 取得する際はDateTime(年,月,日)でOK

```
DateTime _now = DateTime.now();
DateTime _selectedDay = DateTime(_now.year,_now.month,_now.day);
```

`between 11月11日の始め 〜 11月11日の終わり`
みたいにして取得するのが正解なのかなぁ。。。~~（やり方わからなかった）~~
【追記】
isGreaterThan, isLessThan使うことでできた！

```
QuerySnapshot snapshot = await Firestore.instance
        .collection("workLog")
        .where("date", isGreaterThanOrEqualTo: firstDate)
        .where("date", isLessThan: lastDate)
        .orderBy("date")
        .getDocuments();
```


### firebaseにてnumberとして格納されてるものの取り扱い
firebase上はnumberで入っているが、dart上ではintとdoubleで書かれていたので、
ところどころで
Unhandled Exception: type 'int' is not a subtype of type 'double'
のエラー起こしていたfirebaseに入れる際は.toDouble()してdouble型で入れたはずなんだが、取得したらint型になっていて本エラーが起きてた。

→intもdoubleも許容するnum型つかうことで解消（根本解決じゃないけど）

### メソッドの引数を任意にしたい

```
String getHoge([String parameter]) //大かっこで囲うと任意引数になる 
```
### データをUpsertしたい。並びにupdateDataとsetDataの違い
この方の記事を読んで学んだ。
[Firebase Cloud Firestoreのデータ更新 setとupdateの違い]
(https://tomokazu-kozuma.com/difference-between-set-and-update-when-updating-cloud-firestore-data/)

* set：ドキュメントの追加、上書き、fieldの追加
* update：ドキュメントのfieldを更新

setのほうができること多いんだね。

### TimestampをDateTimeに変換したい
fromMicrosecondsSinceEpoch使うとできる
https://api.dartlang.org/stable/2.6.1/dart-core/DateTime/DateTime.fromMicrosecondsSinceEpoch.html

```
Timestamp ts;
DateTime date = new DateTime.fromMicrosecondsSinceEpoch(ts.microsecondsSinceEpoch);
```
### DateTimeに一ヶ月足したい
結構雑に書いても対応してくれるの優秀〜（ふつうか？）

```
print(new DateTime(2019,12+1,2));
// 2020-01-02 00:00:00.000
print(new DateTime(2019,2,28+1));
// 2019-03-01 00:00:00.000
print(new DateTime(2020,2,28+1));
// 2020-02-29 00:00:00.000
```
###foreach内でreturnしても効かない
この方の記述どおりでやんす
[forループとforEach内でreturnした時の挙動の違い](https://qiita.com/growsic/items/008d0bd9e93174132ffc)

### FireStoreにて、OR条件で検索したい
現状できないとの。(2019年11月)