菜鸟入坑记——第一篇
关键字:AlarmManager
一、AlarmManager简介:
了解android低电耗模式:https://developer.android.google.cn/training/monitoring-device-state/doze-standby.html
AlarmManager的作用:在特定的时刻为我们广播一个指定的Intent。
即:自己设定一个时间,当系统时间到达此时间时,AlarmManager自动广播一个我们设定好的Intent,指向某个Activity或Service。
注意:① AlarmManager主要用来在某个时刻运行你的代码,即使你的APP在那个特定的时间并没有运行。
二、获得AlarmManager实例对象:
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
三、方法:
setExact(int type, long startTime, PendingIntent pi); 一次性闹钟,执行时间精确,为精确闹钟
四、程序设计:
(1)类型type
此处选用闹钟类型为AlarmManager.RTC:闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间(当前系统时间),状态值为1。
(2)开始时间startTime
由于通过SP获得的时间为String类型,需先转换为long类型,且时间单位为ms
1 /**
2 * String类型转换成date类型3 * strTime: 要转换的string类型的时间,4 * formatType: 要转换的格式yyyy-MM-dd HH:mm:ss5 * //yyyy年MM月dd日 HH时mm分ss秒,6 * strTime的时间格式必须要与formatType的时间格式相同7 */
8 public staticDate stringToDate(String strTime, String formatType){9 KLog.d("进入stringToDate");10 try{11 SimpleDateFormat formatter = newSimpleDateFormat(formatType);12 Date date = null;13 date =formatter.parse(strTime);14 returndate;15 }catch(Exception e){16 return null;17 }18 }19 /**
20 * String类型转换为long类型21 * .............................22 * strTime为要转换的String类型时间23 * formatType时间格式24 * formatType格式为yyyy-MM-dd HH:mm:ss//yyyy年MM月dd日 HH时mm分ss秒25 * strTime的时间格式和formatType的时间格式必须相同26 */
27 public static longstringToLong (String strTime,String formatType){28 KLog.d("进入stringToLong");29 try{30 //String类型转换为date类型
31 Date date =stringToDate(strTime, formatType);32 Log.d(TAG,"调用stringToDate()获得的date:" +date);33 if (date == null) {34 return 0;35 }else{36 //date类型转成long类型
37 long Hour =date.getHours();38 long Min =date.getMinutes();39 long TimeLong = Hour*60*60*1000 + Min*60*1000;40 Log.d(TAG,"stringToLong()获得的Hour:" + Hour + " h");41 Log.d(TAG,"stringToLong()获得的Min:" + Min + " min");42 Log.d(TAG,"stringToLong()获得的TimeLong:" + TimeLong + " ms");43 returnTimeLong;44 }45 }catch(Exception e){46 return 0;47 }48 }
Java Date、String、Long三种日期类型之间的相互转换
成功获得睡眠时间(SLEEP_TIME)和起床时间(GET_UP_TIME)(单位ms)之后,计算锁屏时间IntervalTime(睡眠时间至起床时间):
1 //计算时间间隔
2 if (GET_UP_TIME >=SLEEP_TIME){3 IntervalTime = GET_UP_TIME -SLEEP_TIME;4 }else{5 IntervalTime = 24*60*60*1000 + GET_UP_TIME -SLEEP_TIME;6 }
(3)定义跳转Activity的操作:PendingIntent pi
我们的目的是利用AlarmManager的set()方法让闹钟在我们指定的时间点执行我们自定义的intent操作。这里时间点的设置非常重要,若时间设置的不精确(一般精确到秒即可,以下代码中精确至ms),将会导致闹钟执行intent有延迟。(SLEEP_TIME_HOUR和SLEEP_TIME_MIN分布是睡眠时间的小时数和分钟数)
1 //设置当前的时间
2 Calendar calendar =Calendar.getInstance();3 calendar.setTimeInMillis(System.currentTimeMillis());4 //根据用户选择的时间来设置Calender对象(即:睡觉时间)
5 calendar.set(Calendar.HOUR_OF_DAY, (int)SLEEP_TIME_HOUR);6 calendar.set(Calendar.MINUTE, (int) SLEEP_TIME_MIN);7 calendar.set(Calendar.SECOND, 0);8 calendar.set(Calendar.MILLISECOND,0);9 //设置当前时区(若时区不对,闹钟将有偏差)
10 TimeZone timeZone = TimeZone.getDefault();//获取系统时间时区
11 KLog.d("当前设置的时区为: " +timeZone);12 calendar.setTimeZone(timeZone);13 KLog.d("睡觉时间:" + SLEEP_TIME + "ms, 起床时间:" + GET_UP_TIME + "ms.");14 KLog.d("夜间休息时长:IntervalTime = " + IntervalTime + "ms.");
定义intent操作:
1 //定义用于跳转到 LockScreenActivity.class 中的Intent对象intent
2 Intent intent = new Intent(RobotClientMainActivity.this, LockScreenActivity.class);3 intent.putExtra("INTERVAL", IntervalTime);
putExtra("INTERVAL", IntervalTime); "INTERVAL"为关键字,IntervalTime为传入值(此处指睡眠时锁屏的时间ms)。带值跳转至LockScreenActivity.class中,LockScreenActivity执行相应的锁屏操作。
初始化闹钟的执行操作pi:
1 //初始化闹钟的执行操作pi
2 pi = PendingIntent.getActivity(RobotClientMainActivity.this,0
,intent,PendingIntent.FLAG_UPDATE_CURRENT);
方法:PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags);
第一个参数是上下文context;
第二个参数是请求码,用于标识此PendingIntent的对象,相当于关键字;
第三个参数是意图,用于跳转Activity;
第四个参数代表了PendingIntent的四种不同的状态,可用理解为状态标识符。四种状态如下:
①FLAG_CANCEL_CURRENT:
如果当前系统中已经存在一个相同的PendingIntent对象,则已有的PendingIntent将会取消,然后重新生成一个PendingIntent对象。
②FLAG_NO_CREATE:
如果当前系统中不存在相同的PendingIntent对象,系统将不会创建该PendingIntent对象,而是直接返回null。
③FLAG_ONE_SHOT:
该PendingIntent只作用一次。在该PendingIntent对象通过send()方法触发过后,PendingIntent将自动调用cancel()进行销毁,如果你再调用send()方法,系统将会返回一个SendIntentException。
④FLAG_UPDATE_CURRENT:
如果系统中有一个和你描述的PendingIntent对等的PendingIntent,那么系统将使用该PendingIntent对象,但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据,例如更新Intent中的Extras。
(4)设置alarmManager:
1 //定义AlarmManager对象
2 private AlarmManager alarmManager;
1 //初始化alarmManager
2 alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
1 /**
2 * 设置AlarmManager在Calendar对应的时间启动Activity3 * 当到达睡觉时间时跳转至LockScreenActivity执行锁屏操作4 */
5 alarmManager.setExact(AlarmManager.RTC,calendar.getTimeInMillis(),pi);6 KLog.d("从calender中读取到的睡眠时间:" +calendar.getTime()7 + "/n 毫秒:"+calendar.getTimeInMillis());
在此处,系统已经能够在指定的时间跳转至锁屏操作。但是实践中出现的问题是:只要系统时间已经超过指定时间,关机重启时会自动跳入锁屏操作——为什么???。。。:( 。。。求大神指导
********************************************************************************************************************************************************************************************************************************************************************************
虽然没有弄清alarmManager.setExact的机制;但是利用其在实践中的表现(指过了锁屏时间重启后仍会锁屏),在关键时间点加入if/else的判断,成功实现了功能。
相关条件判断如下:
定义和初始化部分:
1 //定义睡觉和起床时间单位ms
2 longSLEEP_TIME,GET_UP_TIME;3 //睡觉和起床时间对应的小时数和分钟数
4 longSLEEP_TIME_HOUR,SLEEP_TIME_MIN;5 longGET_UP_TIME_HOUR,GET_UP_TIME_MIN;6 //定义睡觉时间和起床时间之间的时间间隔
7 longIntervalTime;8 //定义系统当前时间(单位ms)
9 long CurrentTime_ms;
1 //设置当前的时间
2 Calendar calendar =Calendar.getInstance();3 calendar.setTimeInMillis(System.currentTimeMillis());4 KLog.d("111系统当前时间为:" +calendar.getTime());5 KLog.d("系统当前时间Hour:" +calendar.get(Calendar.HOUR_OF_DAY));6 KLog.d("系统当前时间Min:" +calendar.get(Calendar.MINUTE));7 KLog.d("系统当前时间Second:" +calendar.get(Calendar.SECOND));8 CurrentTime_ms = calendar.get(Calendar.HOUR_OF_DAY)*60*60*1000
9 +calendar.get(Calendar.MINUTE)*60*1000+calendar.get(Calendar.SECOND)*1000;
条件判断:
1 /**
2 * 计算夜间休息时长3 * 如果当前时间没到睡眠时间,则休息时长定为睡眠时间至起床时间4 * 若果当前时间在睡眠时间和起床时间之间,则休息时长定为当前时间至起床时间5 */
6 if (GET_UP_TIME >=SLEEP_TIME) {7 if ((CurrentTime_ms >= SLEEP_TIME) && (CurrentTime_ms <=GET_UP_TIME)) {8 IntervalTime = GET_UP_TIME -CurrentTime_ms;9
10 }else{11 IntervalTime = GET_UP_TIME -SLEEP_TIME;12 }13 }else{14 if ((CurrentTime_ms <= SLEEP_TIME) && (CurrentTime_ms >=GET_UP_TIME)) {15 IntervalTime = 24*60*60*1000 + GET_UP_TIME -SLEEP_TIME;16 }else{17 if(CurrentTime_ms <=GET_UP_TIME) {18 IntervalTime = GET_UP_TIME -CurrentTime_ms;19 }else{20 IntervalTime = 24*60*60*1000 + GET_UP_TIME -CurrentTime_ms;21 }22 }23 }24 KLog.d("夜间休息时长:IntervalTime = " + IntervalTime + "ms.");
1 /**
2 * 设置AlarmManager在Calendar对应的时间启动Activity3 * 当到达睡觉时间时跳转至LockScreenActivity执行锁屏操作4 * 若系统当前时间已经不属于夜间休息时间,加入判断使程序不再调用alarmManager5 */
6 if (GET_UP_TIME >=SLEEP_TIME) {7 if (CurrentTime_ms
实现功能:在指定时间范围内对APP锁屏,在锁屏时间内,重启APP仍可锁屏,不会因重启而终止整个锁屏活动。
小结:查阅了N多资料,终于实现了这一功能(*^▽^*),虽然还有许多不懂的地方,但是我会继续努力的。
最后,大神们给给意见撒。。。