flutter_local_notificationsで通知が表示されない(Android13)
結論:requestPermissionメソッドで許可ダイアログを表示させる
2023/3/19 Flutter エラー・バグ日記
ローカル通知機能を使ったアプリの改修中に、実機検証をしていたところ、いつのまにかAndroidで通知が表示されない状況になっていた。
調べてみると、アプリ情報で「通知」が「OFF」となっていた。
Android11や12では問題なく動作する
複数のOSバージョンで確認すると、Android11や12では、問題なく通知が表示された。
初回起動時に、特に通知許可のダイアログは表示されないが、それでも問題なく動作している。
「AndroidManifest.xml」にも、通知関連の許可は設定していない。
どうやらAndroid13の場合に問題が生じてしまう模様。
最新パッケージのReadmeに説明があった
調べてみると、最新の「flutter_local_notifications」パッケージのReadmeにきちんと説明があった。
Android13以降は、iOSと同様に、ユーザーに対して通知権限の許可取得が必要になったらしい。
こちらのAndroid公式サイトに、「Android 13 以降を搭載したデバイスにユーザーがアプリをインストールした場合、アプリの通知はデフォルトでオフになります。」と説明されている。
調べた結果、必要な対応は以下3つと分かった。
①以下のとおり、「FlutterLocalNotificationsPlugin」クラスのインスタンス経由で、「requestPermission()」を実行する。
// クラス名、メソッド名、プロパティ名(変数名)について、筆者が作成したもの(名前変更可のもの) // の名前の末尾には、大文字のオー「O」をつけています // ※ライブラリ(パッケージ)で予め決められているもの(名前の変更不可のもの)と、 // 自分で作成したもの(名前の変更可のもの)の区別をしやすくするため // アプリ起動直後の「flutter_local_notifications」の初期化処理のところで、下記を実行する // FlutterLocalNotificationsPluginクラスのインスタンスを作成(これはAndroid13対応とは関係なく、flutter_local_notificationsを使う場合には必要) FlutterLocalNotificationsPlugin flutterLocalNotificationsPluginO = FlutterLocalNotificationsPlugin(); // 上記で作成したインスタンス経由で、許可ダイアログを表示するメソッドを実行 await flutterLocalNotificationsPluginO.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()!.requestPermission();
なお、パッケージの説明には記載が無いが、「resolvePlatformSpecificImplementation」の返り値は、null許容型(T?)なので、「.requestPermission()」の前に「!」もしくは「?」をつける必要があった。
また、「requestPermission()」は非同期(Future<bool?>型)なので、許可・不許可の取得結果を待てるよう、awaitもつける形にした。
②「android/app/build.gradle」の「targetSdkVersion」と「compileSdkVersion」を「33」以上にする。
③「AndroidManifest.xml」に、以下のパーミッションを追加する。
<manifest ...> <!-- 以下の1文を追加 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <application ...> ... </application> </manifest>
これは、パッケージのReadmeには書かれていないが、紹介されているリンク先のAndroid公式サイトで説明されていた。
確かに、上記①〜③の対応をした結果、Android13の端末では、初回起動時に通知許可のダイアログが表示され、許可すれば、無事通知されるようになった。
iOSでもリリースする場合は、OS判定で回避する必要あり
上記修正をした上で、iOSでビルドしようとしたら、「Null check operator used on a null value」のエラーになってしまった。
これは、「requestPermission」が、Android用のメソッドであることが要因だった(ソースコード内の説明を見ると分かる)。
そのため、このメソッド実行部分を、「if (Platform.isAndroid) { ・・・}」の中に記載することで、iOSの場合には実行を回避するよう修正したら、無事エラーを解消できた。
\一般的なエラー対処法をまとめた記事はこちら/
リリースしたアプリ(全てFlutterで開発)
個人アプリ開発で役立ったもの
おすすめの学習教材
\超初心者向けでオススメな元Udemyの講座/
\キャンペーン時を狙えば安価で網羅的な内容が学べる(日本語訳あり)/
\Gitの基礎について無料で学べる/
おすすめの学習書籍
\実用的。image_pickerに関してかなり助けられた/
\Dartの基礎文法を素早くインプットできる/