Android端末の通知バー(ステータスバー)にアプリで指定した日時に通知を出す方法です。
今回やったことはこんな感じです。
- AlarmManagerで指定時間にBroadcastReciver宛のIntentを発行する
- BroadcastReciverの受信処理で通知を表示する
参考にさせて頂いたサイト:
それでは、詳細の説明です。
1.指定時間にIntentを発行する
まずは、AlarmManagerを使用して指定した日時にレシーバー宛のIntentをブロードキャストしてやります。
//呼び出す日時を設定する Calendar triggerTime = Calendar.getInstance(); triggerTime.add(Calendar.SECOND, 5); //今から5秒後 //設定した日時で発行するIntentを生成 Intent intent = new Intent(MainActivity.this, Notifier.class); PendingIntent sender = PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); //日時と発行するIntentをAlarmManagerにセットします AlarmManager manager = (AlarmManager)getSystemService(ALARM_SERVICE); manager.set(AlarmManager.RTC_WAKEUP, triggerTime.getTimeInMillis(), sender);
6-7行目
上記の例では、あとで実装するNotifier.classに直接投げる(明示的なIntent)として実装しています。
また、自ActivityからでなくアンドロイドのALARMサービスからブロードキャストしてもらうため、7行目のPendingIntent.getBroadcast
でPendingIntentオブジェクトを取得しています。
#明示的なIntentをブロードキャストするのはなんかしっくりこない実装ですが・・・
ちなみにPendingIndentはブロードキャストの他にも次のような使い方もできるようです。
メソッド | 振る舞い |
---|---|
getActivity() | Activityを起動するためのPendingIntentオブジェクトを取得します⇒“startActivity(intent)と同じような振る舞い” |
getActivities() | 複数のActivityを起動するためのPendingIntentオブジェクトを取得します |
getService() | サービスを開始するためのPendingIntentオブジェクトを取得します⇒“startService(intent)と同じような振る舞い” |
加えて、PendingIntentのフラグの指定(上記の例ではPendingIntent.FLAG_UPDATE_CURRENTを使用しています)でも振る舞いが変わります。
詳しくは『PendingIntentのフラグ設定による振る舞いの違い』で書いています。
10-11行目
AlarmManagerに発行時間と発行するPendingIntentをセットします。
発行時間の指定方法には4種類あり、今回はRTC_WAKEUPを使用しています。
タイプ | 説明 |
---|---|
ELAPSED_REALTIME | 端末の電源が入ってからの経過時間(=SystemClock.elapsedRealtime())。ただし、アラーム時間に端末がスリープ中であれば、次の端末ウェイクアプ時になる。 |
ELAPSED_REALTIME_WAKEUP | ↑と同じですが、アラーム時間に端末がスリープ中であれば、即ウェイクアップさせます。 |
RTC | 1970/01/01T00:00:00.0(UNIXエポック)からの経過ミリ秒(=System.currentTimeMillis())。ただし、アラーム時間に端末がスリープ中であれば、次の端末ウェイクアプ時になる。 |
RTC_WAKEUP | ↑と同じ。アラーム時間に端末がスリープ中であれば、ウェイクアップさせます。 |
これで指定した時間にNotifierのonRecived()メソッドが実行されるようになりました。
#ただし、AlarmManagerは端末の電源が切られるとセットされたアラームを忘れてしまうので、必要に応じて端末ブート時に再セットしてやる処理が必要です
#起動時の再スケジューリング方法はこちらです→http://workpiles.com/2014/07/android-alarmmanager-boot/
2.受信処理で通知を表示する
次は受信処理です。ブロードキャストされたIntentの受信にはBroadcastReceiverを使用します。
BroadcastReceiverクラスを継承した受信クラスを用意しonReceive()メソッドをオーバーライドして、通知バーに通知を出す処理を実装してあげれば完成です。
Androidで通知機能を使うためにはNotificationオブジェクトを生成し、NotificationManagerのnotitfi()メソッドに渡してあげることで通知ができます。
また、通知をクリックした時に他のアプリを起動した場合は、クリックされた時に発行されるIntentインスタンスを準備しておきます。
public class Notifier extends BroadcastReceiver { @Override public void onReceive(Context content, Intent intent) { //通知がクリックされた時に発行されるIntentの生成 Intent sendIntent = new Intent(content, MainActivity.class); PendingIntent sender = PendingIntent.getActivity(content, 0, sendIntent, 0); //通知オブジェクトの生成 Notification noti = new NotificationCompat.Builder(content) .setTicker("お時間ですよ!") .setContentTitle("通知") .setContentText("設定した時間がきました") .setSmallIcon(R.drawable.ic_launcher) .setVibrate(new long[]{0, 200, 100, 200, 100, 200}) .setAutoCancel(true) .setContentIntent(sender) .build(); NotificationManager manager = (NotificationManager)content.getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(0, noti); } }
7~8行目
上記例では、通知をクリックしたときに自身のMainActivityを起動するようにしています。
11~19行目
Notificationオブジェクトを生成しています。Notificationオブジェクトの生成にはNotification.Builderを使用すると楽なのですがAndroid3.0(API lv.11)以降でないと使用できないため、サポートライブラリのAndroid.Support.v4.app.NotificationCompat.Builderを使用しています。
setTicker()で通知時に通知バーに表示される文字列を設定したりと色々パラメータを設定した後にbuild()でNotificationオブジェクトを生成します。
setVibrate()で通知時にバイブレーションさせるためにはAndroidManifest.xmlでパーミッションの追加も必要になるので忘れずに!(よく忘れる)
<uses-permission android:name="android.permission.VIBRATE"/>
21~23行目
NotificationManagerのnotifiy()メソッドに生成したNotificationオブジェクトを渡すと通知バーに通知が表示されます。
以上でコード実装部は終了です。最後にAndroidManifest.xmlにReciverを登録します。
<receiver android:name="Notifier"></receiver>
サンプルコード
サンプルアプリです。
https://github.com/workpiles/NotificationTest
アプリを起動してボタンを押すと自動的にアプリは終了されますが、5秒後に通知バーに通知が出ます。
その通知をクリックするとアプリをアプリを起動します。