はじめに

Notificationを時間指定して発行する際に気になった点をまとめた記事です。
通知の出し方を知っている前提で記事を書いていますので、一部のコードの説明しか載せていません。
リクエストがあれば、コードをGitHubにあげようと思います。

やりたかったこと

1. 通知を指定した時間に発行する。
2. 特定の時間毎に通知を発行する。

実装する前に考えていた疑問

  1. どのように、同じ通知や同じ種類の通知を上書きして(前の通知を消して)通知するのか
  2. どのように、通知発行の指示後に届く時間を変更するのか
  3. どのようにインターバルの時間を変更するのか

"疑問"に対する回答

  1. NotificationManager.notify(id, notification)のidを同じものに指定し、再発行すれば、同idの通知は上書きされる。

  2. PendingIntent.getBroadcast(context, requestCode, intent, flags)のrequestCode, flagsに気をつけて、再発行すれば可能。

  3. "2"同様に同じrequestCodeのPendingIntentを使えば、上書き可能。

大まかな流れとして

具体的なコードが知りたい方は、下記のサイトに具体的なコードが書かれています、とても参考になりました。

TECH Projin - Android 指定した日時に通知(Notification)を送る
http://tech.pjin.jp/blog/2017/05/31/android_schedule_notification/

TaoSoftware Developer Blog - AlarmManager 2 定期的な間隔で繰り返し処理をするプログラム
http://www.taosoftware.co.jp/blog/2009/02/alarmmanager.html

具体的に....

□NotificationManager.notify(id, notification)

第一引数である id が、同じであれば上書き、異なっていれば新規に、通知が発行される。

公式 - NotificationManager.notify()
https://developer.android.com/reference/android/app/NotificationManager.html#notify(int, android.app.Notification)

□PendingIntent.getBroadcast(context, requestCode, intent, flags)

第二引数の requestCode がIdentiferとなって、BroadcastReceiverを上書きするか、新規に作成するかを決めている。
また、flagsで上書きする時の処理の仕方を決めている。
詳しく説明しているサイトがあったので引用させてもらいます。

50ぱーせんとおふ - PendingIntentとAlarmManager
http://mashi.exciton.jp/archives/tag/pendingintent

□AlarmManager.setRepeating(type, triggerAtMillis, intervalMillis, operation)

Parameters
int type どの時間を使用するか(通常はRTC_WAKEUPで良いかと...)
long triggerAtMillis 始める時間(ミリ秒)
long intervalMillis 間隔の時間(ミリ秒)
PendingIntent operation PengingIntent.getBroadcast()等で作成したPendingIntent

詳しく説明しているサイトがあったので引用させてもらいます。

Y.A.M の 雑記帳 - AlarmManager
http://y-anz-m.blogspot.jp/2011/03/alarmmanager.html

±1分くらいはズレても良い場合は、
□AlarmManager.setInexactRepeating(type, triggerAtMillis, intervalMillis, operation)
を使うと良いみたいです。

通知の取り消し方

通常の通知の場合は、
□NotificationManager.cancel(int id)
を使うことで簡単に取り消せますが、時間指定した通知の場合はどうすれば良いか。

この場合は、セットした AlarmManager にキャンセルしてもらいます。
□AlarmManager.cancel(PendingIntent operation)
この時、セットするときに作成したPendingIntentを使うのですが、ほとんどの場合、保持していません。
なので、"AlarmUtil.java" のようなAlarmを統括して、作成・登録・取消を行うクラスを作っておきましょう。
cancel()に使うPendingIntentは、Intent.filterEquals()で同一かどうかが決まり、同一と見なされれば取り消すことができます。
なので、同じ方法で作ったPendingIntentを引数に入れれば、取消可能です。
Intent.filterEquals()について詳しく説明しているサイトがあったので引用させていただきます。

Developers.IO - Android の Intent はどんな時に “同じ Intent” として扱われるか
https://dev.classmethod.jp/smartphone/android/android-intent-filter-equals/

結論

時間通りに繰り返して通知を出すって、結構面倒なものなんですね.....
エミュレータだと通知タイミングが結構ズレたりするので、実機でテストした方が良いと思います。
処理速度とかそこらへんが原因だったりするのかな?
知っている方がいれば、教えてくださいお願いします......。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.