[Android] タイマーアプリをAlarmManagerを使って作る

ある時間にアプリから通知して欲しいという場合がよくあります。目覚まし時計とかスケジュール系のアプリなど、これらの通知には時間を管理する AlarmManager 及びその関連APIを使います。
 
以下は、ボタンタップで5秒後にアラームを発生させる例です。
 
alarmmanager_1

Android Studio 2.1.1
Android 6.0

 

sponsored link

AlarmManager

 
短時間の単純なタイマーや時間計測にはAlarmManagerではなく、Handlerを使うことが推奨されています。

For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.

Ref: AlarmManager
https://developer.android.com/reference/android/app/AlarmManager.html
AlarmManager はアプリが起動していない時にコードを実行させたい場合(バックグラウンドにいるケース)に使うということらしいです。
 

Context.getSystemService(Context.ALARM_SERVICE)

 
このクラスを直接インスタンス化してはいけないようで
Context.getSystemService(Context.ALARM_SERVICE) を使います

 
その後、例えば繰り返しのアラームを設定します

 
sender は PnedingIntent のインスタンスです。これは繰り返しのアラームの例ですが、
AlarmManager でのアラーム設定は

  1. set(int type, long triggerAtMillis, PendingIntent operation)
    • 単発アラーム
  2. setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
    • 繰り返しアラームの設定

Android 19 以降では、Alarmmanagerのポリシーが変わり以下の機能が追加されました。

  1. setExact(int type, long triggerAtMillis, PendingIntent operation)
    • 開始時間からの(多少正確な)アラーム設定
  2. setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
    • おおまかなアラームの繰り返し設定
  3. setWindow((nt type, long windowStartMillis, long windowLengthMillis, PendingIntent operation)
    •  設定したwindow内でアラームが起動する
    • バッテリー電力消費と精度の妥協策

 
これにより、Android 19 以降では set(), setRepeating() の精度は正確ではなくなりました
setRepeating() の誤差とsetExact() setWindow()

その他に

  1. cancel
    • 設定したアラームの取り消し
  2. setTime
    • ミリ秒での時間設定
  3. setTimeZone
    • タイムゾーンの設定

があります
 
また、4つのアラームに関する定数があります

  1. ELAPSED_REALTIME
    • スリープ時間を含んだブートアップからの経過時間
  2. ELAPSED_REALTIME_WAKEUP
    • ELAPSED_REALTIME に加えて、実機スリープ中では wake up してくれる
  3. RTC
    • 時刻
  4. RTC_WAKEUP
    • RTCに加えて実機スリープ中では wake up してくれる

 

PendingIntent

 
PendingIntent は作成した Intent をタイミングを見て他のアプリケーションに渡す場合に使います。

 
getBroadcastの第2引数は requestCode です。PendingIntent が1つの場合は0で大丈夫ですが複数ある時は、この requestCode を使って Receiver 側で切り分けます

Ref: PendingIntent
http://developer.android.com/reference/android/app/PendingIntent.html
 

BroadcastReceiver

 
PendingIntent からの Intent を受け取りるクラスを新しく作ります。そこでアラームを受けトーストします。
 

 

シンプルなアラームだけのアプリ作成

 
これらの内容をふまえて実際にコードを組んでみましょう
 
WAKE_LOCK パーミッションとBroadcast の receiver を入れます。
AndroidManifest.xml

 
ボタンをタップしてアラームをセットするようにします
MainAcrivity.java

 
アラームをBroadcastReceiver で受けます
AlarmBroadcastReceiver.java

 
activity_main.xml

 
アラームを設定して開始
BroadcastReceiver で受け取るという簡単な例でした
次はアラームを通知できるようにしてみます
Alarm をNotificationManager で通知する