AlarmManager
クラスをベースにしたアラームを使用すると、アプリの実行期間外に時間ベースで処理を実行できます。たとえば、1 日に 1 回サービスを開始して天気予報をダウンロードするなど、アラームを使用することによって実行時間が長い処理を開始できます。
アラームには以下の特徴があります。
設定した時間または周期的(あるいはその両方)にインテントを開始できます。
ブロードキャスト レシーバと組み合わせて使用すると、ジョブや WorkRequest をスケジュールして他の処理を実行できます。
アラームはアプリの外部で動作するため、アプリが実行されていないときや、デバイス自体がスリープ状態になっているときでも、アラームを使用してイベントやアクションをトリガーできます。
アラームを通じてアプリのリソース要件を最小限に抑えることができます。タイマーや継続的に実行されるサービスに依存することなく、オペレーションのスケジュールを設定できます。
不正確なアラームを設定する
アプリが不正確なアラームを設定すると、システムは将来のどこかの時点でアラームを配信します。不正確なアラームは、Doze などのバッテリー節約に関する制限を尊重しながら、アラーム配信のタイミングに関して一定の保証を提供します。
デベロッパーは、次の API 保証を利用して、不正確なアラームの配信タイミングをカスタマイズできます。
特定の時間の経過後にアラームを配信する
アプリが set()
、setInexactRepeating()
、または setAndAllowWhileIdle()
を呼び出す場合、指定されたトリガー時刻より前にアラームが鳴ることはありません。
Android 12(API レベル 31)以降では、バッテリー セーバーや Doze などのバッテリー節約に関する制限が有効になっていない限り、システムは指定されたトリガー時刻から 1 時間以内にアラームを呼び出します。
時間枠内にアラームを配信する
アプリが setWindow()
を呼び出すと、指定されたトリガー時刻より前にアラームが鳴ることはありません。省電力モードの制限が有効になっていない限り、アラームは指定された時間枠内で、指定されたトリガー時刻から配信されます。
アプリが Android 12 以降をターゲットとしている場合、システムは時間枠付きの不正確なアラームの呼び出しを 10 分以上遅らせることができます。このため、600000
未満の windowLengthMillis
パラメータ値は 600000
にクリップされます。
ほぼ一定の間隔で繰り返しアラームを配信する
アプリが setInexactRepeating()
を呼び出すと、システムは複数のアラームを呼び出します。
- 最初のアラームは、指定された時間枠内で、指定されたトリガー時刻から開始されます。
- 通常、後続のアラームは指定された時間枠が経過した後に発生します。アラームの連続する 2 回の呼び出しの間隔は変動する可能性があります。
正確なアラームを設定する
システムは、将来の正確なタイミングで正確なアラームを呼び出します。
ほとんどのアプリは、不正確なアラームを使用してタスクやイベントのスケジュール設定を行い、いくつかの一般的なユースケースを完了できます。目覚まし時計アプリやカレンダー アプリなど、アプリのコア機能が正確なタイミングのアラームに依存している場合は、代わりに正確なアラームを使用しても構いません。
正確なアラームを必要としないユースケース
正確なアラームを必要としない一般的なワークフローを以下に示します。
- アプリの全期間におけるタイミング オペレーションのスケジュール設定
Handler
クラスには、アプリが動作している間、n 秒ごとに処理を行うなど、タイミング処理を行うための優れたメソッドがいくつか含まれています。postAtTime()
とpostDelayed()
です。これらの API は、リアルタイムではなく、システムの稼働時間に依存します。- アプリの更新やログのアップロードなど、バックグラウンド処理のスケジュール設定
WorkManager
を使用すると、タイミングが重要となる定期的な処理のスケジュールを設定できます。繰り返し間隔とflexInterval
(15 分以上)を指定して、処理のランタイムを細かく定義できます。- 特定の時間が経過した後に行う必要があるユーザー指定のアクション(システムがアイドル状態の場合でも)
- 不正確なアラームを使用します。具体的には、
setAndAllowWhileIdle()
を呼び出します。 - 特定の時間が経過した後に行う必要があるユーザー指定のアクション
- 不正確なアラームを使用します。具体的には、
set()
を呼び出します。 - 指定された時間枠内で行われる可能性があるユーザー指定のアクション
- 不正確なアラームを使用します。具体的には、
setWindow()
を呼び出します。アプリが Android 12 以降をターゲットとしている場合、許可される最小のウィンドウ長は 10 分です。
正確なアラームを設定する方法
アプリでは、次のいずれかの方法で正確なアラームを設定できます。これらのメソッドは、リストの下に近づくほど時間的に重要なタスクを処理するが、より多くのシステム リソースを必要とするように順序付けられています。
setExact()
他のバッテリー節約対策が有効になっていない限り、ほぼ正確な時刻にアラームを呼び出します。
アプリの作業がユーザーにとって時間的に重要な場合を除き、このメソッドを使用して正確なアラームを設定します。
setExactAndAllowWhileIdle()
省電力対策が有効になっている場合でも、ほぼ正確な時刻にアラームを呼び出します。
setAlarmClock()
将来の正確な時刻にアラームを呼び出します。これらのアラームはユーザーに表示されやすいため、システムが配信時間を調整することはありません。システムはこれらのアラームを最も重要なアラームとして識別し、アラームを配信するために必要に応じて低電力モードを終了します。
システム リソースの使用量
アプリが設定している正確なアラームがシステムによってトリガーされると、特に省電力モードの場合、デバイスはバッテリーなどのリソースを大量に消費します。さらに、システムはリソースを効率的に使用する必要があるため、これらのリクエストを簡単にバッチ処理することができません。
可能な限り 不正確なアラームを作成することを強くおすすめします。長時間にわたる作業を行うには、アラームの BroadcastReceiver
から WorkManager
または JobScheduler
を使用してスケジュールを設定します。デバイスが Doze モードの間に作業を行うには、setAndAllowWhileIdle()
を使用して不正確なアラームを作成し、そのアラームによってジョブを開始します。
適切な正確なアラームの権限を宣言する
アプリが Android 12 以降を対象にしている場合、「アラームとリマインダー」の特別なアプリアクセスを取得する必要があります。そのためには、次のコード スニペットに示すように、アプリのマニフェスト ファイルで SCHEDULE_EXACT_ALARM
権限を宣言します。
<manifest ...> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/> <application ...> ... </application> </manifest>
アプリのターゲットが Android 13(API レベル 33)以降の場合、SCHEDULE_EXACT_ALARM
権限または USE_EXACT_ALARM
権限のいずれかを宣言できます。
<manifest ...> <uses-permission android:name="android.permission.USE_EXACT_ALARM"/> <application ...> ... </application> </manifest>
SCHEDULE_EXACT_ALARM
権限と USE_EXACT_ALARM
権限はどちらも同じ機能をシグナルしますが、付与方法が異なり、サポートするユースケースも異なります。ユーザー向けの機能で正確な時刻にアクションを実行する必要がある場合に限り、アプリで正確なアラームを使用して、SCHEDULE_EXACT_ALARM
または USE_EXACT_ALARM
のいずれかの権限を宣言する必要があります。
USE_EXACT_ALARM
- 自動的に付与
- ユーザーが取り消すことはできません
- Google Play の今後のポリシーに準拠している
- 限定的なユースケース
SCHEDULE_EXACT_ALARM
- ユーザーによる許可
- 幅広いユースケース
- アプリは、権限が取り消されていないことを確認する必要があります
Android 13(API レベル 33)以降をターゲットとするアプリの新規インストールでは、SCHEDULE_EXACT_ALARM
権限は事前付与されません。ユーザーがバックアップと復元の処理を介して Android 14 を搭載したデバイスにアプリデータを転送する場合、新しいデバイスでは SCHEDULE_EXACT_ALARM
権限は拒否されます。ただし、この権限が既存のアプリに付与されている場合は、デバイスが Android 14 にアップグレードされたときにこの権限が事前付与されます。
注: setExact
API などで OnAlarmListener
オブジェクトを使用して正確なアラームが設定されている場合、SCHEDULE_EXACT_ALARM
権限は必要ありません。
SCHEDULE_EXACT_ALARM
権限を使用する
USE_EXACT_ALARM
とは異なり、SCHEDULE_EXACT_ALARM
権限はユーザーが許可する必要があります。ユーザーとシステムの両方が SCHEDULE_EXACT_ALARM
権限を取り消すことができます。
アプリに権限が付与されているかどうかを確認するには、正確なアラームを設定する前に canScheduleExactAlarms()
を呼び出します。アプリの SCHEDULE_EXACT_ALARM
権限が取り消されると、アプリは停止され、今後の正確なアラームはすべてキャンセルされます。つまり、canScheduleExactAlarms()
から返される値は、アプリのライフサイクル全体で有効なままになります。
アプリに SCHEDULE_EXACT_ALARMS
権限が付与されると、システムはそのアプリに ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
ブロードキャストを送信します。アプリでは、以下を行うブロードキャスト レシーバを実装する必要があります。
- アプリにまだ特別なアプリアクセスがあることを確認する。これを行うには、
canScheduleExactAlarms()
を呼び出します。このチェックにより、ユーザーがアプリに権限を付与した後、すぐに取り消すケースからアプリを保護できます。 - アプリが必要とする正確なアラームのスケジュールを、現在の状態に基づいて変更する。このロジックは、アプリが
ACTION_BOOT_COMPLETED
ブロードキャストを受信したときの動作と同様です。
SCHEDULE_EXACT_ALARM
権限を付与するようユーザーにリクエストする
必要に応じて、図 1 に示すように、システム設定の [アラームとリマインダー] 画面にユーザーを誘導できます。そのための手順は次のとおりです。
- アプリの UI で、アプリが正確なアラームのスケジュールを設定する必要がある理由をユーザーに説明します。
ACTION_REQUEST_SCHEDULE_EXACT_ALARM
インテント アクションを含むインテントを呼び出します。
反復アラームを設定する
繰り返しアラームを使用すると、システムは定期的なスケジュールでアプリに通知できます。
アラームが適切に設計されていないと、電池を消耗させるだけでなく、サーバーへの負荷が大きくなる可能性があります。そのため、Android 4.4(API レベル 19)以降では、すべての反復アラームが不正確なアラームになります。
反復アラームには以下の特徴があります。
アラームタイプ。詳しくは、アラームタイプを選択するをご覧ください。
トリガー時間。指定したトリガー時間が過去の場合、アラームがすぐにトリガーされます。
アラームの間隔。たとえば、1 日 1 回、1 時間ごと、5 分ごとなどです。
アラームがトリガーされたときに開始するペンディング インテント。同じペンディング インテントを使用する 2 つ目のアラームを設定すると、そのアラームで元のアラームが置き換えられます。
PendingIntent()
をキャンセルするには、FLAG_NO_CREATE
を PendingIntent.getService()
に渡してインテントのインスタンスが存在する場合はそれを取得し、次にそのインテントを AlarmManager.cancel()
に渡します。
Kotlin
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager val pendingIntent = PendingIntent.getService(context, requestId, intent, PendingIntent.FLAG_NO_CREATE) if (pendingIntent != null && alarmManager != null) { alarmManager.cancel(pendingIntent) }
Java
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); PendingIntent pendingIntent = PendingIntent.getService(context, requestId, intent, PendingIntent.FLAG_NO_CREATE); if (pendingIntent != null && alarmManager != null) { alarmManager.cancel(pendingIntent); }
アラームタイプを選択する
反復アラームを使用する場合、最初にどのタイプにするかを検討する必要があります。
アラームの一般的なクロックタイプには、「実経過時間」と「リアルタイム クロック」(RTC)の 2 つがあります。実経過時間ではリファレンスとして「システムが起動してからの経過時間」を使用し、リアルタイム クロックでは UTC(ウォール クロック)時間を使用します。つまり、実経過時間はタイムゾーンやロケールの影響を受けないため、時間の経過に基づくアラームの設定に適しています(30 秒ごとにトリガーされるアラームなど)。リアルタイム クロックは、現在のロケールに依存するアラームに適しています。
どちらのタイプにも、画面がオフの場合にデバイスの CPU のスリープを解除するように指示する「wakeup」バージョンが用意されています。これにより、スケジュール設定された時間にアラームを確実にトリガーできます。この機能は、アプリが時間に依存している場合に便利です。たとえば、特定の処理を制限時間内に行う必要がある場合などです。wakeup バージョンのアラームタイプを使用しない場合、デバイスが次に起動したときにすべての反復アラームがトリガーされます。
単に特定の間隔(30 分ごとなど)でアラームをトリガーする必要がある場合は、実経過時間タイプのいずれかを使用します。通常はこのタイプを選択することをおすすめします。
特定の時間帯にアラームをトリガーする必要がある場合は、時間ベースのリアルタイム クロックタイプのいずれかを選択します。ただし、このアプローチにはいくつかのデメリットがあります。アプリが他のロケールにうまく翻訳されない可能性があります。また、ユーザーがデバイスの時刻設定を変更すると、アプリで予期しない動作が発生する可能性があります。上記のように、リアルタイム クロックのアラーム タイプを使用しても、うまくスケーリングできません。できれば、アラームタイプには「実経過時間」を使用することをおすすめします。
以下に、アラームタイプの一覧を示します。
ELAPSED_REALTIME
: デバイスが起動してからの経過時間に基づいてペンディング インテントを開始しますが、デバイスのスリープは解除しません。経過時間には、デバイスがスリープしていた時間が含まれます。ELAPSED_REALTIME_WAKEUP
: デバイスが起動してから指定された時間が経過した後にデバイスのスリープを解除し、ペンディング インテントを開始します。RTC
: 指定された時間にペンディング インテントを開始します。ただし、デバイスのスリープは解除しません。RTC_WAKEUP
: 指定された時間にデバイスのスリープを解除してペンディング インテントを開始します。
実経過時間タイプのアラームの例
以下に、ELAPSED_REALTIME_WAKEUP
の使用例をいくつか示します。
30 分後にデバイスのスリープを解除してアラームをトリガーします。その後は 30 分ごとにこの処理を行います。
Kotlin
// Hopefully your alarm will have a lower frequency than this! alarmMgr?.setInexactRepeating( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent )
Java
// Hopefully your alarm will have a lower frequency than this! alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);
1 分後にデバイスのスリープを解除し、アラームを 1 回だけ(反復なし)トリガーします。
Kotlin
private var alarmMgr: AlarmManager? = null private lateinit var alarmIntent: PendingIntent ... alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent -> PendingIntent.getBroadcast(context, 0, intent, 0) } alarmMgr?.set( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60 * 1000, alarmIntent )
Java
private AlarmManager alarmMgr; private PendingIntent alarmIntent; ... alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, AlarmReceiver.class); alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60 * 1000, alarmIntent);
リアルタイム クロックタイプのアラームの例
以下に、RTC_WAKEUP
の使用例をいくつか示します。
午後 2 時ごろにデバイスのスリープを解除してアラームをトリガーします。毎日 1 回、同じ時間にこの処理を行います。
Kotlin
// Set the alarm to start at approximately 2:00 p.m. val calendar: Calendar = Calendar.getInstance().apply { timeInMillis = System.currentTimeMillis() set(Calendar.HOUR_OF_DAY, 14) } // With setInexactRepeating(), you have to use one of the AlarmManager interval // constants--in this case, AlarmManager.INTERVAL_DAY. alarmMgr?.setInexactRepeating( AlarmManager.RTC_WAKEUP, calendar.timeInMillis, AlarmManager.INTERVAL_DAY, alarmIntent )
Java
// Set the alarm to start at approximately 2:00 p.m. Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.HOUR_OF_DAY, 14); // With setInexactRepeating(), you have to use one of the AlarmManager interval // constants--in this case, AlarmManager.INTERVAL_DAY. alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);
午前 8 時半ちょうどにデバイスのスリープを解除してアラームをトリガーします。その後は 20 分ごとにこの処理を行います。
Kotlin
private var alarmMgr: AlarmManager? = null private lateinit var alarmIntent: PendingIntent ... alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent -> PendingIntent.getBroadcast(context, 0, intent, 0) } // Set the alarm to start at 8:30 a.m. val calendar: Calendar = Calendar.getInstance().apply { timeInMillis = System.currentTimeMillis() set(Calendar.HOUR_OF_DAY, 8) set(Calendar.MINUTE, 30) } // setRepeating() lets you specify a precise custom interval--in this case, // 20 minutes. alarmMgr?.setRepeating( AlarmManager.RTC_WAKEUP, calendar.timeInMillis, 1000 * 60 * 20, alarmIntent )
Java
private AlarmManager alarmMgr; private PendingIntent alarmIntent; ... alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, AlarmReceiver.class); alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); // Set the alarm to start at 8:30 a.m. Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.HOUR_OF_DAY, 8); calendar.set(Calendar.MINUTE, 30); // setRepeating() lets you specify a precise custom interval--in this case, // 20 minutes. alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * 20, alarmIntent);
アラームに必要な精度を決定する
前述のとおり、アラームの作成では通常、最初にアラームタイプを選択します。さらに、アラームに必要な精度も選択する必要があります。ほとんどのアプリでは、setInexactRepeating()
を選択することをおすすめします。このメソッドを使用すると、Android によって複数の不正確な反復アラームが同期され、それらが同時にトリガーされます。これにより、電池の消耗を抑えることができます。
可能な場合は、正確なアラームを使用しないでください。ただし、厳密な時間要件のあるアプリもまれにありますが、その場合は setRepeating()
を呼び出して正確なアラームを設定できます。
setInexactRepeating()
では、setRepeating()
のようにカスタムの間隔を指定できません。代わりに、間隔定数(INTERVAL_FIFTEEN_MINUTES
、INTERVAL_DAY
など)のいずれかを使用する必要があります。完全なリストについては、AlarmManager
をご覧ください。
アラームのキャンセル
アプリによっては、アラームをキャンセルする機能を追加することをおすすめします。アラームをキャンセルするには、Alarm Manager で cancel()
を呼び出し、開始する必要がなくなった PendingIntent
を渡します。次に例を示します。
Kotlin
// If the alarm has been set, cancel it. alarmMgr?.cancel(alarmIntent)
Java
// If the alarm has been set, cancel it. if (alarmMgr!= null) { alarmMgr.cancel(alarmIntent); }
デバイスの再起動時にアラームを開始する
デフォルトでは、デバイスがシャットダウンするとすべてのアラームがキャンセルされます。アラームがキャンセルされないようにするには、ユーザーがデバイスを再起動したときに自動的に反復アラームを再開するようにアプリを設計します。こうすることで、ユーザーが手動でアラームを再開しなくても AlarmManager
によってタスクの実行が継続されます。
手順は次のとおりです。
アプリのマニフェストで
RECEIVE_BOOT_COMPLETED
権限を設定します。これにより、システムが起動を終了した後にブロードキャストされるACTION_BOOT_COMPLETED
をアプリで受信できます(この処理は、アプリがユーザーによって 1 回以上起動されたことがある場合にのみ行われます)。<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
ブロードキャストを受信する
BroadcastReceiver
を実装します。Kotlin
class SampleBootReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == "android.intent.action.BOOT_COMPLETED") { // Set the alarm here. } } }
Java
public class SampleBootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { // Set the alarm here. } } }
アプリのマニフェスト ファイルにレシーバを追加し、
ACTION_BOOT_COMPLETED
アクションに基づいてフィルタするインテント フィルタを指定します。<receiver android:name=".SampleBootReceiver" android:enabled="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"></action> </intent-filter> </receiver>
マニフェストで起動レシーバが
android:enabled="false"
に設定されていることに注目してください。つまり、アプリで明示的にレシーバを有効にしない限り、レシーバは呼び出されません。このため、起動レシーバが不必要に呼び出されるのを防ぐことができます。レシーバを有効にするには次のように記述します(ユーザーがアラームを設定する場合など)。Kotlin
val receiver = ComponentName(context, SampleBootReceiver::class.java) context.packageManager.setComponentEnabledSetting( receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP )
Java
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class); PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
この方法でレシーバを有効にすると、ユーザーがデバイスを再起動しても有効なままになります。つまり、レシーバをプログラムで有効にした場合、再起動後もマニフェストの設定より優先されます。レシーバは、アプリによって無効にされるまで有効なままになります。レシーバを無効にするには次のように記述します(ユーザーがアラームをキャンセルする場合など)。
Kotlin
val receiver = ComponentName(context, SampleBootReceiver::class.java) context.packageManager.setComponentEnabledSetting( receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP )
Java
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class); PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
デバイスが Doze モードのときにアラームを呼び出す
Android 6.0(API レベル 23)を搭載したデバイスは、デバイスの電池寿命を延ばす Doze モードをサポートしています。デバイスが Doze モードの場合、アラームは起動しません。スケジュール設定されたアラームは、デバイスが Doze モードを終了するまで延期されます。デバイスがアイドル状態でも処理を完了させる必要がある場合に使用できる方法はいくつかあります。
正確なアラームを設定します。
バックグラウンド処理を実行するように構築された WorkManager API を使用します。システムに作業を優先して処理させ、できるだけ早く完了させるように指示できます。詳しくは、WorkManager でタスクのスケジュールを設定するをご覧ください。
おすすめの方法
反復アラームを設計する際に行うあらゆる選択が、アプリによるシステム リソースの使用方法に影響を及ぼし、選択次第でシステム リソースの乱用につながることもあります。たとえば、サーバーと同期する一般的なアプリについて考えてみましょう。同期処理が時刻に基づいて行われ、アプリのすべてのインスタンスが午後 11 時に同期される場合、サーバーに対する負荷により、レイテンシが高くなる可能性があるほか、「サービス拒否」につながる恐れもあります。アラームを使用する場合は、以下のおすすめの方法に従ってください。
反復アラームの結果としてトリガーされるすべてのネットワーク リクエストにランダム性(ジッター)を追加します。
アラームがトリガーされたときにローカル処理を実行します。「ローカル処理」とは、サーバーにアクセスしない処理、またはサーバーのデータを必要としない処理を意味します。
一方、ネットワーク リクエストを含むアラームは、ランダムな時間帯にトリガーされるようにスケジュール設定します。
アラームの頻度は最小限に維持します。
不必要にデバイスのスリープを解除しないでください(アラームタイプを選択するで説明するように、この動作はアラームタイプによって決まります)。
アラームのトリガー時間を必要以上に正確に設定しないでください。
setRepeating()
ではなくsetInexactRepeating()
を使用します。setInexactRepeating()
を使用すると、Android によって複数のアプリの反復アラームが同期され、それらが同時にトリガーされます。これにより、デバイスのスリープを解除する回数が減り、電池の消耗を抑えることができます。Android 4.4(API レベル 19)の時点では、すべての反復アラームが不正確なアラームです。setInexactRepeating()
はsetRepeating()
に比べて改善されていますが、それでも、アプリのすべてのインスタンスがほぼ同時にサーバーにアクセスすると、サーバーに大きな負荷がかかる可能性があります。そのため、ネットワーク リクエストの場合は、前述のようにアラームにランダム性を追加します。可能であれば、時刻に基づいてアラームをトリガーすることは避けてください。
正確なトリガー時刻に基づく反復アラームはうまく調整できません。可能であれば
ELAPSED_REALTIME
を使用してください。アラームタイプについては次のセクションで詳しく説明します。