Android定时锁屏功能实现(AlarmManager定时部分)

宝剑锋从磨砺出,梅花香自苦寒来。这篇文章主要讲述Android定时锁屏功能实现(AlarmManager定时部分)相关的知识,希望能为你提供帮助。
菜鸟入坑记— — 第一篇
关键字:AlarmManager
一、AlarmManager简介:
              参考网址:https://www.jianshu.com/p/8a2ce9d02640
              参考网站:https://www.runoob.com/w3cnote/android-tutorial-alarmmanager.html
              推荐此网址:https://www.jianshu.com/p/d69a90bc44c0
              了解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); 一次性闹钟,执行时间精确,为精确闹钟
              参数解释:此部分参考网站https://www.jianshu.com/p/8a2ce9d02640
四、程序设计:
              (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:ss 5* //yyyy年MM月dd日 HH时mm分ss秒, 6* strTime的时间格式必须要与formatType的时间格式相同 7*/ 8public static Date stringToDate(String strTime, String formatType){ 9KLog.d("进入stringToDate"); 10try { 11SimpleDateFormat formatter = new SimpleDateFormat(formatType); 12Date date = null; 13date = formatter.parse(strTime); 14return date; 15}catch (Exception e){ 16return 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*/ 27public static long stringToLong (String strTime,String formatType){ 28KLog.d("进入stringToLong"); 29try{ 30//String类型转换为date类型 31Date date = stringToDate(strTime, formatType); 32Log.d(TAG,"调用stringToDate()获得的date:" + date); 33if (date == null) { 34return 0; 35}else { 36//date类型转成long类型 37long Hour = date.getHours(); 38long Min = date.getMinutes(); 39long TimeLong = Hour*60*60*1000 + Min*60*1000; 40Log.d(TAG,"stringToLong()获得的Hour:" + Hour + " h"); 41Log.d(TAG,"stringToLong()获得的Min:" + Min + " min"); 42Log.d(TAG,"stringToLong()获得的TimeLong:" + TimeLong + " ms"); 43return TimeLong; 44} 45}catch (Exception e){ 46return 0; 47} 48}

 
              java Date、String、Long三种日期类型之间的相互转换
              参考网址:http://www.blogjava.net/weishuangshuang/archive/2012/09/27/388712.html
              成功获得睡眠时间(SLEEP_TIME)和起床时间(GET_UP_TIME)(单位ms)之后,计算锁屏时间IntervalTime(睡眠时间至起床时间):
             
1//计算时间间隔 2if (GET_UP_TIME > = SLEEP_TIME){ 3IntervalTime = GET_UP_TIME - SLEEP_TIME; 4}else { 5IntervalTime = 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 2Intent intent = new Intent(RobotClientMainActivity.this, LockScreenActivity.class); 3intent.putExtra("INTERVAL", IntervalTime);

 
              putExtra("INTERVAL", IntervalTime); "INTERVAL"为关键字,IntervalTime为传入值(此处指睡眠时锁屏的时间ms)。带值跳转至LockScreenActivity.class中,LockScreenActivity执行相应的锁屏操作。
            初始化闹钟的执行操作pi:
PendingIntent.getActivity的使用:https://www.cnblogs.com/lyxin/p/5995681.html
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对象。
【Android定时锁屏功能实现(AlarmManager定时部分)】②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对象 2private AlarmManager alarmManager;

1//初始化alarmManager 2alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

1/** 2* 设置AlarmManager在Calendar对应的时间启动Activity 3* 当到达睡觉时间时跳转至LockScreenActivity执行锁屏操作 4*/ 5alarmManager.setExact(AlarmManager.RTC,calendar.getTimeInMillis(),pi); 6KLog.d("从calender中读取到的睡眠时间:" + calendar.getTime() 7+ "/n 毫秒:"+calendar.getTimeInMillis());

在此处,系统已经能够在指定的时间跳转至锁屏操作。但是实践中出现的问题是:只要系统时间已经超过指定时间,关机重启时会自动跳入锁屏操作— — 为什么???。。。:(  。。。求大神指导
 

    推荐阅读