Android

Android 8.0 で通知を表示すると System UI がクラッシュする

問題

Android 8.0 未満 で実行した場合は問題なく、 Android 8.0 でだけ、通知を表示させた瞬間に System UI がクラッシュするという問題に遭遇しました。

通知を発行すると「Unfortunately, System UI has stopped.」と表示され、ダイアログの「OK」を押下するとクラッシュを繰り返し、通知を表示させようとしたアプリのプロセスが終了するまでその状況を突破することができなくなります。

今回自分がハマった状況では、 Service を startForeground() メソッドでフォアグラウンド実行する際に指定した通知に問題があったため、何が問題なのかがわからず長時間悩まされました。

原因

これは Android 8.0 のバグで、通知 (Notification) の smallIcon に Adaptive icon を指定すると発生します12

通知バーに表示されるアイコンは Adaptive icon に対応していないため、たしかにそう言われてみれば Adaptive icon を Notification の small icon に指定していることが問題なような気がします。

しかし、 Android Studio 3.0.1 で [New Project] でプロジェクトを新規作成した場合、drawable-anydpi-v26 ディレクトリに ic_launcher.xml として Adaptive icon が作成されるため、 R.mipmap.ic_launcher でランチャーアイコンを参照すると SDK 26 以上では自動的にアダプティブアイコンになります。

そのため、 Notification を生成する際に以下のような指定の仕方をしていると、上の問題が発生することになります。

val notification = Notification.Builder(this, "channelId")
    .setSmallIcon(R.mipmap.ic_launcher) // SDK 26 以上では Adaptive icon になる
    .setContentTitle("title")
    .setContentText("text")
    .build()

回避策

Notification の small icon には Adaptive icon を指定しないようにしましょう。
この問題は既に Issue Tracker に報告されており、今後 Android Studio 3.0.1 のアップデートや 3.1 でリソースタイプの Lint チェックが追加される見込みのようです。3