Android AlarmManager:如何避免过去的警报响起

Lis*_*nne 4 android alarmmanager android-intent android-activity

嗨,谢谢您的帮助。

我有一个使用AlarmManager在接下来的几周,几个月内每天设置一个警报的应用程序...

  • 我在一周的每一天都设置了一个闹钟来开始活动

  • 一周中的每一天都有一个警报,用于在一段时间后停止活动

我有以下问题,我将尝试在以下几行中进行解释:

今天是星期三,

设置警报后,我打开应用程序并为MON,TUE,WED,THU,FRI,SAT,SUN设置警报:

MON和TUE的所有警报立即关闭,我最终收到4个Activity实例!

请我如何避免这种情况???

请看一段我的代码:

        // SET THE ALARM FOR STARTING THE ACTIVITY 
        Intent smon = new Intent(ctxt, VideoActivty.class);
        smon.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent psmon = PendingIntent.getActivity(ctxt, 0, smon, 0);

        Calendar calSet = Calendar.getInstance();
        calSet.set(Calendar.DAY_OF_WEEK, 2);
        calSet.set(Calendar.HOUR_OF_DAY, hsmon);
        calSet.set(Calendar.MINUTE, msmon);
        calSet.set(Calendar.SECOND, 0);
        calSet.set(Calendar.MILLISECOND, 0);

        mgr.setRepeating(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(),
                7 * 24 * 60 * 60 * 1000, psmon);

        // SET THE ALARM FOR KILLING THE ACTIVITY 
        Intent fmon = new Intent(ctxt, VideoActivty.class);
        fmon.putExtra("finish", true);
        PendingIntent pfmon = PendingIntent.getActivity(ctxt, 0, fmon, 0);

        calSet.set(Calendar.DAY_OF_WEEK, 2);
        calSet.set(Calendar.HOUR_OF_DAY, hfmon);
        calSet.set(Calendar.MINUTE, mfmon);
        calSet.set(Calendar.SECOND, 0);
        calSet.set(Calendar.MILLISECOND, 0);

        mgr.setRepeating(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(),
                7 * 24 * 60 * 60 * 1000, pfmon);
Run Code Online (Sandbox Code Playgroud)

这是活动:

public class VideoActivty extends Activity {
private VideoView video;
private MediaController ctlr;
private PowerManager.WakeLock wl;
private KeyguardLock keyguard;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //
    PowerManager pm = (PowerManager) this
            .getSystemService(this.POWER_SERVICE);
    wl = pm.newWakeLock(
            PowerManager.PARTIAL_WAKE_LOCK, "");
    wl.acquire();

    KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    keyguard = km.newKeyguardLock("MyApp");
    keyguard.disableKeyguard();

    getWindow().setFormat(PixelFormat.TRANSLUCENT);
    VideoView videoHolder = new VideoView(this);
    //if you want the controls to appear
    videoHolder.setMediaController(new MediaController(this));
    Uri video = Uri.parse("android.resource://" + getPackageName() + "/" 
    + R.raw.ingress); //do not add any extension
    //if your file is named sherif.mp4 and placed in /raw
    //use R.raw.sherif
    videoHolder.setVideoURI(video);
    setContentView(videoHolder);

    videoHolder.start();
    videoHolder.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

        @Override
        public void onCompletion(MediaPlayer mp) {

                        mp.start();
        }
    });
}


@Override
protected void onNewIntent (Intent i){


  if( i.getBooleanExtra("finish",false) ){
      wl.release();
      keyguard.reenableKeyguard();
      finish();
  }
}


}
Run Code Online (Sandbox Code Playgroud)

Pao*_*lli 5

由于AlarmManager的API页面说明了有关set(...)setRepeating(...)方法的信息:

“如果指定的触发时间是过去的时间,则警报将立即触发,并根据过去的触发时间与重复间隔的间隔来确定警报计数。”

因此,例如,如果您在星期三,则AlarmManager将触发以下事件:周日,周一,周二和(可能)周三。实际上,所有这些武器只会发射一个。

这是我避免这种情况的方法。不确定这是最好的方法,但是它是否可以顺利运行。

假设您要在以下变量中存储要触发AlarmManager 的星期几小时和一天中的分钟

final int myAlarmDayOfTheWeek = ...;
final int myAlarmHour = ...;
final int myAlarmMinute = ...;
Run Code Online (Sandbox Code Playgroud)

当然,这里我假设您按照与Calendar类相同的约定存储星期几,即:

周日=日历.SUNDAY = 1

星期一=日历。星期一= 2

……

星期六=日历。星期六= 7

然后:

Calendar timestamp = Calendar.getInstance();

//Check whether the day of the week was earlier in the week:
if( myAlarmDayOfTheWeek > timestamp.get(Calendar.DAY_OF_WEEK) ) {
    //Set the day of the AlarmManager:
    time.add(Calendar.DAY_OF_YEAR, (myAlarmDayOfTheWeek - timestamp.get(Calendar.DAY_OF_WEEK)));
}
else {
    if( myAlarmDayOfTheWeek < timestamp.get(Calendar.DAY_OF_WEEK) ) {
        //Set the day of the AlarmManager:
        timestamp.add(Calendar.DAY_OF_YEAR, (7 - (timestamp.get(Calendar.DAY_OF_WEEK) - myAlarmDayOfTheWeek)));
    }
    else {  // myAlarmDayOfTheWeek == time.get(Calendar.DAY_OF_WEEK)
        //Check whether the time has already gone:
        if ( (myAlarmHour < timestamp.get(Calendar.HOUR_OF_DAY)) || ((myAlarmHour == timestamp.get(Calendar.HOUR_OF_DAY)) && (myAlarmMinute < timestamp.get(Calendar.MINUTE))) ) {
            //Set the day of the AlarmManager:
            timestamp.add(Calendar.DAY_OF_YEAR, 7);
        }
    }
}

//Set the time of the AlarmManager:
timestamp.set(Calendar.HOUR_OF_DAY, myAlarmHour);
timestamp.set(Calendar.MINUTE, myAlarmMinute);
timestamp.set(Calendar.SECOND, 0);
Run Code Online (Sandbox Code Playgroud)

请注意,通过在Calendar.add(...)中使用Calendar.DAY_OF_YEAR,您甚至不需要照顾月份的变化...

如果您处于第一个条件(即myAlarmDayOfTheWeek> timestamp.get(Calendar.DAY_OF_WEEK)),则也可以只使用Calendar.set(...),其中Calendar.DAY_OF_WEEK作为字段,而myAlarmDayOfTheWeek作为值。

现在,您只需要设置AlarmManager。例如:

final AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, timestamp.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 7, myAlarmPendingIntent);
Run Code Online (Sandbox Code Playgroud)

还请避免每次都计算日间隔(即24 * 60 * 60 * 1000),而应使用AlarmManager.INTERVAL_DAY(或最多86400000)。