[Android] AlarmManagerをBroadcastRecieverと使う

ある時間にアプリから通知して欲しいという場合がよくあります。目覚まし時計とかスケジュール系のアプリなど、これらの通知には時間を管理する AlarmManager 及びその関連APIを使います。
 
 
1x1.trans - [Android] AlarmManagerをBroadcastRecieverと使う

Android Studio
2021.2.1

 




AlarmManager

 
いきなりですが、アプリのオプションでアラームを鳴らしたいだけなら、Intentを使ったアラーム クロックを使うと簡単です。
 
また、setExactAndAllowWhileIdleをサービスを使って繰り返す方法もあります。

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

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

Ref: AlarmManager


 
また、AlarmをBroadcastReceiver で受けるケースでは、ブロードキャストの制限事項 があります。

Android 8.0 を対象にしているアプリは、暗黙的なブロードキャストに対するブロードキャスト レシーバーをマニフェストで登録できなくなりました。 

明示的な登録であれば大丈夫のようです。元々の理由が暗黙的BroadcastRecieverがたくさんあると関係ないアプリも毎回呼び出しを食らってリソース、消費電力の観点からよくないと言う理由からです。

また、AlarmManagerを使う上で、Dozeモードという低消費電力モードを考えないといけないのですが、API levelによって挙動が異なります。
つまり目覚まし時計を作ろうとした場合、このあたりをうまくやらないと時間通りにアラームが鳴りません。

https://akira-watson.com/android/setwindow-repeat.html

この他にタスクスケジュールを実行できるののとしてJobSchedulerやJobDispatcherなどがあります。
 

 

AlarmManager

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


 
その後、例えば繰り返しのアラームメソッド set はこのように設定します


 
sender は PnedingIntent のインスタンスです。
これは単発アラームの例ですが、他にもメソッドがいくつもあります。

また、API levelによって様々追加されました。AlarmManager | Android Developers

  • API level 19: アラーム時間の精度が低いものが使えるようになる
  • API level 23: Dozeモードの導入でDoze中でも起動できるメソッドの追加
  • API level 24: Direct callbackが使えるメソッド

set: ワンショットのアラーム, API level 19 以降では低精度


 
set: 上記set に Direct callback が追加


 
setRepeating: 繰り返しアラーム


 
setInexactRepeating: 繰り返しアラーム、API level 19 以降では低精度


   
setExact: setよりも正確なワンショットアラーム


 
setExact: 上記setExactに Direct Callback が追加


 
setAndAllowWhileIdle: setと同じだが low-power idleモードでも実行される。


 

 

setExactAndAllowWhileIdle: setExactと同じだが low-power idleモードでも実行される。


Doze中でも定期的にアラームを出にはこれらを使います。
 
 
setWindow: 設定したwindow内でアラームが実行


 
setWindow: 上記setWindowにDirect Callbackが追加


 
setAlarmClock: Dozeモードでもアラームを出してくれるようです。


 
また、その他に

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

などがあります
 
また、アラームに関する定数が幾つかあります。例えば、

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

 

 

PendingIntent

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


Android 12からは PendingIntentのmutability(可変性) を指定するために
FLAG_IMMUTABLE を設定する必要があります。

PeindingIntentでは受け取った側が指定されていないパラメータを追加して投げることができるためにFLAG_IMMUTABLEを明示的に指定して上書きできないようにします。
(FLAG_MUTABLE は書き換えできる)

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

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

setExactなどの正確なアラームを設定したアプリでは、システム設定の [特別なアプリアクセス] 画面に表示される「アラームとリマインダー」機能へのアクセス権が必要になります。

マニフェストで SCHEDULE_EXACT_ALARM 権限をリクエストします。

 

BroadcastReceiver

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

 

サンプルコード

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


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


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


 
activity_main.xml

 

サンプル動画

 

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

 
References:
AlarmManager | Android Developers
BroadcastReceiver | Android Developers
PendingIntent | Android Developers

シェアする

  • このエントリーをはてなブックマークに追加

フォローする