TL;DR

1
2
3
import { startActivityAsync, ActivityAction } from 'expo-intent-launcher';

startActivityAsync(ActivityAction.APPLICATION_DETAILS_SETTINGS, { data: `package:${YOUR_PACKAGE_NAME}` })

APPLICATION_DETAILS_SETTINGSを開くことができる。下の画像のような画面。

APPLICATION_DETAILS_SETTINGS
APPLICATION_DETAILS_SETTINGS

cf: Opening Device Settings on Android using Linking - Expo Forum

まえがき

ReactNativeで使用するフレームワーク(React codebase)であるExpoを便利に使用してはいるが、先週リリースされたAndroid 13で使用すると問題が発生する。

Android 13ではiOSと同じように通知を要求するときにダイアログを表示するようになったが、これと2022年8月20日時点のExpo(SDK 46)とは相性が良くないらしい。

まず、Notifications.requestPermissionsAsync()で権限を要求することができない。何も表示されないまま即座にstatusがdeniedとしてresolveされてしまう。

そもそもターゲットがAPI level 32以上じゃないと任意の場所で通知権限を呼び出せない気がするし、それならExpo SDKのバージョン待ちということになりそうだ。

だからと言ってAPI level 31以下の場合と同じように最初のアクティビティでダイアログが出ることもないから困ってしまった。

この場合、UX的な解決策としては通知がdeniedされた場合に設定画面に飛ばしてやるのが最善だろう。現にiOSで一回通知を拒否してしまった場合二度とアプリ側からリクエストすることはできないから、Linking.openURL('app-settings://notification/YOUR_BUILD_IDENTIFY')して通知の許可画面に飛ばしている。

IntentLauncherを使う

AndroidでiOSのURLスキームのようなことをするのが、IntentLauncherであり、Expoでもexpo-intent-launcherが用意されている。Exampleにはこう書かれている。

1
2
3
4
import { startActivityAsync, ActivityAction } from 'expo-intent-launcher';

// Open location settings
startActivityAsync(ActivityAction.LOCATION_SOURCE_SETTINGS);

そしてその下にはActivityActionの一覧が記載されていて、その中にはAPPLICATION_DETAILS_SETTINGSAPP_NOTIFICATION_SETTINGSなど「まえがき」の解決策となりうる定数が記載されている。

しかし、ExampleのLOCATION_SOURCE_SETTINGSをこれらに入れ替えてもうまく行かない。アプリ特有の設定だからパッケージ名が要るような気がするが、ドキュメントには何も書かれていない。

expo-intent-launcherはAndroid限定だしマイナー扱いなのだろうが、ドキュメントも雑だし先人たちの情報も見当たらない。

とりあえずparamsとしてIntentLauncherParamsを見ると、packageNameってのがあるのでそのまま指定してみるが何も動かない。

迷いまくった結果、Expo ForumのOpening Device Settings on Android using Linkingってトピックにちゃんと書いてあった。(が、2019年のものなのでこのままコピペしても動かない。)つまり、{ data: 'package:' + YOUR_PACKAGE_NAME }をすれば良いらしく、実際にそれで動いた。

しかしこれで動いたのはAPPLICATION_DETAILS_SETTINGSであり、APP_NOTIFICATION_SETTINGSの方は動かなかった。というか、ActivityActionに記載されているやつのうちいくつかは最低でも書くだけじゃ動かないものがある。初心者お断り設計である。