警报系统--时间段计算
//------------------2019-10-24
居然看不懂了,估计使用系统时钟AlarmManager,
在工作时间段内使用Repeating方式每8分钟执行一次,而是休息时段
着使用定时唤醒方式跳过,即比分在08:00使用RTC_WAKEUP唤醒
//------------------End 2019-10-24---------
允许用户指定工作时间段,只有在指定的时间段内警报才会被触发
时段记录结构:
/**
* 说明表示格式与范围是:[00,00 - 24,00]
* 分钟部分范围是[0-59]
* 8,50 表示8点50
* 最小单位是分钟,由0,1,2,3,....1439
* 个指定时间段不能相交,开始时间点与结束时间点必需唯一
* includeTime内各时间段必须按小到大排序
*/
private void initIncludeTime() {
includeTime=new ArrayList<AlarmSetting.HourSegment>();
includeTime.add(new HourSegment(7,0,10,30)); //7:00 - 10:30
includeTime.add(new HourSegment(13,30, 16,30));//13:30 - 16:30
includeTime.add(new HourSegment(18,30, 20,30));//18:30 - 20:30
}
排除时段列表计算:
//计算排除时间列表
int bPoint=0;
List<HourSegment> excludes=new ArrayList<AlarmSetting.HourSegment>();
for (HourSegment s : getIncludeTime()) {
int sBIndex=getIndex(s.beginHour,s.beginMinute);
int sEIndex=getIndex(s.endHour,s.endMinute);
if(sBIndex > bPoint){
excludes.add(new HourSegment(getMoment(bPoint), getMoment(sBIndex-1)));
}
bPoint=sEIndex + 1;
if(bPoint>1439)break;
}
if(bPoint<=1439){
excludes.add(new HourSegment(getMoment(bPoint), getMoment(1439)));
}
完整代码:
package cn.fstudio.alarm; import java.io.Serializable; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import cn.fstudio.util.AppSettingUtil; import android.R.bool; import android.content.Context; import android.util.Log; import android.util.Pair; /** * @author Administrator * */ public class AlarmSetting implements Serializable{ /** * */ private static final long serialVersionUID = 1L; /** * 两次警报窗口的最小间隔时间 */ private Integer fireInterval =10; private Integer pollInterval = 10; private Integer localReviewInterval=5; private Integer refireDelay=45; private List<HourSegment> includeTime=null; public AlarmSetting(){ initIncludeTime(); } /** * 说明表示格式与范围是:[00,00 - 24,00] * 分钟部分范围是[0-59] * 8,50 表示8点50 * 最小单位是分钟,由0,1,2,3,....1439 * 个指定时间段不能相交,开始时间点与结束时间点必需唯一 * includeTime内各时间段必须按小到大排序 */ private void initIncludeTime() { includeTime=new ArrayList<AlarmSetting.HourSegment>(); includeTime.add(new HourSegment(7,0,10,30)); //7:00 - 10:30 includeTime.add(new HourSegment(13,30, 16,30));//13:30 - 16:30 includeTime.add(new HourSegment(18,30, 20,30));//18:30 - 20:30 } /** * 本地轮讯时间 * 指Service触发间隔 * */ public Integer getLocalReviewInterval() { if(localReviewInterval==null)localReviewInterval=5; return localReviewInterval; } public void setLocalReviewInterval(Integer localReviewInterval) { this.localReviewInterval = localReviewInterval; } public Integer getPollInterval() { if(pollInterval==null)pollInterval=10; return pollInterval; } public void setPollInterval(Integer i) { this.pollInterval = i; } public Integer getFireInterval() { if(fireInterval==null)fireInterval=10; return fireInterval; } public void setFireInterval(Integer fireInterval) { this.fireInterval = fireInterval; } public List<HourSegment> getIncludeTime() { if(includeTime==null || (includeTime.size()>0 && includeTime.get(0).beginHour==null))initIncludeTime(); return includeTime; } public void setIncludeTime(List<HourSegment> includeTime) { this.includeTime = includeTime; } public Integer getRefireDelay() { if(refireDelay==null)refireDelay=45; return refireDelay; } public void setRefireDelay(Integer refireDelay) { this.refireDelay = refireDelay; } //========内部类======== public static class HourSegment implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private Integer beginHour=null; private Integer beginMinute=null; private Integer endHour=null; private Integer endMinute=null; public Pair<Integer, Integer> getBegin(){ return new Pair<Integer, Integer>(beginHour, beginMinute); } public Pair<Integer, Integer> getEnd(){ return new Pair<Integer, Integer>(endHour, endMinute); } public Integer getBeginHour() { return beginHour; } public void setBeginHour(Integer beginHour) { this.beginHour = beginHour; } public Integer getBeginMinute() { return beginMinute; } public void setBeginMinute(Integer beginMinute) { this.beginMinute = beginMinute; } public Integer getEndHour() { return endHour; } public void setEndHour(Integer endHour) { this.endHour = endHour; } public Integer getEndMinute() { return endMinute; } public void setEndMinute(Integer endMinute) { this.endMinute = endMinute; } public HourSegment(Integer beginHour, Integer beginMinute, Integer endHour, Integer endMinute) { super(); this.beginHour = beginHour; this.beginMinute = beginMinute; this.endHour = endHour; this.endMinute = endMinute; } public HourSegment(Pair<Integer, Integer> begin,Pair<Integer, Integer> end){ this.beginHour = begin.first; this.beginMinute = begin.second; this.endHour = end.first; this.endMinute = end.second; } } // =========通用====================== public transient static AlarmSetting instance = null; public transient static final String FILENAME="alarmSetting"; private transient static Context appCtx=null; public static synchronized AlarmSetting create(Context ctx) { if (instance == null) { appCtx=ctx; Object obj = AppSettingUtil.load(FILENAME, ctx); if(obj==null){ obj=new AlarmSetting(); AppSettingUtil.save(FILENAME, ctx, obj); } instance=(AlarmSetting) obj; } return instance; } public void save(){ AppSettingUtil.save(FILENAME, appCtx, this); } @Override public String toString() { return "AlarmSetting [fireInterval=" + fireInterval + ", pollInterval=" + pollInterval + ", includeTime=" + includeTime + "]"; } //==================Helper=================== public boolean inWorkTime(){ Calendar calendar=Calendar.getInstance(); int hour=calendar.get(Calendar.HOUR_OF_DAY); int minute= calendar.get(Calendar.MINUTE); Pair<Integer, Integer> curV=new Pair<Integer, Integer>(hour, minute); for (HourSegment s : getIncludeTime()) { if( comparePair(curV,s.getBegin())>=0 && comparePair(curV ,s.getEnd())<=0){ calendar.add(Calendar.MINUTE, getLocalReviewInterval()); return true; } } return false; } /** * @param times 不提供使用系统当前时间 * 如果提供格式是 first=hour,second=minute * 只使用times[0] * @return 返回下一次执行的时间(毫秒) */ public long getNextTriggerMillis(Calendar calendar){ int hour=calendar.get(Calendar.HOUR_OF_DAY); int minute= calendar.get(Calendar.MINUTE); Pair<Integer, Integer> curV=new Pair<Integer, Integer>(hour, minute); for (HourSegment s : getIncludeTime()) { if( comparePair(curV,s.getBegin())>=0 && comparePair(curV ,s.getEnd())<=0){ calendar.add(Calendar.MINUTE, getLocalReviewInterval()); return calendar.getTimeInMillis(); } } //计算排除时间列表 int bPoint=0; List<HourSegment> excludes=new ArrayList<AlarmSetting.HourSegment>(); for (HourSegment s : getIncludeTime()) { int sBIndex=getIndex(s.beginHour,s.beginMinute); int sEIndex=getIndex(s.endHour,s.endMinute); if(sBIndex > bPoint){ excludes.add(new HourSegment(getMoment(bPoint), getMoment(sBIndex-1))); } bPoint=sEIndex + 1; if(bPoint>1439)break; } if(bPoint<=1439){ excludes.add(new HourSegment(getMoment(bPoint), getMoment(1439))); } int index=-1; for (HourSegment s : excludes) { index++; if( comparePair(curV,s.getBegin())>=0 && comparePair(curV ,s.getEnd())<=0){ int waitMinute= comparePair(s.getEnd(), curV); //处理凌晨相连的时间端 if(s.endHour==24 ){ if( excludes.get(0).beginHour==0 && excludes.get(0).beginMinute==0){ waitMinute += (excludes.get(0).endHour * 60 + excludes.get(0).endMinute); } } calendar.add(Calendar.MINUTE, waitMinute + 1); //加一,以便落在执行区域 return calendar.getTimeInMillis(); } } return System.currentTimeMillis(); } /** * 转化成分钟下标 * 0,1,2,3....1439 * */ private static int getIndex(int hour,int minute){ if(hour==0 && minute==0)return 0; return (hour * 60) + minute -1; } /** * 根据下标获取时刻 * */ private static Pair<Integer, Integer> getMoment(int point){ if(point==0)return new Pair<Integer, Integer>(0, 0); point=point +1; return new Pair<Integer, Integer>((point / 60 ) , (point % 60)); } private int comparePair(Pair<Integer, Integer> a,Pair<Integer, Integer> b){ return (a.first * 60 + a.second) - (b.first * 60 + b.second); } }