Flutter エラー・バグ日記

※当サイトは、アフィリエイト広告を利用しています

(2023.9.24更新)

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

実際にはエラーでもバグでもなく、自分の仕様への理解不足で思うように動作しなかっただけ、という話も多々含まれますw。

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

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

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

なお、エラー発生時に試して有益だった、一般的な対処法を整理しましたので、よろしければこちらもご覧ください。


2023/9/23 TextFieldのToolbarに追加した項目をタップしてもToolbarを消せない

日記の内容はこちら↓

 

2023/9/12 iOS審査:Guideline 5.1.1(v) - Data Collection and Storageの違反指摘でリジェクト

日記の内容はこちら↓

 

2023/9/6 iOS審査:Guideline 4.8 - Design - Sign in with Appleの違反指摘でリジェクト

日記の内容はこちら↓

 

2023/6/25 App Store Connectへのアップロード時に「Certificate expires in ## weeks」の警告

日記の内容はこちら↓

 

2023/5/24 !!! FAILED BINDER TRANSACTION !!!という表示が出てAdMob広告が表示されない

日記の内容はこちら↓

 

2023/5/15 GoogleService-Info.plist file not foundとなり、iOSでGoogleサインインできない

日記の内容はこちら↓

 

2023/5/7 Firebase In-App Messagingの「デバイスでテスト」のメッセージが届かない

日記の内容はこちら↓

 

2023/5/3 再びAdMobからポリシー違反警告(リワード広告 - 許可されない実装方法)

日記の内容はこちら↓

 

2023/5/1 Include of non-modular header inside framework module 'FirebaseSessions.FIRSESNanoPBHelpers'のエラー

日記の内容はこちら↓

 

2023/4/23 「バージョン###で不足しているdSYMがCrashlyticsで検出されました」の通知

日記の内容はこちら↓

 

2023/4/21 AndroidエミュレーターがGoogleのマークが出たまま起動しない

日記の内容はこちら↓

 

2023/4/1 No implementation found for void io.flutter.embedding.engine.FlutterJNI.nativeUpdateRefreshRate(float)のクラッシュ報告

日記の内容はこちら↓

 

2023/3/30 App Store Connect Operation Error(SDK Version Issue)の警告

日記の内容はこちら↓

 

2023/3/28 Google Play Consoleのリリース前レポートで「Unable to start activity」のクラッシュ報告(Google Wear)

日記の内容はこちら↓

 

2023/3/27 GitHubにgit pushしたら「REMOTE HOST IDENTIFICATION HAS CHANGED!」と出てエラー

日記の内容はこちら↓

 

2023/3/21 flutter_typeaheadの候補リスト部分が、一部の端末だとタップできない

日記の内容はこちら↓

 

2023/3/19 flutter_local_notificationsで通知が表示されない(Android13)

日記の内容はこちら↓

 

2023/2/12 CocoaPods could not find compatible versions for pod "GoogleAppMeasurement"のエラー

日記の内容はこちら↓

 

2023/2/9 Flutter3.7更新時: No file or variants found for assetのエラー

日記の内容はこちら↓

 

2023/2/5 SharedPreferencesPluginでambiguous use of 'register(with:)'のエラー(Flutter3.7更新時・Macデスクトップ)

日記の内容はこちら↓

 

2023/2/4 PathProviderPluginでambiguous use of 'register(with:)'のエラー(Flutter3.7更新時・Macデスクトップ)

日記の内容はこちら↓

 

2023/2/3 Flutter3.7アップグレード後の不具合対応

日記の内容はこちら↓

 

2023/1/28 AdMobインタースティシャル広告のload完了をawaitで待てない

日記の内容はこちら↓

 

2023/1/22 file_pickerで取得したファイルがiOSのtmpフォルダからすぐ消える

日記の内容はこちら↓

 

2023/1/10 Failed to send request: {"jsonrpc":"2.0","id":…のメッセージが出る

日記の内容はこちら↓

 

2023/1/8 iPhoneを横向きにすると、cameraパッケージのプレビュー幅が狭くなる

日記の内容はこちら↓

 

2023/1/3 iOSシミュレーターでReleaseビルドしたら「No such module 'Flutter'」のエラー(実機では問題なし)

日記の内容はこちら↓

 

2022/12/29 XcodeでThis method should not be called on the main thread as it may lead to UI unresponsiveness.の警告

日記の内容はこちら↓

 

2022/12/26 Stored properties cannot be marked potentially unavailable with '@available'のエラー

日記の内容はこちら↓

 

2022/12/24 「Terminated due to signal 9」でXcodeと実機の接続が切れ、以降のログを確認できない

日記の内容はこちら↓

 

2022/12/23 AdMobのバナー広告を別画面で再利用したら「This AdWidget is already in the Widget tree」のエラー

日記の内容はこちら↓

 

2022/12/21 iOSのReleaseビルドでコンソールログを見る方法が分からない

日記の内容はこちら↓

 

2022/12/12 cameraパッケージをAndroid13でビルドすると、コントローラーの初期化でエラー

日記の内容はこちら↓

 

2022/12/10 cameraパッケージで初回の許可ダイアログ表示後にエラー

日記の内容はこちら↓

 

2022/12/6 switch文で「The switch case expression type 'double' can't override the '==' operator.」のエラー

日記の内容はこちら↓

 

2022/12/4 「FittedBox」の中だと「Row」の「mainAxisAlignment」が機能しない

日記の内容はこちら↓

 

2022/11/24 TextFieldを別クラスに配置すると、キーボード位置(viewInsets.bottom)を取得できない

日記の内容はこちら↓

 

2022/11/14 firebase deploy --only functions:### がエラーになりFunctionsをデプロイできない

日記の内容はこちら↓

 

2022/11/12 firebase initすると「.firebaserc already has a default project, using XXXX」 となり、プロジェクトを選択できない

日記の内容はこちら↓

 

2022/11/11 Could not resolve all artifacts for configuration ':image_picker_android:debugUnitTestRuntimeClasspath'のエラー

日記の内容はこちら↓

 

2022/11/6 APIレベル31以上のAndroidエミュレーターだと、Cameraの撮影がエラーになる

日記の内容はこちら↓

 

2022/10/30 Google Play Consoleのリリース前レポートでException java.lang.LinkageErrorのクラッシュ報告

日記の内容はこちら↓

 

2022/10/28 AppStoreの言語表示が、プライマリ言語を日本語に設定しても「EN 英語」になってしまう

日記の内容はこちら↓

 

2022/10/18 Execution failed for task ':app:checkDebugDuplicateClasses'.のエラー

日記の内容はこちら↓

 

2022/10/10 iPhoneでAdMobのインタースティシャル広告の閉じるボタンが押せない

日記の内容はこちら↓

 

2022/10/9 不定期にNull check operator used on a null valueが出る(getRootWidgetSummaryTree関連)

日記の内容はこちら↓

 

2022/10/4 PlatformException(channel-error, Unable to establish connection on channel., null, null)のエラー

日記の内容はこちら↓

 

2022/10/1 Androidエミュレーターが起動しているのに「no device selected」になる

日記の内容はこちら↓

 

2022/9/25 Xcode14で、iPadを非対応にする(対象端末から除外する)設定が見つからない

日記の内容はこちら↓

 

2022/9/24 iPadの表示向きを固定できない 〜Xcode14での対処法

日記の内容はこちら↓

 

2022/9/23 ノッチのあるiPhoneでSafeAreaを使うと、ステータスバーの文字が見えなくなる

日記の内容はこちら↓

 

2022/9/22 flutter_native_splashを使うと、iOSのステータスバー(status bar)が表示されなくなる

日記の内容はこちら↓

 

2022/9/21 Xcode14でビルドしたらSigning for "・・・・" requires a development team. のエラー

日記の内容はこちら↓

 

2022/9/20 iPadだとshare_plusの共有アプリ一覧が表示されない

日記の内容はこちら↓

 

2022/9/17 Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.のエラー

日記の内容はこちら↓

 

2022/9/16 Unrecognized Android Studio (or Android Support plugin for IntelliJ IDEA) version のエラー

日記の内容はこちら↓

 

2022/9/10 share_plusのshareFilesメソッドの完了をawaitで待てない

日記の内容はこちら↓

 

2022/9/2 image_pickerで撮影した写真データが、縦横逆で(90度回転して)表示されてしまう

日記の内容はこちら↓

 

2022/8/28 Image.fileにwidthやheightのプロパティがあるのに、取得するとnullになる

日記の内容はこちら↓

  

2022/8/7 ステータスバーの高さ「padding.top」を取得したが、値がゼロになってしまう

日記の内容はこちら↓

 

2022/8/5 Stackで下層ウィジェットからはみ出た部分をタップできない

日記の内容はこちら↓

 

2022/8/1 AppBar上のアイコンサイズを縮小できず、サイズオーバーのエラーになる

日記の内容はこちら↓

 

2022/7/28 There are multiple heroes that share the same tag within a subtree のエラー

日記の内容はこちら↓

 

2022/7/24 Navigatorで、Do not use BuildContexts across async gaps の警告が出る

日記の内容はこちら↓

 

2022/7/20 Macデスクトップアプリの審査で、メニューバーの言語が(localization)不統一のためリジェクト

日記の内容はこちら↓

 

2022/7/18 Flutter3にアップグレードしたら、menubarプラグインが使えない

日記の内容はこちら↓

 

2022/7/17 MacデスクトップアプリからのGoogle SignInが突如エラーになる

日記の内容はこちら↓

 

2022/7/10 Textの上に余白があるのに上寄せできない

日記の内容はこちら↓

 

2022/7/3 Flutter 3にアップグレードしたら、No named parameter with the name 'maxLengthEnforced'のエラー

日記の内容はこちら↓

 

2022/6/29 Google Playのリリース前レポートで「Strongly consider using FLAG_IMMUTABLE」のクラッシュ報告 〜Android12関連〜

日記の内容はこちら↓

 

2022/6/28 Google Playのリリース前レポートで「no such table: media_store_extension」のクラッシュ報告 〜機種xiaomi Redmi 6A〜

日記の内容はこちら↓

 

2022/6/26 「このファイルは Android 12 以降にはインストールできません。」のエラー

日記の内容はこちら↓

 

2022/6/24 doc comments(3本スラッシュ「///」のコメント)のポップアップを表示できない

日記の内容はこちら↓

 

2022/6/23 DBのupgradeで列追加すると「'Null' is not a subtype」のエラー→Dart Data Classプラグインが原因と判明

日記の内容はこちら↓

 

2022/6/21 sqfliteで「ADD COLUMN」を使ってテーブルに複数列を追加しようとしたらエラー

日記の内容はこちら↓

 

2022/6/16 'decoration != null || clipBehavior == Clip.none': is not true. のエラー

日記の内容はこちら↓

 

2022/6/14 親Container内に小さいContainerを置きたいが、親のサイズまで広がってしまう

日記の内容はこちら↓

 

2022/6/12 リストア(インポート)したはずのsqfliteの「.db」ファイルからデータを読み込めない

日記の内容はこちら↓

 

2022/6/8 InteractiveViewerの拡大率「details.scale」を取得したいが、毎回1.0に戻ってしまう

日記の内容はこちら↓

 

2022/6/2 AdMobのApp Storeのリンク設定で、自分のアプリが見つからない 〜「App Store Marketing Tools」のリンクで解決

日記の内容はこちら↓

 

2022/5/30 iOS15.5だとApp Tracking Transparency(ATT)ダイアログが表示されないと言われリジェクト

日記の内容はこちら↓

 

2022/5/28 ‘Pods_Runner.framework’ is missing one or more architectures required by this target: armv7 のエラー

日記の内容はこちら↓

 

2022/5/20 url_launcherで非推奨になったメソッドを修正したら、ブラウザが起動しなくなった

日記の内容はこちら↓

 

2022/5/14 AdMobから、設定していないリワード広告について、ポリシー違反の警告が来る

日記の内容はこちら↓

 

2022/5/10 flutter_local_notificationsのonSelectNotification属性が、アプリを閉じたバックグラウンド状態だと動作しない

日記の内容はこちら↓

 

2022/5/7 flutter_local_notificationsのonSelectNotification属性でNavigatorを使うとき、contextを参照できない

日記の内容はこちら↓

 

2022/5/6 iOSのpermission_handlerで、許可していてもPermissionStatusがdeniedになる

日記の内容はこちら↓

 

2022/5/5 The following GlobalKey was specified multiple times in the widget tree. のエラー

日記の内容はこちら↓

 

2022/5/4 minSdkVersion 16 cannot be smaller than version 19 declared in library [:firebase_analytics] のエラー

日記の内容はこちら↓

 

2022/5/3 バックアップした「hive」のファイルをインポート(リストア)して上書きしても、データが更新されない

日記の内容はこちら↓

 

2022/5/2 標準テキストの色の指定方法(Theme.ofの指定方法)が分からない

日記の内容はこちら↓

 

2022/5/1 Flutter2.8以降のFirebase初期設定で、パスを通しても「flutterfire configure」が「command not found」になる

日記の内容はこちら↓

 

2022/4/30 LeaderLayer anchor must come before FollowerLayer in paint order, but the reverse was true.のエラー

日記の内容はこちら↓

 

2022/4/14〜15 release modeだと、アプリ起動時に、TextFieldがフォーカスされていても、キーボードが出現しない

日記の内容はこちら↓

 

2022/4/10 Containerで「Cannot provide both a color and a decoration」のエラー

日記の内容はこちら↓

 

2022/4/7 MacOSのデスクトップアプリで「The Scrollbar's ScrollController has no ScrollPosition attached.」のエラー

日記の内容はこちら↓

 

2022/4/4 MacOSのデスクトップアプリ:かな漢字変換中に、Backspaceや上下キーを押すと挙動がおかしくなる(続き)

日記の内容はこちら↓

 

2022/3/31 「error: linker command failed with exit code 1 (use -v to see invocation)」のエラー

masterチャンネルに変更し、masOSアプリをビルドしたら上記のエラーが発生。

初めて遭遇した。

エラー文を読んでも趣旨がわからないため、ググると多くの情報が引っかかる。

主に、こちらこちらの情報を参考にさせていただき、試してみるが、そもそもXcode内に「Enable Bitcode」の項目が見つからず、対応できず。

また、もう一つ書かれていた対策として、「Library/Developer/Xcode/DerivedData/」内のデータ(Xcodeの中間生成ファイル)を全削除してみるも、結果は変わらず。。。

そこで、いつもの基本作業を試していなかったことを思い出し、

「flutter clean」「pub get」→macosフォルダ内で「pod install」

をやったところ、普通に解消された。

慌てて調べて、若干時間を浪費してしまった。。

やはり基本中の基本である「flutter clean」と「pod install」は最初に試すべき。。

 

2022/3/28 macOSがBig Sur 11.2.3だと、Xcode13にアップデートできないい

日記の内容はこちら↓

 

2022/3/24〜3/26 Flutterを2.2.3から2.10.3にアップグレードして発生したエラー対応記録

日記の内容はこちら↓

 

2022/3/21 Google Play Consoleに、QUERY_ALL_PACKAGES 権限の申告に関する連絡あり

日記の内容はこちら↓

 

2022/3/18 MacOSのデスクトップアプリ:かな漢字変換中に、Backspaceや上下キーを押すと挙動がおかしくなる

日記の内容はこちら↓

 

2022/3/17 MacOSのデスクトップアプリのApp Store Connectへの送信完了後、「Cannot be used with TestFlight」の警告が出る

日記の内容はこちら↓

 

2022/3/16 MacOSのデスクトップアプリをApp Store ConnectにDistributeしようとしたら、「App sandbox not enabled.」のエラー

日記の内容はこちら↓

 

2022/3/13 MacのデスクトップアプリをXcodeでビルドすると、「Swift Compiler Error No such module '#######'」のエラー

日記の内容はこちら↓

 

2022/3/12 Macのデスクトップアプリだと、file_pickerの動作中に、アプリ画面を触れてしまう

日記の内容はこちら↓

 

2022/3/7 Macのデスクトップアプリで、TextFieldのテキストを右から左に選択するとRangeErrorになる

日記の内容はこちら↓

 

2022/3/2 Macのデスクトップアプリで、path_providerのメソッドが使えない

日記の内容はこちら↓

 

2022/2/26 Androidエミュレーターが「Running multiple emulators with the same AVD is an experimental feature.」で起動できない(解決せず)

macOSのエミュレーターを使い始めた影響?かは不明だが、突然、使っていたPixel4のAndroidエミュレーターが起動不能になった。

Android Studioの右下に、以下のエラーメッセージが出る。

Error Opening Emulator
emulator: ERROR: Running multiple emulators with the same AVD is an experimental feature. Please use -read-only flag to enable this feature.

以前、こちらの記事の情報に従って、隠しフォルダである「.android」フォルダ内の「avd/エミュレーター名.avd」内にある下記3ファイルを削除したら解決したので、今回も試す。

cache.img
hardware-qemu.ini.lock
multiinstance.lock

しかし、再度、エミュレーターを起動するも、白地の画面に「Google」が表示されたままで、30分ほど待っても起動しない。

途中で起動を終了させると以下のエラー。

Error : Opening Emulator handleCpuAcceleration
handleCpuAcceleration: feature check for hvf cannot add library /Users/・・・・/Library/Android/sdk/emulator/qemu/darwin-x86_64/lib64/vulkan/libvulkan.dylib: failed added library /Users/・・・・/Library/Android/sdk/emulator/lib64/vulkan/libvulkan.dylib cannot add library /Users/・・・・/Library/Android/sdk/emulator/qemu/darwin-x86_64/lib64/vulkan/libMoltenVK.dylib: failed added library

こちらの情報を参考に、「advancedFeatures.ini」を作り、「.android」フォルダに置いたり、こちらの情報を参考に、「cache.img.qcow2」も削除したりしてみたが、やはり起動できない。。

試しに「AVD Manager」から、新規でPixel4のAndroidエミュレーターを作成すると、これは問題なく起動できた。

新・旧のエミュレーターの「avd/エミュレーター名.avd」内を比較すると、正常に動作する方は、「default_boot」フォルダ内に「ram.img」ファイルがあるが、エラーの方にはこのファイルがなく、代わりに「ram.img.dirty」ができている。。

時間がもったいないこともあり、、旧エミュレーターについて、最終手段である「AVD Manager」の右側プルダウンの「Wipe Data」をして初期化すると、問題なく起動できるようになった(エミュレーター内のデータは消えてしまったが、、、)。

 

2022/2/24 macOSアプリとして起動すると「The FlutterFire plugin firebase_auth for macOS requires a macOS deployment target of 10.12 or later」のエラー

日記の内容はこちら↓

 

2022/2/21 GCPのAPIキー制限で、Google Calendar APIのみ有効にすると、Firebaseにアクセスできない。

GoogleカレンダーにアクセスするFlutterアプリを作っていたが、Google Cloud Platform(GCP)のAPIキー設定箇所(認証情報)に、警告マークが出ていた。

APIキーへのアクセス制限を入れていなかったことが原因。

そこで、アクセスできるAPIを「Google Calendar API」のみに制限したところ、Firebaseにアクセスできなくなった。

具体的には、「firebase_auth」パッケージに紐づく「GoogleAuthProvider.credential」メソッドが機能せず、以下のようなエラーが出る。

Ignoring header X-Firebase-Locale because its value was null.
[firebase_auth/unknown] com.google.firebase.FirebaseException: An internal error has occurred.
[ Requests to this API identitytoolkit method google.cloud.identitytoolkit.v1.AuthenticationService.SignInWithIdp are blocked. ]

GCPのダッシュボードを見てみると、「Identity Toolkit API」「Firebase Installations API」にエラーが発生していた。

そこで、上記2つのAPIにチェックを入れ、有効化すると、無事エラーが解消された。

こちらにも似たような報告がなされている。

APIキーの制限について、アプリケーションの制限に関しては影響範囲を特定しやすいが、APIの制限に関しては、どのAPIを制限すると問題が発生するのか、手探りな印象。。。

アプリケーションの制限をするだけでも警告マーク消えるので、自分のような理解不足の段階では、APIの制限はしない方が無難か。。。

 

2022/2/17 GooglePlayにアプリをリリースしたら、Google SignIn(Googleサインイン)ができなくなった②

以前も同じ現象が起こったが、その際は、こちらに書いた対策(Google Play ConsoleのSHA-1をFirebaseに追加登録)で解決できた。

今回は、この対策をした上でリリースしたのに、なぜかサインインできず、焦る。。

正確には、サインインは何とかできるが、開発中にAndroid Studioから直接ビルドしたときと比べると、異常に時間がかかる状況。。

また、サインアウトについては、なぜかエラーになる。

調べても情報が見つからなかったが、GCP(Google Cloud Platform)上で、AndroidのAPIキーに、アプリケーション制限をかけたときに、SHA-1を設定したことを思い出した(GCPの「認証情報」→「Android key」を編集→「アプリケーションの制限」→「Androidアプリ」を選択)。

このときは、デバッグ証明書のフィンガープリント(SHA-1)しか登録していなかったので、ここにもGoogle Play Console上で取得できるSHA-1を追加登録してみる。

すると、Google Playからインストールしたアプリからも、問題なくサインイン・サインアウトができるようになった。

今回の学びは、こちらの記事にも反映しました。

 

2022/2/15 iOSビルドで「Command PhaseScriptExecution failed with a nonzero exit code」のエラー

久しぶりに開いたプロジェクトを、iOSシミュレーターでビルドしたら発生。

Androidでは問題なく実行できている。

大概のエラーは解決するお決まりの「Podfile.lock」削除→「pod install」→「flutter clean」→「pub get」をやってみるが、解消せず。。

エラーログを見ても、上記エラー文しか表示されておらず、怪しい場所の検討がつかない。。

仕方なく調べると、記事はたくさん見つかるが、原因は色々あるようで、解決法も記事によって違う。

その中で、スバリ同じ状況を説明しているこちらのYouTube動画を発見。

まず、Xcodeで「TARGETS」にある「Runner」「Build Phases」タブを開く(初めて開いた、、)。

次に、「Run Script」のプルダウンを開くと、

/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build

という部分があるので、これを削除する。

これで再ビルドすると、無事エラーが解消された!

正直、原理はよく理解できていないが、、、ともかく教えていただいた動画に感謝。

 

2022/2/13 Stream型のデータ処理が終わった後に、次の処理を実行させたい→「await for」を使う

エラー対応ではないが、やり方を見つけるのに苦労したのでメモ。

Googleドライブから「files.get」メソッドでデータを読み込み、加工処理した後に、データを表示する処理をさせたいが、返り値がStreamのため、Future awaitのようなことができず、加工処理が終わる前に表示処理がなされてしまう。。

コードは以下のような形。

「files.get」メソッドで読み込んだStream型の変数.listen(
 (dataO) {
   ** dataOのデータ加工処理 **;
 },
 onDone: () {
   ** 上記加工処理したデータの表示処理 **; // これが先に実行されてしまう。。
 },
);

調べたところ、こちらの記事に「await for」を使うと、Streamの処理を待てると教えていただく。

当初、上記記事の内容を理解するのに苦労したが、「listen」を使うケースと何度も照らし合わせて、恥ずかしながら、ようやく理解。

結果、以下のように書き換えることで、加工処理→表示処理の順で実行できるようになった。

await for (dataO in 「files.get」メソッドで読み込んだStream型の変数) {
     ** dataOのデータ加工処理 **;
}
** 上記加工処理したデータの表示処理 **;

※上記「dataO」は、Stream型で順次供給されてくるプロパティ(変数)の中の1つ、という理解。

Stream終了を待てずに困ったことは多々あったので、今後は「await for」を活用していこう。

 

2022/2/8 画面遷移するときに、たまに「'width > 0.0': is not true.」のエラーが出る

毎回ではないが、画面遷移する際に、

'package:flutter/src/rendering/box.dart': Failed assertion: line 320 pos 12: 'width > 0.0': is not true.

というエラーが出る。

エミュレーターが重くて画面遷移に時間がかかる時に発生する印象。

エラー文の後にリンクがあったので、叩いてみると、

FittedBox(
 fit: BoxFit.scaleDown,
 child: Text("・・・"),
)

の部分を指していた。

画面遷移時にTextの中身(String変数)をクリアする処理を入れていたが、おそらく、中身がクリアされた後に、Textの表示を続けようとしたため、幅が0になってこれ以上縮められないぞ、とエラーになった模様。

Textの表示終了後に、中身のStringがクリアされればエラーにならないが、非同期処理を使っていることもあり、処理が重いときは、この順番が逆になると推察。

対策を調べると、こちらの記事に、BoxConstraintsを使って、以下のように最小サイズを1pixelに制限すれば回避できる、とあったので、やってみると確かに解消できた。

FittedBox(
 fit: BoxFit.scaleDown,
 child: 
  ConstrainedBox(    // <- これを追加
     constraints: BoxConstraints(minWidth: 1, minHeight: 1),  // <- これを追加
     child: Text("・・・"),
  ),
)

「BoxFit.scaleDown」は、画面サイズや親ウィジェットのサイズに収まるように、テキストやアイコンを縮めてくれるので愛用していたが、今後は気をつけよう。

 

2022/2/6 Scrollbarの「isAlwaysShown: true」をScrollablePositionedListのリストビューで使えない(未解決)

以前、何かの情報で、「Scrollbar」クラスの「isAlwaysShown」プロパティ(スクロールバーを常時表示するか否かを設定するプロパティ)は、trueにするとエラーになるので使えない、と目にした記憶があり、使ってこなかった。

実際、単純に「isAlwaysShown: true」とすると、以下のようなエラーが出ていた。

A ScrollController is required when Scrollbar.isAlwaysShown is true. The Scrollbar was not provided a ScrollController, and attempted to use the PrimaryScrollController, but none was found.
'package:flutter/src/widgets/scrollbar.dart':
Failed assertion: line 953 pos 11: 'scrollController != null'

The Scrollbar's ScrollController has no ScrollPosition attached.
A Scrollbar cannot be painted without a ScrollPosition.
The Scrollbar attempted to use the PrimaryScrollController. This ScrollController should be associated with the ScrollView that the Scrollbar is being applied to. When providing your own ScrollController, ensure both the Scrollbar and the Scrollable widget use the same one.

しかし、こちらの情報を見て、「Scrollbar」コンストラクタと、スクロールバーを付けたいウィジェット(例えば、SingleChildScrollView、TextField、ListView.builderなど)の両方に、コントローラーとして共通のScrollControllerのインスタンスを設置すれば、エラーが発生しないと分かった。

よく読んでいなかったが、、、確かに2つ目のエラーメッセージの最後にそう書かれていた。

しかし、スクロールさせたいリスト表示に、「scrollable_positioned_list」パッケージによる「ScrollablePositionedList.builder」コンストラクタを用いた場合、ScrollController型のインスタンスを設置できるプロパティが無いため、できなかった。。

「ScrollablePositionedList.builder」には、スクロール系のコントローラーを設置できる「itemScrollController」というItemScrollController型のプロパティはあるのだが、あくまでScrollController型ではないため、「Scrollbar」と共通のコントローラーを設置できない。。。

パッケージのソースコード内も探ってみたが、対応方法が分からず。。

調べると、こちらに同様のイシューを上げている方がいて、まだ解決していない模様。

「scrollable_positioned_list」パッケージは、リストの初回表示位置を自由に指定できるので便利だったが、スクロールバーを常時表示したい場合は、「ListView.builder」を用いて対応するしかない、というのが現状の理解。

 

2022/2/5 Google Calendar API:deleteメソッドで削除しても、予定情報が完全に消えない

Google Calendar APIを使ってGoogleカレンダーに登録した予定(イベント)を、deleteメソッドで削除すると、カレンダー上からは見えなくなる。

しかし、削除した予定のeventIdをキーにして、getメソッドを使うと、削除したはずの予定情報が取得できてしまう

どうやら完全には消えていないらしい。。。

APIの説明ページやソースコード内の解説を見ても、この点の説明を見つけられず、完全削除する別メソッドも見当たらない。。

こちらに類似した質問をしている方もいたが、解決策を得られていない模様。

しばらく悩んだ末、ふと、登録したGoogleカレンダーの設定アイコン(歯車マーク)を開いてみると、「ゴミ箱」という項目を発見。

開くと、なんとdeleteメソッドで削除した予定達が並んでいた!

そこで、ゴミ箱内で完全削除した上で、getメソッドを実行すると、今度はちゃんと

Null check operator used on a null value

のエラーが発生し(try catchで処理可能)、予定情報は取得されなかった。

ゴミ箱に移動しているとは、、盲点(というか、カレンダーに「ゴミ箱」があること自体、知らなかった。。。)。

カレンダーのゴミ箱を空にするメソッドも探してみたが、見つけられず(あるのかもしれませんが、、、)。

同じ質問をされているこちらの記事では、新たに作成したテンポラリのカレンダーに、削除対象の予定(イベント)を移動させ、そのテンポラリのカレンダーごと削除する、という荒技が紹介されていた。

なるほど!と思ったが、処理は複雑になりそう。。

ゴミ箱内は30日で自動削除されるため、大きな問題はないと考え、deleteメソッドの利用だけで良しとすることに。

 

2022/1/28 「File」クラスに突然赤い波線のエラーが出る

今までエラーが出なかったのに、突然「File」クラスの全箇所に赤い波線のエラーが表示されていた。

なかなか理由が分からなかったが、Android Studioの「Git」タブの「Compare with Local」で変更箇所を調べたら、冒頭のimport文に、いつの間にか「import 'dart:html';」が追加されたと分かった。

元々は「dart:io」の「File」クラスを使っていたので、これが原因の模様。

どうやら「File」を使ったコードを他からコピペした際に、「dart:html」のクラスと判断されて自動インポートしてしまったらしい。。

外からコードを持ってくる際は、意図しないインポートがされないよう注意。

 

2022/1/26〜1/27 「JS: A parser-blocking, cross site (i.e. different eTLD+1) script」という警告が出る

突然、実行中のデバッグウィンドウに、以下のような警告が出るようになった。

W/Ads     ( 3996): JS: A parser-blocking, cross site (i.e. different eTLD+1) script, https://pagead2.googlesyndication.com/pagead/js/XXXX/XXXX/XXXX.js, is invoked via document.write. The network request for this script MAY be blocked by the browser in this or a future page load due to poor network connectivity. If blocked in this page load, it will be confirmed in a subsequent console message. See https://www.chromestatus.com・・・for more details. (https://googleads.g.doubleclick.net/・・・

「document.write」を用いていると、ネットワークが遅い場合にブロックされるよ、、という趣旨に読める。

リンク先をクリックすると、よく分からないコードが書かれたテキストファイルがダウンロードされる。。

中を読むのは不可能な感じなので、ネットで調べてみる。

まず、「document.write」は、JavaScriptで文字列などをブラウザ上やコンソールに表示させるメソッドらしく、こちらこちらの記事によると、「async」をつけて修正する、との情報があった。

ただ、コード中を調べても「document.write」はどこにも使われておらず。。そもそも、書いているコードはDartであって、JavaScriptではない。。

警告に「googleads」という言葉もあるので、恐らく広告が絡んでいるのだろうか、、、。

その後、調べても解決せず、1日経ってもう一度実行すると、今度は警告が出なくなった。

違いとしては、表示しているテスト広告(バナー)の内容が変わったこと。

警告が出ていたときは、見たことのない英語表示のバナーが出ていたが、よく見る日本企業のバナーに変わってからは解消されている。

表示する広告側の仕様によって発生するものなのだろうか。。。結局よく分からないままだが、備忘として記録。

 

2022/1/19 TextPainterクラスのtextDirection属性に、「TextDirection.ltr」を設定するとエラー

TextPainterのインスタンスを作る際、文字の方向を指定するtextDirection属性に、enum型の「TextDirection.ltr」(左から右)か「TextDirection.rtl」(右から左)を設定できるのだが、何度書いても「ltr」の所に赤い波線が出てエラーになった。

textDirection: TextDirection.ltr ← この「ltr」にエラー表示が出る。。。

原因が分からず、しばらくの間、地味に苦しむ。。

結果、「textDirection:」と「TextDirection」の部分にマウスカーソルを当ててポップアップの説明を見てみると、「textDirection:」は「dart:ui」ライブラリからの「TextDirection」を要求しているのに対し、自分のコードではインポートしていた「intl」パッケージからの「TextDirection」が設定されていると分かった。

どうやら、「dart:ui」にも「intl」にも「TextDirection」があり、競合していた模様。あまり競合しそうにない名前だったので、思いもよらなかった。。

なので、「dart:ui」の方に「as ui」を付けて、

textDirection: ui.TextDirection.ltr

としたら、無事エラーが解消された。

Android Studioのポップアップ説明も重要なヒントになりますね。

 

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を連発しないように注意します。

 

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」のエラー

日記の内容はこちら↓

 

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で読み込んだ画像が、撮影した向きどおりに表示されない

日記の内容はこちら↓

 

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」のエラー

日記の内容はこちら↓

 

2021/10/31 「pod install」したら、「CocoaPods could not find compatible versions for pod "Firebase/Auth"」のエラー

日記の内容はこちら↓

   

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をコピーしました