web-dev-qa-db-ja.com

コードを毎日実行するように定期的なAlarmManagerを設定する方法

私は現在、毎日指定された時間内にアラームを鳴らすアラームマネージャーを作成しようとしています。まず、ユーザーがその日にアラームを設定しているかどうかを確認します。

      if ((User.getReminderTime(Home.this) > 0)
    && (dt.getDate() != today.getDate() || dt.getDay() != today
      .getDay())) {
   AppointmentManager.setFutureAppointmentCheck(this
     .getApplicationContext());
   User.setLongSetting(this, "futureappts", today.getTime());
  }

次に、実際のアラームが翌日の12時から12時10分の間に鳴るように設定します。

     public static void setFutureAppointmentCheck(Context con) {
  AlarmManager am = (AlarmManager) con
    .getSystemService(Context.ALARM_SERVICE);

  Date futureDate = new Date(new Date().getTime() + 86400000);
  Random generator = new Random();

  futureDate.setHours(0);
  futureDate.setMinutes(generator.nextInt(10));
  futureDate.setSeconds(0);

  Intent intent = new Intent(con, FutureAppointmentReciever.class);

  PendingIntent sender = PendingIntent.getBroadcast(con, 0, intent,
    PendingIntent.FLAG_ONE_SHOT);

  am.set(AlarmManager.RTC_WAKEUP, futureDate.getTime(), sender);

 }

これで2分ごとにオフになるようにテスト環境をセットアップしましたが、正常に動作しているようですが、実際のデバイスに展開すると、受信者がアラームを受信して​​いないようです。デバイスがスリープ状態にあることが問題である可能性があると考えたため、電源マネージャーを追加しました。しかし、それでも機能しません:

      PowerManager pm = (PowerManager) context
    .getSystemService(Context.POWER_SERVICE);
  PowerManager.WakeLock wl = pm.newWakeLock(
    PowerManager.PARTIAL_WAKE_LOCK, "keepAlive");
  wl.acquire();
  setFutureAppointments(context.getApplicationContext());
  AppointmentManager.setFutureAppointmentCheck(context
    .getApplicationContext());
  User.setLongSetting(context.getApplicationContext(), "futureappts",
    new Date().getTime());
  wl.release();

誰かが私が露骨に間違っていることを見ているのですか、それとも私がこれについて間違っているのですか?ありとあらゆる助けに感謝します。

17
ninjasense

私は通常、次のようなことをします。

Intent i = new Intent(this, MyService.class);
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.cancel(pi); // cancel any existing alarms
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
    SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_DAY,
    AlarmManager.INTERVAL_DAY, pi);

このように、AlarmManagerServiceを再設定することを心配する必要はありません。

私は通常、アプリの起動時(メインアクティビティではonResume)、およびBOOT_COMPLETEDを受信するように設定されたBroadcastReceiverでこのコードを実行します。

私はServicesの作成とAlarmManagerの使用に関するガイドを書きました。これは、自分の経験と、Google I/Oトークを見ながら選んだいくつかのヒントとテクニックに基づいています。もし興味があれば、それを読むことができます here


以下のあなたの質問に答えるために、私ができることは引用 the docs です:

public void setInexactRepeating (int type, long triggerAtTime, long interval, PendingIntent operation)

トリガー時間要件が不正確な繰り返しアラームをスケジュールします。たとえば、1時間ごとに繰り返されるが、必ずしも1時間ごとに発生するとは限らないアラーム。これらのアラームはsetRepeating(int、long、long、PendingIntent)によって提供される厳密な繰り返しよりも電力効率がよくなります。システムがアラームのフェーズを調整して同時に発火させ、デバイスが必要以上にスリープ状態から復帰しないようにすることができるためです。

アラームの最初のトリガーは要求された時間より前ではありませんが、それ以降はほぼ完全な間隔で発生しない可能性があります。さらに、繰り返しアラームの全体的な期間は要求どおりですが、アラームが2回連続して発生するまでの時間は異なる場合があります。アプリケーションが非常に低いジッターを要求する場合は、代わりにsetRepeating(int、long、long、PendingIntent)を使用してください。

結論として、それはあまり明確ではありません。ドキュメントには、アラームは「異なる可能性がある」とだけ書かれています。ただし、最初のトリガーは、その後のほぼ完全な間隔では発生しない可能性があることを知っておくことが重要です。

44
Felix

これは機能しており、5秒ごとにアラームを発します

private void setRecurringAlarm() {

        Logger.d(IConstants.DEBUGTAG, "Setting Recurring Alarm");

        Calendar updateTime = Calendar.getInstance();

        updateTime.set(Calendar.SECOND, 5);

        Intent alarmIntent = new Intent(this, AlarmReceiver.class);
        PendingIntent recurringDownload = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
        AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarms.cancel(recurringDownload);
        alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), 1000 * 5, recurringDownload); //will run it after every 5 seconds.
    }
4
AZ_