先来一发简单的Demo体验一下:

1、AndroidManifest.xml注册Service服务。

<serviceandroid:name=".pendingintent.AlarmService"android:exported="false" />

2、利用AlarmManager 3秒后发送Intent

public void alarm() {AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);Intent intent = new Intent(this, AlarmService.class);intent.setAction(ACTION_ALARM);PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);if (Build.VERSION.SDK_INT < 19) {am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 3000, pendingIntent);} else {am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 3000, pendingIntent);}
}

3、Service代码

public class AlarmService extends Service {private Handler mHanler = new Handler(Looper.getMainLooper());@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {mHanler.post(new Runnable() {@Overridepublic void run() {Toast.makeText(AlarmService.this, "闹钟来啦", Toast.LENGTH_SHORT).show();}});return super.onStartCommand(intent, flags, startId);}
}

具体见Demo:https://github.com/suyimin/Demos

AlarmManager的常用API

set(int type, long triggerAtMillis, PendingIntent operation)

该方法用于设置一次性闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟执行时间,第三个参数表示闹钟响应动作。

setRepeating(int type, long triggerAtMillis,long intervalMillis, PendingIntent operation)

该方法用于设置重复闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟首次执行时间,

第三个参数表示闹钟两次执行的间隔时间,第四个参数表示闹钟响应动作。

setInexactRepeating(int type, long triggerAtMillis,long intervalMillis, PendingIntent operation)

该方法也用于设置重复闹钟,与第二个方法相似,不过闹钟时间不精确。

setExact(int type, long triggerAtMillis, PendingIntent operation)

setWindow(int type, long windowStartMillis, long windowLengthMillis,PendingIntent operation)

SDK_INT 19以后为了节能省电(减少系统唤醒和电池使用),使用Alarm.set()和Alarm.setRepeating()已经不能保证精确性,

不过还好Google又提供了两个精确的Alarm方法setWindow()和setExact(),所以19以后需要精确的闹钟就需要上面两个方法。

cancel(PendingIntent operation)

取消Intent相同的闹钟,这里是根据Intent中filterEquals(Intent other)方法来判断是否相同。

public boolean filterEquals(Intent other) {if (other == null) {return false;}if (!Objects.equals(this.mAction, other.mAction)) return false;if (!Objects.equals(this.mData, other.mData)) return false;if (!Objects.equals(this.mType, other.mType)) return false;if (!Objects.equals(this.mPackage, other.mPackage)) return false;if (!Objects.equals(this.mComponent, other.mComponent)) return false;if (!Objects.equals(this.mCategories, other.mCategories)) return false;return true;}

从方法体可以看出mAction、mData、mType、mPackage、mComponent、mCategories这几个完全一样就认定为同一Intent。

闹钟类型

这个闹钟类型就是前面setxxx()方法第一个参数int type.

  • AlarmManager.ELAPSED_REALTIME:使用相对时间,可以通过SystemClock.elapsedRealtime() 获取(从开机到现在的毫秒数,包括手机的睡眠时间),设备休眠时并不会唤醒设备。
  • AlarmManager.ELAPSED_REALTIME_WAKEUP:与ELAPSED_REALTIME基本功能一样,只是会在设备休眠时唤醒设备。
  • AlarmManager.RTC:使用绝对时间,可以通过 System.currentTimeMillis()获取,设备休眠时并不会唤醒设备。
  • AlarmManager.RTC_WAKEUP: 与RTC基本功能一样,只是会在设备休眠时唤醒设备。

具体年月日启动闹钟

Calendar calendar = Calendar.getInstance();calendar.set(Calendar.YEAR,2016);calendar.set(Calendar.MONTH,Calendar.DECEMBER);calendar.set(Calendar.DAY_OF_MONTH,16);calendar.set(Calendar.HOUR_OF_DAY,11);calendar.set(Calendar.MINUTE,50);calendar.set(Calendar.SECOND,0);//设定时间为 2016年12月16日11点50分0秒AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);Intent intent = new Intent(this, AlarmService.class);intent.setAction(AlarmService.ACTION_ALARM);PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);if(Build.VERSION.SDK_INT < 19){am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);}else{am.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);}

AlarmManager闹钟不准原因

前面介绍的所有的set方法其实都是调用内部的一个private的方法setImpl(),只是不同的set方法传入的值不同而已。

private void setImpl(int type, long triggerAtMillis, long windowMillis, long intervalMillis,int flags, PendingIntent operation, final OnAlarmListener listener, String listenerTag,Handler targetHandler, WorkSource workSource, AlarmClockInfo alarmClock) {if (triggerAtMillis < 0) {/* NOTYETif (mAlwaysExact) {// Fatal error for KLP+ apps to use negative trigger timesthrow new IllegalArgumentException("Invalid alarm trigger time "+ triggerAtMillis);}*/triggerAtMillis = 0;}......try {mService.set(mPackageName, type, triggerAtMillis, windowMillis, intervalMillis, flags,operation, recipientWrapper, listenerTag, workSource, alarmClock);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}}

这里只展示了相关代码,而具体控是否精确是靠windowMillis这个参数

再看看普通的set()与setRepeating()方法如何传递windowMillis参数

public void set(int type, long triggerAtMillis, PendingIntent operation) {setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, operation, null, null,null, null, null);}public void setRepeating(int type, long triggerAtMillis,long intervalMillis, PendingIntent operation) {setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, 0, operation,null, null, null, null, null);
}

可以发现windowMillis参数为legacyExactLength()方法返回值的,那么我们接着在看legacyExactLength方法

可以看出mAlwaysExact这个变量控制着该方法的返回值,如果是小于API19的版本会使用

WINDOW_EXACT参数,这个参数是0(意思就是区间设置为0,那么就会按照triggerAtMillis这个时间准时触发,也就是精准触发)另一个参数WINDOW_HEURISTIC的值是-1,这个值具体的用法就要看AlarmManagerService具体的实现了,反正只要知道这个值是不精准就可以。而setExact()这个值为WINDOW_EXACT,setWindow()的话这个值你可以自己传所以19以后他们是精准的。

相关知识


本篇blog只以getService()方式举了栗子,还可通过getBroadCast()发送广播或getActivity()启动Activity来执行某项固定任务。其中各方法的最后一个参数含有以下常量分别代表不同含义的任务执行效果:

  • 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对等的PendingInent,那么系统将使用该PendingIntent对象,但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据,例如更新Intent中的Extras。

总结


AlarmManager非常适合Android中定时任务.并且因为他具有唤醒CPU的功能,可以保证每次需要执行特定任务时CPU都能正常工作, 
或者说当CPU处于休眠时注册的闹钟会被保留(可以唤醒CPU)。

AlarmManager介绍相关推荐

  1. Android闹钟 AlarmManager的使用

    转自:http://www.cnblogs.com/mengdd/p/3819806.html AlarmManager介绍 AlarmManager这个类提供对系统闹钟服务的访问接口. 你可以为你的 ...

  2. Android中AlarmManager的使用

    本篇博客的部分内容参考了:https://www.cnblogs.com/ProtectedDream/p/6351447.html 最近在写一个 "抢订羽毛球场地" 的 app, ...

  3. android 设备关机后还能在设定的闹钟时刻响起的功能如何实现,Android闹钟 AlarmManager的使用...

    Android闹钟 AlarmManager的使用 AlarmManager介绍 AlarmManager这个类提供对系统闹钟服务的访问接口. 你可以为你的应用设定一个在未来某个时间唤醒的功能. 当闹 ...

  4. AlarmManager系统闹钟

    AlarmManager介绍 AlarmManager这个类提供对系统闹钟服务的访问接口.你可以为你的应用设定一个在未来某个时间唤醒的功能.当闹钟响起,实际上是系统发出了为这个闹钟注册的广播,会自动开 ...

  5. Android AlarmManager闹钟的使用

    AlarmManager介绍 AlarmManager这个类提供对系统闹钟服务的访问接口. 你可以为你的应用设定一个在未来某个时间唤醒的功能. 当闹钟响起,实际上是系统发出了为这个闹钟注册的广播,会自 ...

  6. python人像绘制_python 绘制三国人物关系图

    author:weizhendong data:2019.12.19 func:绘制三国演义人物关系图 """ import codecs import jieba.po ...

  7. Android Jetpack组件之WorkManger使用介绍

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  8. AlarmManager深入浅出

    原文链接:侯 亮,https://my.oschina.net/youranhongcha/blog/149564 1.概述 在Android系统中,闹钟和唤醒功能都是由Alarm Manager S ...

  9. Android7.0 Doze模式分析(一)Doze介绍 amp; DeviceIdleController

     參考:http://blog.csdn.net/gaugamela/article/details/52981984 在Android M中,Google就引入了Doze模式.它定义了一种全新的 ...

最新文章

  1. 在项目中引入领域驱动设计的经验
  2. android toolchain maintain team
  3. 2021年,戴尔的显示器竟然出现了弹出式摄像头
  4. windows7 nginx php mysql_windows7配置Nginx+php+mysql的详细教程
  5. python 内置方法 BUILT-IN METHODS
  6. 随机数的生成 java
  7. 阿里巴巴开源项目汇总-(JAVA)
  8. oracle秒级查询,oracle 中查询超过10秒以上的sql语句(性能优化)
  9. LINUX SHELL中大小写转换及注意事项
  10. 清华大学计算机系高考选科要求,清华大学新高考选课要求-清华大学新高考选考科目...
  11. 输出阻抗与输入阻抗详解
  12. Windows10彻底关闭安全中心
  13. 不用电脑怎么设置路由器
  14. 《伯克毕生发展心理学3》
  15. 零基础做油管搬运二创项目的正确方式,短视频小白玩家套利的可能
  16. 谷歌浏览器(Google Chrome)官方下载
  17. 康耐视visionpro工具-数据分析CogDataAnalysisTool
  18. 数字转字母python_将一串数字转换成字母python
  19. 英特尔12代酷睿架构,十二代酷睿架构
  20. cmake交叉编译时链接到x86库的问题

热门文章

  1. 如何在前端完美控制浏览器兼容性问题
  2. 离散数学班委成员选举,王小红,李强,丁金生,python实现
  3. html meter做个C盘,HTML基础教程:meter标签详细讲解
  4. Error opening session. Cause: java.lang.NullPointerException
  5. 10个不大为人知的网站
  6. 网闸——(好)物理隔离网闸——入门篇
  7. VMware Workstation 无法恢复错误: (vcpu-0) Exception 0xc0000005 (access violation) has occurred.
  8. Vue3 + Photo-sphere-viewer 全景
  9. Spring学习笔记(一):初识IOC和DI
  10. 鸟哥的Linux私房菜-基础学习篇(第四版):鸟哥-电子书