2022/09/11

[android] ブート後に intent を受け取る

AlarmManager の章にデバイスの再起動後にアラームを開始したい場合について書かれている。

デバイスの再起動時にアラームを開始する
https://developer.android.com/training/scheduling/alarms#boot

デバイスの再起動をアプリは検知することは通常できないので、 intent を受け取るようにするようにしておくのだ。
つまり、アラームとは関係が無いのだが、アラームを設定したアプリを起動していたのに、いつの間にか再起動されてアラームが動作しなかったということがあるからここで説明しているのだろう。

 

書いてあるとおりに実装した。
一度アプリを起動しておけば、再起動すると notification が表示される。

https://github.com/hirokuma/AndroidAlarmTest/compare/20488ad5377f82a2d529b2654dbb6262a50985e6..4f69554d7f177e051d3f57b33e59c7701986507d

(関係ないけど、Windows で作っていたからか AndroidManifest.xml だけ CR/LF になっていた。 Android Studio の設定だけでは足りないのか?)

 

また、このブート時に受け取るような設定は永続的なものではないようだ。
このアプリを「アプリ情報」から強制停止してからデバイスを再起動すると notification が出てこなかったからだ。一度設定しておけば良いものでも無く、アプリがブート前に立ち上がって設定しておくだけで良いものでも無く、アプリがまったく死んでいない状態にしておかなければならないようだ。

 

では、ブート時の notification が表示されただけで setComponentEnabledSettings() を実行していない状態で再起動したらどうなるだろうか?
これはブート時に notification が表示された。 AlarmTest アプリは Activity の onCreate() で setComponentEnabledSettings() を呼び出しているのでおそらく呼ばれていないだろう。3分間隔の notification も出ないのでそのはずだ。
プロセスとしては立ち上がっているけれども、 onCreate() から始まる経路は使われていないということかな。

[android] アラームの復習

さて、少し期間が空いてしまったため Android の Alarm についてかなり忘れてしまった。
ほんの少し・・・それですら命取りになるのが加齢よ。。。


前回は AlarmManager を使って通知を出すようなしくみを考えていたが、Android というシステムからするとデバイスの起動状態を管理するという分野になるそうだ。宇宙の成り立ちみたいな広い話ですな。

デバイスの起動状態を管理する  |  Android デベロッパー  |  Android Developers
https://developer.android.com/training/scheduling

定期的に intent を発行する、というだけでなく、もっとデバイスの中で限られたリソースをうまいこと使いたいとなると電源やネットワークの状態によってアプリの動作を制限するというのも理解できる。
アプリを作っている人たちはみんな「私のアプリを使って!」と思っているので、1つしかデバイスがないのであれば優先順位を付けるしかないのだ。

そう考えると、アクションゲーム?のように前面にアプリが起動していないと意味が無いようなアプリの場合はあまり考えなくて良いだろう。バックグラウンドで動作できるアプリが複数あるのに対して、フォアグラウンドで動作できるアプリは1つしかないからだ。画面を分割することもできたと思うが、それでも入力のフォーカスを持っているのは 1アプリだけだろう。

そう考えると、定期的にアプリを起動したいのはフォアグラウンドにはいないアプリが主になるはずだ。
Android 10 からはバックグラウンドアプリから Activity を表に出すことに制限がかかった。調べ切れていないが OS のバージョンが上がってできなくなったことが増えていてもおかしくない。

こういった実装やバージョンの事情がいろいろと複雑にしているのだと思う。
developer のドキュメントはよくできていると思うのだが、Google で検索しても本家の情報が出てこないのであれば実装する人が混乱するのも仕方ないと思う。


AlarmManager 以外にも WorkManager がある。
最近は WorkManager を使うよう勧めているように思うが、得意とする分野が少し異なる。

他の API との関係性
https://developer.android.com/topic/libraries/architecture/workmanager?hl=ja#other-APIs

Dozeモードを解除できるのが AlarmManager らしい。

プラットフォームの電源管理  |  Android オープンソース プロジェクト  |  Android Open Source Project
https://source.android.com/docs/core/power/platform_mgmt

Doze とアプリ スタンバイ用に最適化する  |  Android デベロッパー  |  Android Developers
https://developer.android.com/training/monitoring-device-state/doze-standby?hl=ja

検索していると Dozeモードが搭載された Android 6.0 のときの話が良く出てくるが、Android 7.0 でさらに拡張されたのか。
上のリンクは AOSP なので OS そのものの話になっている。今回はアプリを作る方の立場なので下のリンクの方がわかりやすい。

  • 電源と接続していない
  • 静止状態にしている(センサーで見ているのだろう)
  • 画面オフのまま一定時間過ぎる

これで Dozeモードになるそうだ。それ以降は「メンテナンス枠」ということでときどき Dozeモードを解除して、また戻る。ということは、アプリが Dozeモードになるのではなく本体が Dozeモードになるということか。
時間経過のグラフを見るとメンテナンス枠になるタイミングがどんどん延びているので、放置状態が長くなるほど働かなくなるようにすることで電池の減りをなくそうということだろう。

AlarmManager はこの Dozeモードを無視して動くことができるというのが強みなのだろう。ただそこからすぐに Dozeモードに再突入するかもしれんが、そこはアプリ次第なのか。その API も追加されたもので、なおかつ 9分に 2回以上はアラームが発生しない(ということは 9分に 1回までということか)。

 

もう1つの「アプリスタンバイ」はアプリ単位。いくつか条件が整わないといけないので、アプリスタンバイにならないように作るのは難しくないかもしれない。ただ、アプリスタンバイでなくてもリソースを使いすぎだと判断されたら OS から止められるしくみはあったと思うので、結局は実験して確認するのがよいのか? でも対策していない要因でアプリが止められたら結局調べるしかないだろうし、知識を補充するのが先か・・・。

 

アプリが途中で動かなくなることについての YES/NO シートとか、logcat にこのメッセージが出たらこの状態、みたいなものがあるとよいのだが。

2022/08/21

[android] AlarmManager でアプリを起こしたい

やりたいこと

AlarmManager を使って、アプリが起動していないように見える状況でもアプリを起動させたい。

 

結果

アプリがタスク一覧に載っていなくてもアラームから起動することはできるが、強制停止状態では無理。

本体の OS が API 29 以降では Alarm のようなバックグラウンドからアプリを起動させることに制限がかかっているので、一旦 Notification などでユーザに通知だけ行い、ユーザ操作によってアプリを起動させることになるだろう。

バックグラウンドからのアクティビティの起動に関する制限  |  Android デベロッパー  |  Android Developers
https://developer.android.com/guide/components/activities/background-starts

 


前回、AlarmManager を使って反復アラームを設定し、AndroidManifest.xml に設定した <receiver> の class がブロードキャストされた intent を受け取ってログ出力するところまで確認した。

私がやりたいのは、アプリが立ち上がっていない(と思われる)状況でも AlarmManager での発火をトリガにしてアプリを起動したい、というものだ。
プリインストールのような system 属性のアプリであれば好き勝手できそうだし、Google Play からインストールしたアプリであればあまり勝手なことをされたいとは思わないだろう。

なので今回は Google Play からインストールするような system 属性を持たないアプリで期待したことができるのか、できないならどこまでやれるのかを調べたい。


前回は 15 分にしたが、あれは WorkManager の最短が 15分だったはず、くらいで決めたものだ。
AlarmManager なら 3 分でもできた。

2022-08-20 20:48:32.650/com.hiro99ma.alarmtest2 D/com.hiro99ma.alarmtest2.MainActivity: setAlarm
2022-08-20 20:53:47.674/com.hiro99ma.alarmtest2 D/com.hiro99ma.alarmtest2.NotificationReceiver: Receive !!
2022-08-20 20:56:28.482/com.hiro99ma.alarmtest2 D/com.hiro99ma.alarmtest2.NotificationReceiver: Receive !!
2022-08-20 20:59:47.663/com.hiro99ma.alarmtest2 D/com.hiro99ma.alarmtest2.NotificationReceiver: Receive !!
2022-08-20 21:02:47.665/com.hiro99ma.alarmtest2 D/com.hiro99ma.alarmtest2.NotificationReceiver: Receive !!

まあ、間隔が短くできるということはリソースを食いやすいということでもあるだろうから、アプリの審査としては厳しくなってしまうのかも? どういう基準で見ているのかは知らんのだけど、面倒なアプリの方が審査に時間がかかりそうな気がするじゃあないか。そういう基準だったら、AlarmManager ではなく WorkManager の方が緩いと思うのだ。

ともかく、3分くらいだったらテストしやすいのでそれで見ていこう。


まず「アプリが終了している」という状態について確認が必要だ。

「アプリが動いている」という状態が一番確実なのは、そのアプリがフォアグラウンドになっていて Activity が表示されているときだ。これは間違いなく動いているだろう。

ならばActivity が表に出ていないときがどうなのか、ということになる。
調べていて出てきたのが「 Doze」と「アプリスタンバイ」というものだ。

Doze とアプリ スタンバイ用に最適化する  |  Android デベロッパー  |  Android Developers
https://developer.android.google.cn/training/monitoring-device-state/doze-standby?hl=ja

書いてあるとおりなら、

【Doze】
デバイスが長い間使用されていない場合にアプリのバックグラウンド CPU とネットワーク アクティビティを保留する

【アプリスタンバイ】
ユーザーがしばらくの間操作していないアプリのバックグラウンド ネットワーク アクティビティを保留

アプリスタンバイはネットワークだけしか保留しないのか? 文章だけ読むと、先に「アプリスタンバイ」になり、それでも長い間使用されないようであれば「Doze」になるようにも見えたのだが、そうではないのだろう。

アプリで Doze をテストする
https://developer.android.google.cn/training/monitoring-device-state/doze-standby?hl=ja#testing_doze

「dumpsys deviceidle force-idle」を実行してそのアプリの動作が変わるなら、Dozeモードで動作が変わるアプリということだろう。

アプリスタンバイの場合はどれをスタンバイにするか指定しているので別物かなぁ、というところだ。
ネットで検索したらもっとよい情報が出てくるだろうが、今回はそこまで考えたくないので無視だ。


私が「アプリが「終了している」というのは、アプリスタンバイに近いと思う。
そして Android のタスク一覧から該当するアプリを上スワイプしたときも「終了している」だろうから起動してほしい。
できればアプリ情報画面で強制停止(force stop)させたあとからも起動してほしいのだが、これは難しいと思う。

あとは、アプリの中から「終了」を行った場合だ。
これが何をしているのかがよくわからんのだが、Activity が 1枚しかないときに「戻る」を選ぶと「終了しますか?」と尋ねてくるアプリがあったように思う。

ユーザが「アプリを終了したい」と思うことと、アプリとして終了するという実装は、一致しないとはいわないまでも、一致しづらいことが多いと思う。例えばゲームのハイスコアをサーバで管理してみんなで共有するようなアプリがあったとして、ユーザが「ハイスコアを更新したから終了させよう」と思ったタイミングと、アプリが「スコアのデータをサーバにアップしよう」と実装されているタイミングは必ずしも一致しないだろう。ユーザは終わった気分でいても、他のユーザがアクセス中だったりしてアップロードを保留しているかもしれない。サーバにアクセスが集中しないようにわざと遅らせるようにしているかもしれない。

そう考えると、モバイルのアプリは「終了」が即時行われるとは考えづらい。たぶん即時終了させるのがアプリ情報画面から「強制停止」を行う操作だろう。
一覧から上スワイプするのは強制停止ではないと思う。Doze にさせるか、スタンバイにしているかのどちらかではないか。調べていないけどスタンバイじゃないかなぁと思っている(個人の感想です)。

端末を USB接続しているとスリープしない状態になったりするし、その設定をオフにしても実は何かあるんじゃないの?とか、15分を 3分にしたことで挙動が違ったりするんじゃないの?とかいろいろ考えてしまうのだが、まあそのときはそのときだ。

Android Studio の Logcat タブでアプリが (DEAD) になるようであればアラームを受け付けることはさすがにできないだろう(と思ったが、タスク一覧から上スワイプすると DEAD になったので違うのか)。


adb shell でログインすると、 dumpsys というコマンドが使用できる。

dumpsys  |  Android デベロッパー  |  Android Developers
https://developer.android.com/studio/command-line/dumpsys?hl=ja

dumpsys コマンドだけたたくとすべてのシステムサービス情報を出力しようとするので、対象とするサービスを指定するのがよろしい。今回であれば alarm だ。
指定してもたくさん出力されるのだが、試作している alarmtest2 で検索するとこういう情報が見つかった。

    ELAPSED_WAKEUP #5: Alarm{bef203a type 2 origWhen 27853758 whenElapsed 27853758 com.hiro99ma.alarmtest2}
      tag=*walarm*:com.hiro99ma.alarmtest2/.NotificationReceiver
      type=ELAPSED_WAKEUP origWhen=+2m54s204ms window=+2m15s0ms repeatInterval=180000 count=0 flags=0x0
      policyWhenElapsed: requester=+2m54s204ms app_standby=-5s796ms device_idle=-- battery_saver=-5s796ms
      whenElapsed=+2m54s204ms maxWhenElapsed=+5m9s204ms
      operation=PendingIntent{77e94eb: PendingIntentRecord{b073248 com.hiro99ma.alarmtest2 broadcastIntent}}

ここでは ELASPSED_WAKEUP と経過時間で発火するように指定している。おそらく 3行目の type=ELAPSED_WAKEUP の次に出ている origWhen が発火するまでの残り時間だと思う。時間をおいて取得すると減っていたからだ。

これは、alarmtest2 アプリを起動すると出てきたし、タスク一覧で上スワイプして消したときも残っている。たぶん発火すると「App Alarm history」というところにも出てきたし、Alarm stats にも出てくるようになった。しかしアプリ情報から強制停止させると出てこなくなった。おそらくだが、アプリ情報から強制停止ボタンがタップできるような状態であればアラームは動くんじゃないかな。強制停止でアラームが消えるのは、登録元が消えたからか通知先が消えたからか。まあどっちでもよいが、確認するためには通知先を別アプリにしないとわからんな。

 

ん?
ということは、自分で自分にアラームを仕掛けておいて自分を起動する、というのは無理というか、既に起動しているから表に出してあげるだけで目的を達成できるんじゃなかろうか。

override fun onReceive(context: Context?, intent: Intent?) {
    val actionIntent = Intent(context?.applicationContext, MainActivity::class.java).apply {
        action = Intent.ACTION_MAIN
        addCategory(Intent.CATEGORY_LAUNCHER)
        flags = Intent.FLAG_ACTIVITY_NEW_TASK
    }
    context?.startActivity(actionIntent)
}

こんな感じだろうと思ったのだが、例外は発生しないもののアプリが表に出てくることはなかった。 Notification をタップしてアプリを表に出すときはこれでよかったのだが、状況が違うのか。

? I/ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.hiro99ma.alarmtest2/.MainActivity} from uid 10502
? W/ActivityTaskManager: Background activity start [callingPackage: com.hiro99ma.alarmtest2; ...(中略)...; inVisibleTask: false]
? D/ActivityTaskManager: getPreferredLaunchDisplay userset_displayid false current displayId -1
? D/ActivityTaskManager: getPreferredLaunchDisplay userset_displayid false current displayId -1
? E/ActivityTaskManager: Abort background activity starts from 10502

BroadcastReceiver だからダメなのかと思い、AlarmManager から setRepeating() するときの PendingIntent で同じ actionIntent を呼ぶようにして設定したのだが、それでも同じだった。

 

「ダメだった」という状況について説明していなかった。
手順はこうだ。

  1. alarmtest2 を起動する
  2. タスク一覧を出して alarmstart2 を上スワイプする
  3. アラームが発火するまで待つ(本体は 2分でスリープになる)

3分以上待っているとアラームが発火して Logcat に何か出てくるので、そのときにスマホをスリープ解除して画面を出し、alarmtest2 アプリが表に出ていれば成功、出ていなければダメ、という判定の仕方をしている。


logcat の 「Abort background activity start」がエラー出力なので、そこら辺か。

バックグラウンドからのアクティビティの起動に関する制限  |  Android デベロッパー  |  Android Developers
https://developer.android.com/guide/components/activities/background-starts

あー、ユーザが操作しているのにいきなり表に出てくる可能性があるから制限がかかるのか。
わかる。私だったら怒るね。

ただ、私は alarmtest2 を API 26 以上ということで作っている。であれば API 29 からというこの制限から外れるんじゃないのか?

image

雰囲気からすると、ここに書いている APIレベルは本体の OS のものということだろう。

 

ともかく、Android としては「時間に依存する通知」を使ってほしいそうだ。リンク先や "ヘッドアップ通知" という言葉も出てくるので、いわゆる Notification を使えってことなのだと思う。 Notification → 通知をタップしてアプリを出す、がよいのかな。


というわけで、Notification を追加した alarmtest2 の最新版がこちら。

https://github.com/hirokuma/AndroidAlarmTest/commit/7aea025ed07fd53d4774a526f3328984ff4994a7

前々回の Notification 記事から持ってきたのだが、Notification を表示するタイミングとコンテキストが違うので多少変更されている。

アプリが起動して行うのは Notificationチャネルの作成のみ。
BroadcastReceiver の onReceive() で Notificationの作成と表示を行っている。記事を書いたときは with という Kotlin のスコープ関数なるもので notify() を呼んでいたが、BroadcastReceiver からは使えなかったので普通に書いた。

これを実行すると、数分おきに Notification の通知が行われる。スリープしていても Notification が出てくるので非常にうっとうしい。 API が間違っていなくても用法を間違うと嫌な動作をするという例と思ってもらおう。

2022/08/15

[android] AlarmManager でアラームする

Android の基礎学習。
AlarmManager でアプリが起動していなくても何かしたい。 notification が出したいのだが、まずは Log が出るだけでも良いだろう。

Schedule alarms  |  Android Developers
https://developer.android.com/training/scheduling/alarms

 

いろいろ書いてあるのだが、こういう系統はだいたいイベントが発火するときに PendingIntent で何かするものだろう。
PendingIntent は作るとき?に Intent を与えられて、PendingIntent の殻をかぶった Intent みたいなものだろうと思ってる。

作るといっても、PendingIntent.getActivity() だったり PendingIntent.getBroadcast() だったりといくつか作り方がある。前回はnotification の学習だったが、そこでは notification をタップしたときの挙動用に PendingIntent.getActivity() を使っていた。
タップすると自アプリが表に出てくる=Activity に対して通知するからだと思っている。

では、notification を出したい場合は誰が受け取るのだろう?
今回は Activity を表に出したくないので getActivity() ではないだろう。
受け取るために Service がいるのだったら getService() かもしれない。でもわざわざ service を作りたくないとも思う。
PendingIntent で他に PendingIntent を返す static メソッドはなさそうだ(ForegroundService みたいなの以外は)。

PendingIntent.getBroadcast() で作ってやって、それを受け取るところで処理できるなら一番楽そうな気がする。


ブロードキャストを受け取る方法について。

Broadcasts overview  |  Android Developers
https://developer.android.com/guide/components/broadcasts

ローカルだったら LocalBroadcastManager があるようなことを書いてあるが、class 自体が deprecated 扱いだったから今から使わなくてもよいだろう。他の observable pattern で置き換えられるようなことは書いてあったが、これを使えとは書かれていないのでチュートリアルの通りにやれば良いのだろう。

英語版を見ているが、受け取り方は「Manifest-declared receivers」と「Context-registered receivers」の2種類のようだ。
AndroidManifest.xml にあらかじめ書いておくタイプか、ソフトウェア上で必要なときだけ受け付けるタイプか。
その2択であれば、アラームについては AndroidManifest に書くタイプだろう。アプリが立ち上がっていないときに受け取りたいのだから。でも、もしかしたら一度登録しておけばよいというタイプかもしれんので実験はしてよかろう。


これに従ってアラームを作っていく。
「反復アラーム」というのは、ワンショットではないアラームのことだろう。

AlarmManager  |  Android Developers
https://developer.android.com/reference/android/app/AlarmManager

 

アラームの大きな設定は、タイプと精度のようだ。

タイプは、「何分後」みたいな経過時間タイプ(ELAPSED_REALTIME 系)と「何時何分」みたいな時間指定タイプ(RTC 系)があるようだ。
ELAPSED は経過時間といいつつ、デバイスが起動してからの経過時間という基準になっているそうだ。実装は、例では「SystemClock.elapsedRealtime()」からの相対値を指定していた。

精度は、曖昧だけど電池に優しいか、時間きっちりかを選択するもののようだ。メソッドとしてはおそらく第1引数に type を取るものがそれだと思う。

image

チュートリアルでは setInexactRepeating() と setRepeating() が紹介されている。 exact の頭に in- が付くことで「正確ではない」ということなのだろう。反復アラームだからその 2つだけ紹介されているのだろう。

アラームというものが Androidのバージョンで変化しているもののようで、APIの説明にいろいろ書いてある。

  • API 31以降で Intent.EXTRA_ALARM_COUNT を使うなら、 PendingIntent の flags に FLAG_MUTABLE がいる
  • API 19 の時点で反復アラームはすべて inexact になっている。繰り返しで正確にしたいなら、ワンショットのアラームを繰り返すことになる。

うーん、よくわからん。
API 20 以降なら setRepeating() だけでexact にできるということかな?

 

とりあえず動いているようなので記録を残しておいた。
Kotlin + Android 8以降 + Empty Activyty をベースにしている。

https://github.com/hirokuma/AndroidAlarmTest/tree/260da35b09a5012999a96de6d1e62903e7d525c2

 

Logcat のログを必要そうなところだけ抜粋。

2022-08-15 17:33:25.893/com.hiro99ma.alarmtest2 D/MainActivity: setAlarm
2022-08-15 17:52:25.390/com.hiro99ma.alarmtest2 D/NotificationReceiver: Receive !!
2022-08-15 18:14:40.987/com.hiro99ma.alarmtest2 D/NotificationReceiver: Receive !!
2022-08-15 18:23:33.683/com.hiro99ma.alarmtest2 D/NotificationReceiver: Receive !!
2022-08-15 18:35:38.638/com.hiro99ma.alarmtest2 D/NotificationReceiver: Receive !!

15分にしたのだが、15分より短いのもある。
WAKEUP の方にしたから放置した状態で確認したかったのだけど、ときどき触ったりしたので実際はどうだか分からん。

何が苦労したかって、 Activity::onCreate() でアラームを設定すると動作しなかったことだ。
何か方法はあるのかもしれないが、setAlarm() を onCreate() で呼び出すとダメだったのだ。動くサンプルがあったのだけどアラームの設定に違いがなさそうだったのでひどく悩んだのだ。そのサンプルはボタンをタップしてアラームを設定するようになっていたので、ためしに onResume() に持っていったら動作したのだった。

まだいろいろわかっていないが、今回はアラーム動いた記念なのでよしとしよう。

2022/08/11

[android] Notificationを出す

基礎の勉強。

Android Studio でプロジェクトを作る。
対象は Android 8.0 以降。Kotlin。Empty Activity。

Create a Notification  |  Android Developers
https://developer.android.com/training/notify-user/build-notification

日本語版もあるのだけど、若干更新されていない。まあ、実行時エラーで気づける程度のものだが。
ともかく、基礎的な notification を作成する。

Create a basic notification
https://developer.android.com/training/notify-user/build-notification#SimpleNotification

手順

  1. notification で表示する中身を作る。
    NotificationCompat.Builder() の後ろに設定するメソッドを連結して呼んでいくだけ。
    Builder() の第2引数である CHANNEL_ID は String型。これは Android 8.0 以降で追加されたものらしく、それより前は無視するとのこと。
    これは、この次に作る notification channel を指定するものだ。
    なお、日本語版で~と書いたのは、ここの PendingIntent.getActivity() の最後の引数が 0 になっていたからだ。今は何か指定しないといけないそうである。フラグの違いは検索すると出てくるので探してほしい。
  2. notification channel を作る。
    そういえば、Android のどこからかアプリの上にドットを出したりするようになったなぁ。
  3. notify() で表示。

 

こんな感じだ。

    private fun createNotificationChannel() {
        val name = "のてぃふぃけーしょんちゃんねる"
        val descriptionText = "のてぃふぃけーしょんちゃんねるのですくりぷしょん"
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(NOTIFICATION_ID, name, importance).apply {
            description = descriptionText
        }
        val notificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(channel)
    }

    private fun createNotification(): NotificationCompat.Builder {
        // 自アプリを起こす
        val wakeupMeIntent = Intent(this, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        }
        val wakeupMePendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, wakeupMeIntent, FLAG_IMMUTABLE)

        return NotificationCompat.Builder(this, NOTIFICATION_ID)
            .setSmallIcon(com.google.android.material.R.drawable.ic_clock_black_24dp)
            .setContentTitle("のてぃふぃけーしょんたいとる")
            .setContentText("のてぃふぃけーしょんてきすと")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setContentIntent(wakeupMePendingIntent)
            .setAutoCancel(true)
    }

これらを、たとえば onCreate() などで呼び出す。
notify() の第1引数は Int 型で、ユニークならよいらしい。あとから中身を更新したり削除したりするときに識別するものだそうだ。

        createNotificationChannel()
        val builder = createNotification()
        with(NotificationManagerCompat.from(this)) {
            notify(NOTIFY_TEST_ID, builder.build())
        }

まあ、アプリの起動と同時に notification を出すことは少ないかもしれんが、うまいことやってほしい。


このアプリを起動すると notification が出てくる。
左側の時計アイコンは、適当に Android Studio の自動補完で候補に出てきたものだから、ちゃんとしたものかどうか知らん。

image

notification の中身は出てきたから良いとして、notification channel で設定したものはどこで出てくるのか?

見つけたのは、アプリごとの「アプリ情報」画面から「通知」をタップして表示される画面だった。

image

これだと notification channel の name だけなのだが、さらに表示されている項目をタップすると description の方も出てきた。

image

 

日本語にしておくと、そしてひらがなにしておくと他の文字列やデバッグ情報と重ならないからありがたいね。

 

ちなみにアプリ名が「AlarmTest」なのは、AlarmManager の実験をしたかったからだ。
時間になったら何かしたい→ notification を出すか、という流れだ。