Flutter エラー・バグ日記

(2022.1.14更新)

Flutterで日々直面したエラー・バグ(できたら対応履歴も)を日記的につづっています(Flutter以外の話も若干あります)。

些細なことでも同じ問題にぶつかった方にヒントになれば、という思いで書いています。

ライトな日記思考なので、詳細説明はしておらず、基本、テキストのみで画像とかは載せておりません。。m(_ _)m

解説記事ではないため、解決していない内容や、その時々の間違った解釈を述べてしまっている可能性が大いにありますので、何卒、ご了承ください。


スポンサーリンク
  1. 2022/1/13 意図しない再描画が発生すると思ったら、原因は「MediaQuery.of」だった
  2. 2022/1/11 GetX(「get」パッケージ)のサンプルコードを試したら膨大なエラー(「No named parameter」など)
  3. 2022/1/9 Google Cloud PlatformのOAuth同意画面のアプリ名を変更するとエラー
  4. 2022/1/5 Appleの審査に出そうとしたら「Apple TVプライバシーポリシーは必須です」の表示が出て止められる
  5. 2022/1/2 App Store ConnectへのArchive送信時に「Unable to process request – PLA Update available」のエラー
  6. 2021/12/31 Android Studio(Mac)でaabファイルを作ろうとしたら、「Generate Signed Bundle / APK…」が表示されない
  7. 2021/12/29 デバッグビルドだと正常に動くが、リリースビルドだと期待した挙動にならない(まだ理解不足)
  8. 2021/12/26 Android Studioでビルドを実行したら「devtools-2.9.2/build” could not be found」のエラー
  9. 2021/12/23 TextFormField内の文字が、なぜか上寄せになってしまう。
  10. 2021/12/19 TextFieldで、ScrollControllerの「animateTo」メソッドが機能しない
  11. 2021/12/18 pod installすると、「CocoaPods could not find compatible versions for pod “・・・”」のエラー
  12. 2021/12/12 MaterialPageRouteが原因で、WidgetのY座標位置を正確に取得できない
  13. 2021/12/10 プロジェクトのnull safety移行: エラーで「dart migrate」コマンドが通らない → オプション2つ付けて何とか通す
  14. 2021/12/7 AndroidとiOSとで、Googleサインインの挙動が違う
  15. 2021/12/5〜12/6 iOS Appleの審査で、iOS 15.1だとATTの同意取得ダイアログが表示されないと言われてリジェクト
  16. 2021/12/1〜12/2 iOSで、image_pickerのカメラアクセスを許可しないとエラーになり、正常動作できない
  17. 2021/11/26 GooglePlayにアプリをリリースしたら、Google SignIn(Googleサインイン)ができなくなった
  18. 2021/11/22 iOSシミュレーターでのみ、TextFieldで「’readOnly && !obscureText’: is not true」のエラーが発生
  19. 2021/11/20 Image Pickerで読み込んだ画像が、撮影した向きどおりに表示されない
  20. 2021/11/18 Google APIへの接続で、「status: 401, message: Request had invalid authentication credentials」のエラー(別原因と判明)
  21. 2021/11/13 Google Play Consoleの「メインストアの掲載情報」(アプリ名、簡単な説明)で、ガイドラインを遵守していないと警告
  22. 2021/11/12 「Open Android Module in Android Studio」がグレーアウトして開けない場合の対処法
  23. 2021/11/6 配列内の複数の要素を同時に消そうとしたら「RangeError (index): Invalid value: Not in inclusive range」のエラー
  24. 2021/11/1 AdMobでバナー広告を2つ表示したら「This AdWidget is already in the Widget tree」のエラー
  25. 2021/10/31 「pod install」したら、「CocoaPods could not find compatible versions for pod “Firebase/Auth”」というエラー
  26. 2021/10/23 「oktoast」で表示されないトーストが発生→「OKToast」のラップはアプリ内で1回しか使えなかった。
  27. 2021/10/22 Google APIへの接続で、「status: 401, message: Request had invalid authentication credentials」のエラー(後日、別原因と判明)
  28. 2021/10/20 「The instance member ‘変数名’ can’t be accessed in an initializer」というエラーへの対処法
  29. 2021/10/18 「gallery_saver」パッケージを使ったら、Kotlinのバージョンがおかしいというエラー
  30. 2021/10/14 Dividerでなぜか横線が表示されない
  31. 2021/10/11 今まで問題なかった「initState」メソッド内の「context.read」が、いつの間にかエラーに(一応解決)
  32. 2021/10/10 Android Studioで、option+Enterが効かなくなった(解決)
  33. 2021/9/20 Card内の配置でなぜか「A RenderFlex overflowed by 8.0 pixels on the bottom.」のエラーになる(解決)
  34. 2021/9/18 Android エミュレーター内の「ファイル」アプリで、ファイルやフォルダの選択しかできない問題への対処
  35. 2021/9/11 正規表現を使ったマッチングが何度やっても成功しない
  36. 2021/9/6 Device File Explorer内のアプリ専用フォルダの情報が更新されない問題への対処
  37. 2021/9/5 DevToolを起動したら「127.0.0.1 で接続が拒否されました。」のエラー
  38. 2021/9/2 Google SignInでCalendar APIに接続できない(解決)
  39. 2021/9/1 Null check operator used on a null value
  40. 2021/8/31 Google SignInでCalendar APIに接続できない

2022/1/13 意図しない再描画が発生すると思ったら、原因は「MediaQuery.of」だった

コードを修正していたら、いつの間にか意図しないタイミングで画面の再描画が発生するようになってしまった。

setStateやNotifyListenersをしていないタイミングで、再描画が発生する。

怪しそうな所をひたすらコメントアウトして挙動を確かめていたら、画面サイズを図るために追加した「MediaQuery.of(context).size.height;」が原因と分かる。

「MediaQuery.of」でなぜ再描画?と思ったが、Flutter公式にちゃんと説明があった。

Querying the current media using MediaQuery.of will cause your widget to rebuild automatically whenever the MediaQueryData changes (e.g., if the user rotates their device).

MediaQuery.ofを使用して現在のメディアをクエリすると、MediaQueryDataが変更されるたびに(たとえば、ユーザーがデバイスを回転させた場合)、ウィジェットが自動的に再構築されます

https://api.flutter.dev/flutter/widgets/MediaQuery-class.html

言われてみれば確かに、、、という感じだが、盲点だった。。

buildメソッド下で「MediaQuery.of」を多用していたため、利用する都度、画面情報を取得するのではなく、一度取得したら、変数に入れて使い回すように修正。これで再描画は回避できた。

今後は安易にMediaQueryを連発しないように注意します。

 

 

\ Flutterの学習で役立ったコンテンツ・書籍 /

The Complete 2021 Flutter Development Bootcamp with Dart

 

 


Dart入門 – Dartの要点をつかむためのクイックツアー
スポンサーリンク

2022/1/11 GetX(「get」パッケージ)のサンプルコードを試したら膨大なエラー(「No named parameter」など)

pub.devで7,000を超えるLIKEがついているGetXに興味が湧く。

日本語の解説ページまで用意されているのが珍しい。

状態管理にはProviderを使っているが、もう少し手軽な方法がないかと思っていたので、早速サンプルコードを試してみると、

Error: No named parameter with the name ‘useInheritedMediaQuery’.
useInheritedMediaQuery: useInheritedMediaQuery,
^^^^^^^^^^^^^^^^^^^^^^
Context: Found this candidate, but the arguments don’t match.
const CupertinoApp.router({
   ^^^^^^^^^^^^^^^^^^^
Context: Found this candidate, but the arguments don’t match.
const MaterialApp.router({
   ^^^^^^^^^^^^^^^^^^
Context: Found this candidate, but the arguments don’t match.
const MaterialApp({
   ^^^^^^^^^^^
(以下略)

などの多数のエラーが出る。

調べると、こちらこちらなどに同様の報告が多くされていた。

結論としては、最新の4.6.1だと発生するようで、4.6.0未満(具体的には4.5.1)に下げたら解消した。

確かに書くコード量も少なく便利なので、既存プロジェクトにおいても、部分的に活用するのもアリかもしれない。

 

スポンサーリンク

2022/1/9 Google Cloud PlatformのOAuth同意画面のアプリ名を変更するとエラー

Flutterに限らない話だが、Google Cloud Platform(GCP)の同意画面設定でアプリ名を変えたら

アプリの保存中にエラーが発生しました

と表示され、何度やっても変更できない。

デフォルトのアプリ名は「project-######(数字12桁)」だが、これを変更したかった。

調べると、こちらの情報が類似しており、「アプリ名をユニークにしたら通った」との報告がされていた。

しかし、絶対にユニークになる名称に変更してもエラーになる。

色々と実験しまくった結果、

アプリ名に「google」という言葉が入っているとエラーになる!

と判明。

「Googleテストアプリ」に変更したら上記エラーになったが、単純に「テストアプリ」にしたらエラーが出なかったので気づいた。

その後、色々なパターンで試したが、恐らく間違いない。

この情報はチュートリアルページでも見つけられなかったので、地味に苦労した。。。(どこかに記載があるのかもしれませんが、、)

本番のアプリ名に「google」を入れることはないと思うが、テスト開発中のアプリには適当に名前を付けがちなので、自分のような目に会わないよう、お気をつけください。。

 

2022/1/5 Appleの審査に出そうとしたら「Apple TVプライバシーポリシーは必須です」の表示が出て止められる

アプリを更新してApple審査に出そうとしたら、上記メッセージが出てストップ。

初めて見るメッセージで戸惑う。。

App Store Connectの左側メニューの「一般」の「Appのプライバシー」に入ると、画面上部に、

このページ上に1つ以上のエラーがあります。
 日本語とApple TVプライバシーポリシーは必須です。

との表示。

確かに「Apple TVプライバシーポリシー」の欄は空欄にしていたが、他の審査時にはこんなエラーは出なかった。

心当たりとしては、以前、間違って「tvOS App」を「提出準備中」の状態にしてしまったことか。。

この問題についてググってみたが、Apple TVを説明するApple公式の情報以外はほとんど見つからず、、、。

かなり以前の情報ではあるが、唯一見つかったこちらの情報(数少ない情報で大変助かりました!)では、「tvOS Appの取り下げはできない」とのことで、かなり厄介そう。。。

しかたなく、iPhone用のプライバシーポリシーのURLを「Apple TVプライバシーポリシー」にも設定して審査に出した。

URLを入力した部分に、「Apple TVプライバシーポリシー」自体の審査をするような表示が出てきたので、アプリ審査がさらに難航しそうな予感がするも、結果はあっさり承認

ちなみに、上記情報で紹介されていた方法にならい、レビューコメントに「Apple TVの利用は希望していませんが、登録を間違えたようなので、キャンセルしてください」と書いたが、この部分はスルーされ、レスポンスはなかった。

また、この後で気がついたが、「tvOS App 1.0提出準備中」となっている所をマウスオーバーすると、赤いマイナスマークが出てきて、提出準備を削除することができる模様。今は取り下げできるようです(怖くてやっていないですが、、)。

いずれにしても、tvOSでリリースするつもりがないなら、tvOSの提出準備は押さないよう、注意した方が良さそうです。

 

2022/1/2 App Store ConnectへのArchive送信時に「Unable to process request – PLA Update available」のエラー

XcodeからApp Store Connectに、審査用のArchiveを送信(Distribute App)しようとしたら、以下2つのエラーが出た。

Multiple errors occurred:
× Unable to process request – PLA Update available
You currently don’t have access to this membership resource. To resolve this issue, agree to the latest Program License Agreement in your developer account.

× No profiles for ‘com.########’ were found
   Xcode couldn’t find any iOS App Store provisioning profiles matching ‘com.########’.

2つ目のエラーは、provisioning profileが見つからないということだが、設定したはずなので、そんなはずない、、と戸惑う。

1つ目のエラーは、よく読まずにとりあえず「Unable to process request – PLA Update available」でググると、2件ほどヒットするが、解決には至らず。。

改めてよく見てみると、Developerアカウント内で規約に同意することが必要、ということらしい。

そんな理由で、App Store Connectへの送信時にエラーになるの?と戸惑いつつ、ともかくApple Developerのサイトにログインしてみる。

すると、トップページの上部に、

The Apple Developer Program License Agreement has been updated.
In order to access certain membership resources, you must accept the latest license agreement.

と出ていた。

規約を改定したので、承諾してくださいとのこと。素直に承諾ボタンをクリック。

Xcodeの画面に戻り、先ほどのエラー画面からいったん「Previous」ボタンで1つ前に戻り、再び「Next」ボタンで進んだところ、エラーが2つとも消え、無事Uploadされた。

規約に同意していないと、provisioning profileも認識されないとは。。

度々思うことですが、まずはエラー文をよく読むことが大事ですね。

 

2021/12/31 Android Studio(Mac)でaabファイルを作ろうとしたら、「Generate Signed Bundle / APK…」が表示されない

年末に更新リリースしようとして、直前で詰まる。かなり苦しんだ。。

※本件、こちらに記事化しました。

Flutterプロジェクトの中の「Android」フォルダを右クリックし、いつものとおり「Open Android module in Android Studio」で、Android専用の画面を起動し、「Build」メニューからaab(Android App Bundle)ファイルを作ろうとしたが、肝心の「Generate Signed Bundle / APK…」の項目が出てこない。。

画面右上をよく見ると、

Gradle project sync failed. Basic functionality (e.g. editing, debugging) will not work properly.
Try Again    Open ‘Build’ View    Show Log in Finder

と出ており、どうやらこれが原因らしい。

「Try Again」しても当然同じことの繰り返し。

「Open ‘Build’ View」で「Build」ウィンドウを開くと、目立ったエラーはない。。

「Show Log in Finder」からログを見てみたが、膨大すぎてわけが分からず。。

特にエラーではないのかな、、、と思い、右下の「Event Log」を見てみると、

Gradle sync failed: Sync failed: reason unknown

と赤字で出ていて、やっぱりエラーだと分かる(「reason unknown」って困る、、、と思いつつ)。

仕方なくググると、大概の情報が、「Android Gradle Plugin Version」「Gradle Version」の対応関係が不整合なので、Gradleを最新にして解消する、というものだった。

2つのバージョンの整合性はこちらで確認できるのだが、自分の場合は、

  • Android Gradle Plugin Version → 4.1.0
  • Gradle Version → 6.7

となっており、不整合はなさそう。

そもそも、既に上記と同じバージョン関係の別プロジェクトから、aabファイルを作成できていたので、これが問題ではなさそう。。。

そこからは、再起動やキャッシュの削除など、色々と試行錯誤して難航するも、ちゃんとログを見ていなかったことを思い出し、「idea.log」ファイルを頑張って見てみると、

ERROR – intellij.openapi.progress.Task – Module: ‘flutter_plugin_android_lifecycle’ platform ‘android-31’ not found.
com.android.tools.idea.gradle.project.sync.idea.issues.SdkPlatformNotFoundException: Module: ‘flutter_plugin_android_lifecycle’ platform ‘android-31’ not found.

というログに気づく。

どうやらAPIレベル31のAndroid SDKが入っていないことが問題らしい。

「app/build.gradle」ファイルでは、targetSdkVersionは30にしていたので、「なんで31が必要なの?」と疑問に思うが、たぶん自分が理解不足なだけだろう。。。

導入しているパッケージに31を必要とするものがあったのかな、、?

とにかく「31」を入れてみようと、「Preferences」→「Appearance & Behavior」→「System Settings」→「Android SDK」と進み、「Android API 31」をインストール(※Mac版のAndroid Studioの遷移)。

もう一度、Gradle project syncをやってみると、無事syncが成功し、「Build」メニューに「Generate Signed Bundle / APK…」が表示された!

やはり、ログをきちんと見ることが重要、と改めて認識。。

苦闘しましたが、、無事、Google Playに更新リリースできました。

 

2021/12/29 デバッグビルドだと正常に動くが、リリースビルドだと期待した挙動にならない(まだ理解不足)

要因を詰めきれておらず、詳しい説明ができないが、こういう現象があったというメモ。

「リリースビルドではうまくいくが、デバッグビルドだとおかしい」というのは経験済だが、逆は初めて。

原因が分からずかなり苦しんだが、リリースビルドとデバッグビルドをprint文でログ比較したところ、デバッグビルドでは1度しか回らなかった処理が、リリースビルドでは2度回っていたことが分かった。

非同期処理で、データの読み込みが終わったら描画する処理をしており、データを読み込むViewModel層から、notifyListenersでView層のConsumerに通知していた。

この部分が、リリースビルドだと2度回っていた。

1度処理が回る間に、配列変数に値をaddメソッドで追加するのだが、2度回ったことで想定以上に値が追加されてしまい、結果、期待した挙動にならなくなっていた。

そのため、値を追加する前に配列を初期化するよう修正し、対処はできた。ただ、詳細はまだ理解できておらず。。

そもそも自分のMVVMの扱い方が下手なのだと思うが、、、

探してたどり着いたこちらの情報を拝見すると、デバッグビルドだとDartの処理が遅いため、かえってうまくいく事がある模様。。

リリースビルドだと処理が早すぎで2度回ってしまったということか。。

とりあえずこういう事象もあることを理解。勉強してもう少し理解を深めます。。

  

2021/12/26 Android Studioでビルドを実行したら「devtools-2.9.2/build” could not be found」のエラー

日本語の記事が見当たらなかったので、備忘も兼ねて共有。

今日ビルドしたら、急に以下のようなエラーが出るようになった。

Unhandled exception:
Invalid argument(s): A directory corresponding to fileSystemPath “/Users/XXXXXX/.pub-cache/hosted/pub.dartlang.org/devtools-2.9.2/build” could not be found
#0 createStaticHandler (package:shelf_static/src/static_handler.dart:50:5)
#1 defaultHandler (package:devtools_server/src/external_handlers.dart:38:23)<asynchronous suspension>
#2 serveDevTools (package:devtools_server/src/server.dart:215:15)<asynchronous suspension>
#3 serveDevToolsWithArgs (package:devtools_server/src/server.dart:73:10)<asynchronous suspension>

ビルド自体は問題なくできるのだが、DevToolに問題があるらしく、確かにDevToolのボタンを押しても起動しない。。特になにかやった記憶はないのだが、、、。

ネットで調べてみると、英語の記事だが、以下2つの情報があった。

結論としては、DevToolのバージョンを下げる、ということで、

dart pub global activate devtools -v 2.8.0

のコマンドをターミナルで実行すれば良いとのこと。

※あくまで「activateであり、「active」ではないと注意喚起されています。

Android StudioをArctic Foxにバージョンアップするのを避けていたせいだろうか。。。

上記イシューには、環境変数を設定する、という解決方法を提示している方もいて、そっちが本質的な対処法にも感じるが、手間に感じたので、、、結局バージョンを下げる方を選択。

上記コマンドを実行したら、すごく長いメッセージが出て、ちょっと心配になったが、無事終了。

Android Studioを再起動後、ビルドしたら、無事エラーメッセージは消え、DevToolも起動できた。

※コマンド実行後に、Android Studioを再起動せずにビルドすると、エラーは消えるも、DevToolが起動できなかったので、再起動が必要な点に注意です。

 

2021/12/23 TextFormField内の文字が、なぜか上寄せになってしまう。

原因をよく分かっていないが、1行のみのTextFormField内の文字が、上寄せになってしまう。

前提として、高さを規定するためにContainerでラップしており、TextFormFieldには「InputDecoration」の「fillColor」属性で背景色を付けている。

フォントを変更したらこうなったのだが、別の箇所にほぼ同じ方法で設置しているTextFormFieldでは発生しない。

調べるとこちらの記事に様々な解決方法の議論がされていた。

最終的に、自分の場合は以下の手順で解決したのでメモ。

①decoration属性に、InputDecorationを設置し、「isCollapsed: true」にする。

これで位置は概ね上下中央に修正されたが、まだ若干ずれている。

また、TextFormFieldの高さがフォントギリギリまで縮んでしまい、かつ文字もTextFormFieldの左端ギリギリから始まるので、見栄えが悪い。

②InputDecorationに、「contentPadding: EdgeInsets.only(left: xxx)」を設定する。

これで左側にパディングを設けて、ギリギリから始まるのを改善する。

③ラップしているContainerにも「color」属性で、TextFormFieldと同じ背景色をつける。

これでTextFormFieldの高さが、フォントギリギリまで縮んでいることが見た目上、わからなくなる

④同じくラップしているContainerに、「alignment: Alignment.centerLeft」を設定する。

これで微妙にずれていた上下位置が完全に中央化された。

 

上記参考記事の中にあった「textAlignVertical: TextAlignVertical.center」は、自分の場合は効果がなかった。

こんな単純そうなことでも、未だに難しい。。

 

2021/12/19 TextFieldで、ScrollControllerの「animateTo」メソッドが機能しない

ボタンを押したら、TextField内のスクロールバーが上端や下端に動く機能を「amimateTo」メソッドで実装していたが、うまく動作しない。

やり方はこちらの記事でご紹介した方法。この記事のコードではうまく動作していたのだが。。

悪戦苦闘の結果、Stackを使っていた関係で、ScrollControllerのインスタンス(ここでは「scrollControllerO」とする)の設置位置が悪かったと判明。

「scrollControllerO」をTextField内に設置していたが、StackをラップしているSingleChildScrollViewの方に設置したら無事動作した(SingleChildScrollViewにもコントローラーを設置できると初めて知った。。)

↓動かなかった時のコード

Container(
  child: Scrollbar(
    child: SingleChildScrollView(
      child: Consumer<・・・>(
        return Stack( // CustomPaintとTextFieldをStackで重ねている
          children: <Widget>[
            CustomPaint(・・・),
            TextField(
              scrollController: scrollControllerO,  //ここに設置していた
              ・・

↓修正して正常動作したコード

Container(
  child: Scrollbar(
    child: SingleChildScrollView(
      controller: scrollControllerO,  //ここに設置位置を変更
      child: Consumer<・・・>(
        return Stack(
          children: <Widget>[
            CustomPaint(・・・),
            TextField(
              // scrollController: scrollControllerO,  //ここの設置を廃止
              ・・

なお、「scrollControllerO」をTextField内に設置したままで、SingleChildScrollViewをContainerの上に移動することでも、「animateTo」メソッドは動作したが、今度はCustomPaintが一緒にスクロールしなくなってしまった。

なので、Stackの要素を一緒にスクロールさせたければ、ScrollControllerのインスタンスは、Stackの上位に設置しないといけない、というのが現状の結論。

 

2021/12/18 pod installすると、「CocoaPods could not find compatible versions for pod “・・・”」のエラー

Flutterのパッケージを追加した後に、iOSで起動するため、pod installしたら、下記エラーが出た。

Google-Mobile-Ads-SDKのバージョン不整合が問題らしい。

[!] CocoaPods could not find compatible versions for pod “Google-Mobile-Ads-SDK”:
  In snapshot (Podfile.lock):
    Google-Mobile-Ads-SDK (= 7.69.0)
In Podfile:
google_mobile_ads (from .symlinks/plugins/google_mobile_ads/ios) was resolved to 0.0.1, which depends on Google-Mobile-Ads-SDK (= 8.11.0)

You have either:
* out-of-date source repos which you can update with pod repo update or with pod install --repo-update.
* changed the constraints of dependency Google-Mobile-Ads-SDK inside your development pod google_mobile_ads.
You should run pod update Google-Mobile-Ads-SDK to apply changes you’ve made.

過去にも、Firebase系のパッケージをインポートした際に、よく遭遇したエラー。

エラー文中の指示通り、「pod install –repo-update」で解決する事が多かったので、今回もやってみると、今度は以下のエラー。

[!] CocoaPods could not find compatible versions for pod “Google-Mobile-Ads-SDK”:
In snapshot (Podfile.lock):
Google-Mobile-Ads-SDK (= 7.69.0)
In Podfile:
google_mobile_ads (from .symlinks/plugins/google_mobile_ads/ios) was resolved to 0.0.1, which depends on
Google-Mobile-Ads-SDK (= 8.11.0)
You have either:
* changed the constraints of dependency Google-Mobile-Ads-SDK inside your development pod google_mobile_ads.
You should run pod update Google-Mobile-Ads-SDK to apply changes you’ve made.

「pod install –repo-updateをせよ」という提案文が無いだけで、他は全く同じ。

よく見ると、こちらの記事で整理したエラー内容とほぼ同じ。

依存関係をいったん解消する必要がありそうなので、上記記事を参考に、

「podfile.lock」を削除
→「flutter clean」実行
→「pub get」クリック
→「pod install –repo-update」実行

とやったら、無事pod installできた。

今後も度々遭遇しそうなので、忘れないように備忘。

 

2021/12/12 MaterialPageRouteが原因で、WidgetのY座標位置を正確に取得できない

こちらの記事で、デバイスによって異なるAppBarの高さ(Y座標の下端)を、GlobalKeyで取得し、それに応じてWidgetを最適配置する方法をご紹介している。

この方法に1つ注意点が判明。

他の画面から遷移してきた場合、Y座標位置がおかしい値になるケースがある。

具体的には、予想よりも大きい(下にずれた)値になる。

ネットで調べても原因が分からず、自分なりに検証したところ、どうやら画面遷移するときに、画面が下から出てくるため、遷移中の位置を取得してしまうことが理由だと分かった(自分なりに得た結論ですが、もし違っていたらスミマセンm(_ _)m)。

きちんと「WidgetsBinding.instance?.addPostFrameCallback」のメソッドを使い、ビルド完了後にGlobalKeyの位置取得をしているが、発生してしまう。

アニメーションがスタートした時点でビルドは完了した扱いになるのだろうか。。端末によって生じ方が異なるので、処理速度に依存するのかもしれない。。。

一般によく使用する「MaterialPageRoute」は、遷移後の画面が下から出てくる設定になっている。

そこで、「MaterialPageRoute」の使用をやめて「PageRouteBuilder」に変更し、「transitionDuration: Duration(seconds: 0)」としてアニメーションを無くすと、解消できた。

ただ、さすがに味気ないので、iOS仕様となる「CupertinoPageRoute」に変更したら、これでも解消できた。「CupertinoPageRoute」は、遷移後の画面が横から出てくる設定のためである。

遷移後の画面で、Y方向(縦方向)の座標を取得する必要がある場合は、自分でアニメーションを設定するのは大変なので、「CupertinoPageRoute」を利用するのが良さそう、というのが現状の結論です(画面遷移のアニメーションにこだわりが無ければですが、、)。

 

2021/12/10 プロジェクトのnull safety移行: エラーで「dart migrate」コマンドが通らない → オプション2つ付けて何とか通す

ついに、古いプロジェクトのnull safety移行に着手。

公式サイトのほか、こちらこちらの記事を参考にさせていただく。

まず、「flutter pub outdated –mode=null-safety」でパッケージのnull safety対応状況を調べると、現状で非対応なものが2つあった。

これらを対応済みの別パッケージに変更してコードを修正し、再度同じコマンドを入れると、

All your dependencies declare support for null-safety.

となり、未対応がなくなったことを確認できた。

なので、

dart pub upgrade –null-safety

を実行して「pub get」すると、予想どおりDart Analysisに沢山のエラーが出る。

気にせず

dart migrate

をすると、

Bad state: Error: package has unmigrated dependencies.

となってしまい、皆さんが紹介されているウェブ上のコード編集ツールのURLが表示されない。。

おかしい。未対応のパッケージが無いことは確認済なのだが。。

エラーメッセージの最後に、オプションを付けて、「dart migrate –skip-import-check」でやってみよ、とあるので素直にやってみると、今度は、

The migration tool didn’t start, due to analysis errors.

と出る。

Dart Analysisにエラーがあるのは分かっており、「それを今から修正するのが、ウェブ上の編集ツールなんじゃないの??」と思う。

こちらの記事の方が、全く同じことをおっしゃっていて、勇気づけられる。

今度はエラーメッセージに、「–ignore-errors」のオプションを付けてみよ、とあるので

dart migrate –ignore-errors

をやってみる。すると、

Aborting migration due to an exception.  This may be due to a bug in the migration tool, or it may be due to errors in the source code being migrated.  If possible, try to fix errors in the source code and re-try migrating.  If that doesn’t work, consider filing a bug report at:

バグかも知れないからレポートを提出してくれと。。

エラーメッセージからは、どうやらAdmob関連が悪さしているみたいなのだが、、、(コード自体はクラス名が変更になっているので、後で直すつもりだったが、、)。

ただ、エラーメッセージの中に、今度は「–ignore-exceptions」のオプションをつけると、とにかく進められるよ、と書かれている。

そのため、

dart migrate –ignore-errors –ignore-exceptions

のように、オプションを2つ付ける形で実行。

やっと、ウェブ上の編集ツールのURLが表示された。

その後は、予想どおりコード自体の修正作業で諸々苦労はあったものの、何とかnull safety移行を完了。

とにかくオプションを付けまくって、移行ツールのURLをゲットするところまで行ければ、何とかなりそう、というのが現状の結論です^^;

 

2021/12/7 AndroidとiOSとで、Googleサインインの挙動が違う

2つ目のアプリが無事、AppStoreでも承認され、リリースできたが、リリース前に発覚して修正することになった事項のメモ。

このアプリは、Googleサインインの機能を入れているが、GoogleドライブとGoogleカレンダーの2つにアクセスする場面があるため、Googleサインインが求められる場面も複数ある。

各APIを使用するには、GoogleSignInAccountのインスタンスが必要なので、他の場面でサインインしていたとしても関係なく、再度signInメソッドを実行し、GoogleSignInAccountのインスタンスを作成していた。

Androidの場合は、サインイン済のときは、サインインのダイアログがもう一度出ることはなかった。しかし、iOSの場合は、毎回ダイアログが出てしまう。これはユーザビリティが悪い。。

とは言え、インスタンスを使い回すことも難しいので、F4でGoogle SignInのソースを見て何かヒントが無いか見ていると、「signInSilently」というメソッドがあることを知る。

ソースの解説コメントを見ると、このメソッドなら、ダイアログを出さずにサインインしてくれる模様。

そこで、isSignedInメソッドでサインイン済か否かを判定し、サインイン済ならsignInメソッドではなく、signInSilentlyメソッドを使うよう変更。

無事、iOSでも度々ダイアログが出る状況を回避することができた。

パッケージのソースを眺めることでヒントに出うこともある、と実感しました。

 

2021/12/5〜12/6 iOS Appleの審査で、iOS 15.1だとATTの同意取得ダイアログが表示されないと言われてリジェクト

2つ目のアプリをAppleの審査に出したら、下記コメントのメールが来てリジェクト。。

Your app uses the AppTrackingTransparency framework, but we are unable to locate the App Tracking Transparency permission request when reviewed on iOS 15.1.

勉強不足だったが、ATT(App Tracking Transparency)の仕様が変わってしまった模様(公式サイト)。

iOS 15.1だと、アプリがアクティブ状態になる前に表示しようとすると、ダイアログが出ないらしい(まさかそんな事になっていたとは。。)。こちらの記事が大変参考になりました。

まず手元にiOS 15.1がなく、シミュレーターもiOS 15.1のものがないので、状況を確認できない。。

シミュレーターでやるにはXcodeのバージョンを13に上げる必要があるみたいだが、相当時間かかるだろうし、正直、今はやりたくない。。

実機はバージョンを上げると戻せなくなるので、iPhoneはiOS14を維持しつつ、手持ちのiPadをアプデすることに(iPad mini 4だったので、ギリギリiOS 15.1の対象内で助かった、、)。

で、iPadをiOS 15.1にして、TestFlight版で確認したが、ATTのダイアログはちゃんと表示される。なぜだろう。。

ネット記事を調べると、「ちゃんと表示されます」と返信して交渉する手もあるみたい。

ただ、自分は交渉して説得できる自信がなかったので、素直に修正することに。

現状のコードを見ると、最初の画面のbuildメソッド(MyAppクラス内)の直下で、単純にATTのメソッドを呼び出していたので、ビルド完了前にダイアログが出てしまっていた

そのため、MyAppクラスをStatefulに変更し、initStateの中で、「WidgetsBinding.instance?.addPostFrameCallback」のメソッドを使い、ビルド完了後にATTが呼ばれるように変更(この結論に至るのに結構苦労しました、、、)。

改めてiOS 15.1の実機でATTダイアログが出ることを確認。

Appleに再申請したら、無事承認されました。

コード修正する上で、こちらの記事がとても参考になりました。ありがとうございました!

 

2021/12/1〜12/2 iOSで、image_pickerのカメラアクセスを許可しないとエラーになり、正常動作できない

ここ数日、この問題に苦しんだ。。

2つ目のアプリをGoogle Playでリリースした後、App Storeにリリースすべく、TestFlightで試していたときに気づく。

image_pickerでカメラやギャラリーにアクセスする際、Androidだと出ないが、iOSだとユーザーにアクセス許可を求める同意画面が出る。

ここで「許可しない」を選ぶと、pickImageメソッドが完了できず、アプリが止まってしまう。。

しかも、アクセス許可の同意画面は1回しか出ないので、アプリを再起動して再度カメラやギャラリーを使おうとすると、即アプリが止まってしまう。。

調べると、「permission_handler」パッケージを使って、ユーザーの許可状況に応じて同意画面を再表示できる模様(こちらの記事はとても参考になります)。

ただ、設定ファイル(Podfile)をかなりいじる必要があり、バージョン依存も起こりそうなので気が進まず。。

結果、不許可時のエラーは、try catch文で検知できるとわかったので、pickImageメソッドの部分をtry catchでくくって、エラーのときはnullを返し、トーストメッセージで「iPhoneの設定で有効にしてください」と設定変更を誘導つつ、処理を先に進めるように修正した。

この方針を選択するにあたっては、こちらの記事が大変参考になりました。ありがとうございます!

image_pickerのアクセス不許可問題については、触れている記事が少なかったので、焦りました。。

 

2021/11/26 GooglePlayにアプリをリリースしたら、Google SignIn(Googleサインイン)ができなくなった

今日は、1つの記事に本当に助けられたので、拡散したい気持ちも込めて記録。

今般、2つ目のアプリをこちらにリリースしました。

このアプリは、GoogleのAPIを使う関係で、Google サインインを実装しており、実機やエミュレーターのテスト時には問題なくサインインできていた。

しかし、リリースしたアプリをGoogle Playからダウンロード(正確には内部テスト状態のアプリをダウンロード)して確認したところ、なぜかサインインができない!

※自分がサインイン失敗時に仕込んでいたエラーメッセージが表示され、実際にサインインもできていない。

リリースの最終局面でこのエラーは辛い、、、と青ざめて、ダメ元で検索したところ、とてもありがたい記事が。

なんと、Google Play Consoleから「アプリ署名鍵の証明書」(※)の「SHA-1 証明書のフィンガープリント」を確認し、FirebaseのAndroidプロジェクトに追加登録する必要があるとのこと。

※現在のPlay Consoleでは、左側メニューの「設定」→「アプリの完全生」で確認できます。

Firebase Authenticationを設定したときに、当然ながらSHA-1の登録はやっていた。これはネット上にある様々なチュートリアル記事で書かれている話。

しかし、Google Playにリリースする際に、追加でSHA-1の登録が必要という情報は、見たことがなかった。。。

確かに上記の記事どおり、「アプリ署名鍵の証明書」をFirebaseに追加登録したら、無事、アプリからGoogle サインインできるようになった。

この点を解説してくれている記事は、上記の記事以外に見当たらなかったので、本当に助けられました。ありがとうございました!

 

2021/11/22 iOSシミュレーターでのみ、TextFieldで「’readOnly && !obscureText’: is not true」のエラーが発生

TextField内で、特定の正規表現にマッチした文字のスタイルを変更するコードを実行したところ、Androidエミュレーターでは正常に動作するのに、iOSシミュレーターで実行すると、以下のエラーが出て、お決まりの真っ赤な画面に。

‘package:flutter/src/rendering/editable.dart’: Failed assertion: line 2376 pos 14: ‘readOnly && !obscureText’: is not true. See also: https://flutter.dev/docs/testing/errors

気になるのは、コンソールの方には何もエラーが表示されないという点。。

いつも画面にエラーが出るときは、コンソール(デバッグウィンドウ)の方にも出るのだが。。

エラーは、正規表現にマッチした瞬間に発生する。。

エラー文によると、TextFieldが、「読み取り専用 かつ マスキングしない」の条件を満たしていないので、エラーになったらしい。

エラーのとおり「editble.dart」ファイルの2376行を見てみたが、確かに「assert(readOnly && !obscureText);」とあるので、assertに引っかかった模様。。

しかし、特段、TextFieldのプロパティに、readOnlyもobscureTextも設定していないのだが。。。

仕方なく、日本語・英語でググりまくるも、類似の情報が全然引っかからない。

そこで試しにiOS実機で実行すると、なんとエラーにならなかった

シミュレーターだとうまくいくが、実機だとエラーになる、という話はよく聞くが、今回はその逆。。

結局、未だに原因は不明だが、実機では問題ないのでいったん良しとしよう。。

 

2021/11/20 Image Pickerで読み込んだ画像が、撮影した向きどおりに表示されない

Image Pickerでカメラ撮影した画像を、画面に表示する処理を作っているが、横向きで撮影しても縦向きで表示されてしまうことがある。

調べてみると、こちらに対処法のスレッドがあった。

readAsBytesメソッドでUint8List型に変換した後、decodeImageメソッドでImage型に変換し、それをbakeOrientationメソッドにかけると、画像が「EXIF:Exchangeable Image File Format」データを持っていれば、その中にある向きのデータを見て、適切な向きに修正したImage型を生成してくれる、という方法らしい。

さっそく試すと、確かにできた。が、、、カメラ撮影してから画面に表示されるまでに異常に時間がかかるようになってしまった。。。

その他にも方法があるようだが、画像データそのものを直しにかかると処理に時間がかかりそうなので、表示するときにユーザーが回転ボタンをタップして調整できるようにする方針に変更。

調べると、こちらの記事にとてもありがたい情報が。

RotatedBoxクラスで表示部分をラップして、quarterTurnsプロパティをセットすればよいらしい。

ただ、quarterTurnsに「90」と入れたら、90度ではなく180度回転してしまった。

F4でソースコードを調べると、どうやらquarterTurnsには、90度ずつ何回回転させるか、の回数(int型)を指定するらしい。

つまり、0、1、2、3の4通りを設定すればよい。

結果、無事、思い通りの実装ができました。

情報を共有いただいた皆様、ありがとうございましたm(_ _)m

 

2021/11/18 Google APIへの接続で、「status: 401, message: Request had invalid authentication credentials」のエラー(別原因と判明)

以前、2021/10/22の日記で書いた内容の訂正。

Google APIへの接続時に出る下記エラーについて(OAuth2の認証がうまくいかない)。

DetailedApiRequestError(status: 401, message: Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.)

対処法は、エミュレーターの再起動かと思っていたが、その後も同じ状況が発生し、再起動しても解決しなかった。

前回発生したときは、そもそもこのエラーがどういう状況で生じるのか、よく分かっていなかったが、今回、OAuthの同意画面を経て接続承認したGoogle アカウント上で、いったん接続を解除し、再度、同意画面から接続承認を得て、APIにアクセスしようとすると、発生すると分かった。

試行錯誤の末、結論としては、エラーが出てから1時間待って再度接続を試みると、エラーは生じなくなる、とわかった。

理由は、こちらこちらの情報にある通り、トークンの有効期限が1時間だかららしい(公式サイトではまだ見つけられていないですが、、)。

根本的にエラーを生じさせないためには、恐らく、リフレッシュトークンを使った接続方法に変える必要がありそうだが、flutterでやる方法がよく分からず、現在調査中。。

 

2021/11/13 Google Play Consoleの「メインストアの掲載情報」(アプリ名、簡単な説明)で、ガイドラインを遵守していないと警告

Flutterの話ではないが、リリースしているAndroidアプリについて、Google Play Consoleの「メインストアの掲載情報」に2箇所、警告が出ているのに気づく。

 

1つ目は「アプリ名」で、

  • 30文字以内にせよ ※以前は50文字までOK
  • 特殊文字の使用はNG

とのこと。

近々、ポリシーの変更が予定されているらしい。

こちらの説明ページを見ると、かなり細かくアプリ名やアイコンの表示方法が規定されている。

仕方なく、素直に文字数を30文字以内に修正し、括弧(「」)やハイフン(-)も削除したら、無事、警告が消えた。

 

2つ目は、「簡単な説明」で、

  • 過度に句読記号を使用するな

とのこと。

確かに、アプリの機能を「、」で列記する書き方をしていた。

とは言え、80文字の制限があるので、文章でつらつら書くと字数オーバーになってしまう。。

そこで、こちらのページにあるガイドラインの説明をよく読んでみると、

単語、ピリオド(.)、カンマ(,)、特殊文字(& など)の間にスペースが必要な場合は、スペースを使用してください。

Play Consoleヘルプ

と書かれていたので、単純に「、」をスペースに変更

これで無事、警告が消えた。

 

ちなみに「メインストアの掲載情報」は、修正したあとに、画面下部の「保存」ボタンを押すと、自動的にGoogleの審査中となり、しばらく待つとGoogle Playに反映されるようになります。

 

いつの間にか警告が出ていて驚いたけど、落ち着いてガイドライン読んで対処するしかないですね。

 

2021/11/12 「Open Android Module in Android Studio」がグレーアウトして開けない場合の対処法

Android Studioで、古いFlutterのバージョンで作成したファイルを、

「android」フォルダで右クリック
→「Flutter」
「Open Android Module in Android Studio」

を選択し、Androidプロジェクトとして開きたいけど、項目がグレーアウトしていて開けない、という問題。

以前は、こちらの記事で対処法を知り、対処していた(ありがとうございます!)。

 

ただ、今回、以下2つの記事を知り、もっと楽な方法を教えていただく(いずれも大変分かりやすい記事なので、本記事ではリンクを貼らせていただくに留める)。

 

以前の方法でも解決できていたので有り難かったけど、開く度に対応が必要だったので、やや手間だった。

一方、今回知った方法であれば、一度設定すれば済むのでとても楽

教えていただき、ありがとうございました!

 

2021/11/6 配列内の複数の要素を同時に消そうとしたら「RangeError (index): Invalid value: Not in inclusive range」のエラー

恐らく初歩レベルのエラーでお恥ずかしいですが、備忘も兼ねて記録。

配列内の複数の要素を同時に消したいと思い、削除用のインデックス配列を作って、下記のようにForループで削除処理を回してみた。

final testList = ["test1", "test2", "test3", "test4"];
final deleteIndex = [1,3];
for (int i = 0; i < deleteIndex.length; i++) {
    testList.removeAt(deleteIndex[i]);
}

これで、testList=[“test1”, “test3”]となってくれることを期待したのだが、以下のようなエラーに。

RangeError (index): Invalid value: Not in inclusive range 0..2: 3
When the exception was thrown, this was the stack: 
#0      List.[] (dart:core-patch/growable_array.dart:254:60)
#1      List.removeAt (dart:core-patch/growable_array.dart:23:22)

初め理由がわからず悩んだが、よく考えたら、forループで回すと、削除処理のたびに配列長が短くなり、消したい要素のインデックスも変わってしまうと気づく。。

「そのインデックスもうなくなってるよ(消されて配列短くなっているから)」

ということですね。

配列要素の値そのものを指定すれば、forループで回しても消せるのだが、今回は値を先に知ることができない事情があり、なんとしてもインデックスを指定して同時に消したい。

こういう場合、どうしたらいいのだろう?と調べていると、ありがたいことにこちらの記事に、「removeWhere」というメソッドがあることを教えていただく。

そこで、removeWhereとcontainsメソッドを使って、下記のようにコード修正したら、無事、同時に配列内の複数要素を削除する事ができた。

final testList = ["test1", "test2", "test3", "test4"];
final deleteIndex = [1,3];
testList.removeWhere((value) => deleteIndex.contains(testList.indexOf(value)));

大変初歩的な内容かもしれませんが、、同じエラーにぶつかった方のご参考になれば幸いです。

 

2021/11/1 AdMobでバナー広告を2つ表示したら「This AdWidget is already in the Widget tree」のエラー

AdMob(google_mobile_ads)を導入し、画面の下部にバナー広告を表示した状態で、画面内のボタンタップ時にダイアログを表示するときにも画面上部にバナー広告を表示するようにしたところ、以下のようなエラーが発生。

The following assertion was thrown building AdWidget(dirty, state: _AdWidgetState#18c5b):
This AdWidget is already in the Widget tree
If you placed this AdWidget in a list, make sure you create a new instance in the builder function with a unique ad object.
Make sure you are not using the same ad object in more than one AdWidget.

既にウィジェットツリーに広告ウィジェット(AdWidget)が存在しているため、二重では表示できないよ、ということらしい。

ネットで調べると、別の広告IDのバナーを表示すれば良い、という情報もあったが、AdMobに広告ユニットを追加しなければならないので、他の方法がないか模索。

結果、使用する広告ID自体は同じだが、その広告IDを代入するプロパティ(ゲッター)を、画面下部用とダイアログ表示時用の2つ用意し、それぞれをBannerAdクラスのadUnitId属性の引数として与える形で、BannerAdクラスのインスタンスを2つ作成したらうまく行った。

エラーメッセージをよく読んだら、「新しいインスタンスを作成せよ」とあるので、ちゃんと書いてありましたね。後で気づきました。。

 

2021/10/31 「pod install」したら、「CocoaPods could not find compatible versions for pod “Firebase/Auth”」というエラー

「google_mobile_ads」のパッケージを入れた後(これが原因かわかりませんが、、)、iOS実機で動かすため「pod install」したら、以下のようなエラーが出る。

CocoaPods could not find compatible versions forpod “Firebase/Auth”:  In snapshot (Podfile.lock):   Firebase/Auth (= 8.5.0)
  In Podfile:    firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) was resolved to 3.0.2, which depends on      Firebase/Auth (= 8.8.0)
Specs satisfying the `Firebase/Auth (= 8.5.0), Firebase/Auth (= 8.8.0)` dependency were found, but they required a higher minimum deployment target.

どうやらプロジェクトで使っている「firebase_auth」のバージョンが、pod installで入れようとするバージョンと整合しない?ということらしい。

特に「firebase_auth」のバージョンは変えておらず、以前は普通にpod installできたのに謎。。

pod install対策としていつもやっている、「podfile.lock」の削除、「flutter clean」などしてからpod installしても変わらない。

調べると、stackoverflowのこちらの記事

pod install --repo-update

をすると良いとの事だったので、やってみると、こんな感じで最後の1文だけエラーが出た。

・・・(略)・・・
Analyzing dependencies
cloud_functions: Using Firebase SDK version ‘8.8.0’ defined in ‘firebase_core’
firebase_auth: Using Firebase SDK version ‘8.8.0’ defined in ‘firebase_core’
firebase_core: Using Firebase SDK version ‘8.8.0’ defined in ‘firebase_core’
[!] GoogleAppMeasurement requires CocoaPods version >= 1.10.2, which is not satisfied by your current version, 1.10.1.

どうやら、CocoaPodsのバージョンが古いことが原因っぽい。

更に調べてこちらのteratailの記事を参考に、sudo gem install cocoapodsをやり、その後でもう一度「pod install –repo-update」をしたら、

・・・(略)・・・
Installing Firebase (8.8.0)
Installing FirebaseAuth (8.8.0)
Installing FirebaseCore (8.8.0)
・・・(略)・・・

のように、無事、バージョン8.8.0がインストールされた模様。

その後、問題なくiOS実機で実行できた。

忘れた頃にまた食らいそうなエラーなので、忘れないようにメモしました。

  

2021/10/23 「oktoast」で表示されないトーストが発生→「OKToast」のラップはアプリ内で1回しか使えなかった。

トーストメッセージの表示には「oktoast」パッケージを使用している。

恐らくメジャーなのは「fluttertoast」だと思われるが、自分の場合、「fluttertoast」だと、どうやってもgravityの設定が機能せず、必ずボトムの位置にトースト表示されてしまう。

その点、「oktoast」だと表示位置が思い通りいくので愛用していたが、今日、なぜか表示されるトーストと表示されないトーストが発生した。

分からず調べていると、こちらの記事に情報が。

「oktoast」は、事前にトースト表示するWidgetを「OKToast」クラスでラップする必要があるが、このラップ処理は、アプリの中でなんと1回しか使えないらしい。

結果、最上位の「MaterialApp」を「OKToast」でラップしたら、全てのトーストが問題なく表示された。

main.dartに「OKToast」クラスがあるのは、ちょっと違和感あるけど、仕方ないか。。

  

2021/10/22 Google APIへの接続で、「status: 401, message: Request had invalid authentication credentials」のエラー(後日、別原因と判明)

※下記内容は、2021/11/18の日記にて内容修正しています。

今までFlutterからGoogle API(Google Driveなど)にアクセスできていたのに、今日、エミュレーターでアクセスしたら、突然こんなエラーが。

DetailedApiRequestError(status: 401, message: Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.)

OAuth2の認証がうまく行ってない模様。

リンク先のGoogleのサイトを見てもよく分からず。。

ネットで色々調べてみると、OAuthの同意画面設定がされていないとか、FirebaseにSHA-1の設定がされていないとかの情報は見つかるものの、いずれも対応済なので、理由が分からず詰まる。。

必死で調べていると、こちらの情報から、Googleの公式サイトで、Google Cloud上のアプリ設定が、テストモードかつ外部ユーザーの場合は、トークンの有効期限が7日で切れる、と書かれていることを教えていただく。

これが原因か!?と思い、解決策を色々調べていると、つまるところ、Google Workspaceを契約しているサービスアカウントでテストしない限り、この期限をクリアできない模様。でも何とか無料の契約の範囲でやりたい。。

なので、何とかフリーのアカウントでもリフレッシュトークンを発行する方法が知りたいと思って調べていると、今度はこちらの情報に、テスト中はトークンが初回しか発行されないが、テストで使っているGoogleアカウント上で、当該アプリの接続をいったん解除すると、もう一度発行できるとの情報が。

しかし、期待してやってみるも駄目。。変わらずアクセスできない。

その後、認証方法のコードを色々と書き換えてみるものの、状況は変わらず。。

諦めかけたところで、ふと、試しにAndroid実機でやってみようと思い、実行すると何故か普通にアクセスできた。

あれ?もしかしてエミュレーターの問題?と思い、Androidエミュレーターを再起動したら、、、

なんとアクセスできる状態に戻った。。

ましても再起動が解決策、、、今回はてっきり認証関係の根深い問題だと思ったので、再起動は全く頭に思い浮かばず。

なぜエミュレーターで突然アクセスできなくなったかは、知識不足で分かっていません。。。また調べたいと思います。

ただ、いくらネットを調べても載っていない解決方法だったので、、、同じ状況の方のご参考になれば幸いです。

 

2021/10/20 「The instance member ‘変数名’ can’t be accessed in an initializer」というエラーへの対処法

クラスの直下で、下記のように定義した変数を、すぐに別の変数に代入しようとすると、

class SampleClass {
  int aaa = 1;  // aaaという変数を定義して、
  int bbb = aaa + 1;  // そのaaaを使ってbbbという変数を定義すると、、、
・・・(以下略)・・・

先に定義した方の変数「aaa」に赤い波線が出て、

The instance member ‘aaa’ can’t be accessed in an initializer. (Documentation) Try replacing the reference to the instance member with a different expression

というエラーになる。

インスタンスメンバーは、変数の初期化には使えないよ、いうエラー。

Documentationのリンク先を見ると、「aaa」をstatic宣言するか、別の値に変更する必要があるとのこと。

staticを使いたくないとき、Stateful Widgetであれば、initStateメソッドの中で「bbb」への代入式を書けば、「aaa」を使うことができる。

しかし、例えば、MVVMモデルで状態管理をしている場合に、ViewModelのクラス内で初期値の設定をするときは、initStateメソッドは使えないので、わざわざもう一度同じ値を書いて代入しなければならず、面倒。。。

ただ今回、たまたま「bbb」にlateをつけてみたらエラーが消えることを発見。

// 修正後
class SampleClass {
  int aaa = 1;
  late int bbb = aaa + 1; // lateをつけて宣言
・・・(以下略)・・・

lateをつけて、いったん「後で代入するよ」と言っておけば、その後すぐに代入してもOKということなのか。。。?

公式のページにも記載がないので、詳細は分かりませんが、ともかくこれで初期値の代入処理が楽になりそうです。

  

2021/10/18 「gallery_saver」パッケージを使ったら、Kotlinのバージョンがおかしいというエラー

以前、こちらの記事で、ユーザーがアクセス可能な端末内のフォルダに保存する方法を整理したが、画像ファイルだけであれば、「gallery_saver」というパッケージを使うと簡単にできそう、という情報を知る。

早速、試してみると、実行直後に、

e: Incompatible classes were found in dependencies. Remove them from the classpath or use ‘-Xskip-metadata-version-check’ to suppress errors
・・・・(略)・・・・
Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.5.1, expected version is 1.1.15.
・・・・(略)・・・・

のようなエラーが出る。。。

どうやらKotlinのバージョンが合っていないらしい。

エラーの難解さに諦めかけたが、粘って調べてみると、こちらの記事に、

gradleフォルダ内の「build.gradle」ファイル冒頭の「ext.kotlin_version = ‘1.3.50’」を「ext.kotlin_version = ‘1.4.32’」に変更すると解決する

との情報が。

※「gallery_saver」で調べても、ほとんど情報が見つからなかったので、エラーメッセージの方で検索したら出てきた。

実際、この方法で修正してみると、エラーが出ずに通った!

「gallery_saver」はとても便利。

await GallerySaver.saveImage(パス名);

の1文だけで、Androidは画像フォルダ、iOSは写真フォルダに画像ファイルをエクスポートできる(「AndroidManifest.xml」と「info.plist」に若干記載は必要だが、パッケージのReadMeページを見てやれば簡単)。

いずれもユーザーがアクセスできるフォルダです。

File型も生成する必要がなく、非常にコードが短くて済むので、オススメのパッケージです。

 

2021/10/14 Dividerでなぜか横線が表示されない

Divider()ウィジェットで、引数にheight、thickness、colorなどを設定しても、何故か横線が表示されず悩む。

仕方なく色々と調べると、こちらの情報が見つかり、どうやらRowが影響してそうだと分かる。

検証した結果、Row()の中に、2つのContainerを横に並べ、右のContainer内にColumnで3つのWidgetを縦に並べており、その2つ目のWidgetがDividerだったが、これに横幅(width)が設定されていなかった事が原因と判明。

Columnの1つ目と3つ目のWidgetに同じ横幅を設定していたので、2つ目のDividerにも自動で同じ横幅が設定されると思っていたら甘かった。。

要は、Dividerを単独で使うと画面いっぱいに横線が引かれるが、Rowで横並べにした場合には、DividerをContainerなどで括って横幅(width)を設定しないと描画されないらしい。

今更こんな基礎的なことですが、また1つ勉強になりました。

 

2021/10/11 今まで問題なかった「initState」メソッド内の「context.read」が、いつの間にかエラーに(一応解決)

Stateful Widgetの「initState」メソッドの中では「context」は使えない、「didChangeDependencies」を使えばできる、といった情報はよく目にする。

しかし、自分はMVVMの設計方法でProviderを使っているが、View層のStateful Widgetの「initState」内で、「context.read」メソッドを使ってもエラーは生じていなかった。

※ロジックはよく分かっていないが、、、Android Studioでは、contextが紫の文字になって、F4でソースにアクセスできるので、一番大元のcontextにアクセスすることで可能になっている?

ただ、別の部分のコードをいじっていたら、いつの間にか「initState」内の「context.read」に赤い波線が出ていて

The method ‘read’ isn’t defined for the type ‘Context’. (Documentation)
Try correcting the name to the name of an existing method, or defining a method named ‘read’.

というエラーになってしまった。

直接関係する部分は一切いじっていなかったので、解消に苦しむ。。

ネットで調べても「そもそもinitState内ではcontextは簡単には使えないよ」的な情報しか見つからず、、「でも自分は今までできていたんだ!」と思うと納得できず。。

自分の変更履歴を探っていった結果、なんと、下記1文で「path」パッケージをインポートしたことが原因と判明

import 'package:path/path.dart';

上記を削除したら、無事、initState内のcontext.readからもエラーの赤波線が消えた。

理由は全く分かっていないが、恐らくpathパッケージ内でもcontextを指定していて、競合してしまうから?この辺は見当違いだと思うので、後で勉強します。

まさかインポート文入れただけで、他の部分に影響が及ぶとは。。

 

2021/10/10 Android Studioで、option+Enterが効かなくなった(解決)

いつもclassを別のclassでラップしたいときに使う「option+Enter」(WindowsだとAlt+Enter)がなぜか突然効かなくなった。。

コード補完機能が効かなくなったときの対処法である、「Dart Analysis」タブから「Restart Dart Analysis Server」をやってみても解消せず。。

定番のAndroid Studio再起動をやっても変わらず。

結果、ググったところ、以下のズバリ記事に助けていただきました。ありがとうございます!

確かに、Preferences → Editor → Intentions の 「Dart」のチェックが外れていた。

何でだろう?何もしていないのに。。チェックしたら無事、option+Enterが復活。

ともかく解決してホッとしました。

 

2021/9/20 Card内の配置でなぜか「A RenderFlex overflowed by 8.0 pixels on the bottom.」のエラーになる(解決)

Cardの中にColumnで縦にWidgetを並べようとした際、きちんとCardクラスをラップしたContainerにheightを設定し、それに収まるように計算して配置したのだが、なぜか「BOTTOM OVERFLOWED BY 8.0 PIXELS」が画面表示されてしまう。

Card内に設定されているPaddingもきちんと考慮し、何度も計算してColumn内の個々のWidgetのheightを設定したはずなのに、「なぜ8pixelもズレるの?」と詰まる。

ネットで調べても同様の報告は見つからず、試行錯誤の結果、

Cardクラスには、デフォルトで上下左右にMarginが4.0pixelつく

ということを理解。

各Widgetのサイズを規定するためにラップした各Containerに別々の色を付けて検証したところ、Cardの枠線の外側にも色がついたので気づいた。そこで、F4キーでCardクラスの中身を見てみると、確かにデフォルトで4.0のMarginが付くと記載があった。

Marginなので、Cardの枠線の内側ではなく、外側に余白がついてしまう。これは盲点。。

DevToolを使うのも良いですが、なかなか見方が難解なので、Containerに色を付けて検証するのは、手軽で良いかもしれません。

 

2021/9/18 Android エミュレーター内の「ファイル」アプリで、ファイルやフォルダの選択しかできない問題への対処

以前も発生して解決できなかったのだが、自分が頻繁に利用しているPixel4のAndroid エミュレーター(Emulator)において、標準搭載している「ファイル」アプリを開いた際、ファイルやフォルダの選択はできるが、ファイル自体を開いたり、フォルダの中に入ったりすることができない現象に見舞われた。。

はっきり再現できていないが、自作のアプリからFile Pickerなどを使ってエミュレーター内のファイル取得等をやっていると、いつの間にかその状況になっている気がする。。 

何とか解決したかったので、ネットで調べまくったが、英語や日本語で調べても情報が見つからず。。(同じ現象になる方はいないのだろうか、、、?)

結果、エミュレーター右側のバーにある電源ボタンを長押しして再起動してみたら治った!

相変わらず再起動は最強です!同じ現象に陥った方のご参考になれば幸いです。

 

2021/9/11 正規表現を使ったマッチングが何度やっても成功しない

if (RegExp(r’^[0-9]+$’).hasMatch(変数名)) ・・・みたいなマッチング処理をしたかったけど、絶対マッチするはずの変数が、何度やってもマッチングされず詰まる。

何度もコピペしたネット記事を見たけど、間違っていない。。

結局、「0-9」のハイフンが、全角の「–」になっていたと判明w

相変わらずこんな基本的なことで詰まってしまった。

・半角ハイフン -

・全角ハイフン −

微妙な長さの違いですね。。

ネット記事のコピペは便利ですが、半角になっているかはチェックしたほうが良さそうです。

 

2021/9/6 Device File Explorer内のアプリ専用フォルダの情報が更新されない問題への対処

アプリ専用フォルダ内にファイルを出力したとき、Device File Explorerを開いてフォルダ内を見ても反映されないので、いつもAndroid Studioを再起動しており、とても手間だった。。

でも、Device File Explorerの上部にあるエミュレーターのプルダウンリストで、該当のエミュレーター名を再選択すると、リフレッシュがかかり、アプリ専用フォルダ内の情報が更新されることに気づいた。

これでだいぶ楽になります!(知らなかったの自分だけかもしれませんが、、)。

 

2021/9/5 DevToolを起動したら「127.0.0.1 で接続が拒否されました。」のエラー

突然、DevToolを起動できなくなった。

Chromeで「127.0.0.1 で接続が拒否されました。」と表示されて接続できない。ファイアーウォールやプロキシ設定を見直すよう、コメントも出ている。。

調べると、こちらの記事などで、「flutter packages pub global activate devtools」をやってみると良いと知ったので、試してみるも、変わらず。。。

flutter cleanも効果なし。

結果、Android Studioを再起動したら無事アクセスできた。

色々調べると、過去にもDevToolが更新されるとこういった事が起こる模様。

やはり再起動は最強です。

 

2021/9/2 Google SignInでCalendar APIに接続できない(解決)

先日、Google SignInのscopeにGoogle CalendarのAPI(https://www.googleapis.com/auth/calendar)を指定したら、グルグルが回り続けてサインインできない問題について、Googleの事前承認が得るしか手がないと思っていたら、こちらの記事を発見。

Google Cloud Platformで公開ステータスを「テスト」にすれば、テストユーザーを追加できて、テストユーザーに対してはGoogleの承認なしでもGoogle CalendarのAPIにアクセスできることが分かった。

これでリリースするまでは色々気にせず実験できそう。Flutter縛りで検索してると、情報が限られてしまうけど、言語の縛りを無くして調べたら有益な記事にたどり着けた。役立つ記事をありがとうございました。

 

2021/9/1 Null check operator used on a null value

「Unhandled Exception: Null check operator used on a null value」のエラーに苦しむ。。

event.reminders!.overrides = xxxx; みたいな代入をしたら発生。

調べたらこちらの記事がとても詳しくて、勉強になった。初期化されていないインスタンスに「!」を付けると発生する模様。

とはいえ、「どうすればいいの?」と悩んだけど、下層から順番に

overridesO = コンストラクタ名(xxx: aaa, yyy: bbb); ※右辺は名前付き引数ありコンストラクタ

→remindersO = コンストラクタ名(overrides: overridesO, zzz: ccc);

とインスタンスを作っていき、最後に、

event.reminders = remindersO;

と代入したら無事行けた!確かにこの方法なら「!」を付ける必要がないですね。

「.」を使って一気に最下層のプロパティに代入するのはNGと理解。

きっと初歩的なことだと思うのですが、、、今更ながら勉強になりました。

 

2021/8/31 Google SignInでCalendar APIに接続できない

Google Calendar APIへの接続を紹介されている複数の記事(こちらこちら)を参考にさせていただき、サンプルコードを動かすも、Google SignInをしたところで、グルグルが回り続けてサインインできない。。(←後日、解消しました!)

Google Cloud Platformで、OAuth同意画面を設定しなくても、Google Driveには接続できたのに。

仕方なく、OAuth同意画面の設定をやってみると、スコープ設定でGoogle Calendarのほぼ全てのAPIが機密性が高いスコープ扱いになっていた。。最近変わったのだろうか。

Google Driveは「drive.appdata」や「drive.file」は鍵マークが無いので、非機密扱い。だからGoogle Driveは接続できたんだと理解。

どうやら古いAPIだと、Google CalendarもGoogle Driveと同様、アプリだけが作成するスケジュールの読み書きができるAPI(calendar.app.created)があったみたいで、それは非機密扱いの模様。

OAuth同意画面のスコープ設定では「calendar.app.created」を選べるが、実際にアクセスすると、「もう使えないよ」とメッセージが出る。自分のやりたいことにはちょうどよい仕様だったのに残念。。

となると、Googleから機密性が高いスコープである「calendar」の利用承認を得ないといけない。。どうするか要検討。。

タイトルとURLをコピーしました