AlarmManager这个类提供对系统闹钟服务的访问接口。html
你能够为你的应用设定一个在将来某个时间唤醒的功能。java
当闹钟响起,其实是系统发出了为这个闹钟注册的广播,会自动开启目标应用。android
注册的闹钟在设备睡眠的时候仍然会保留,能够选择性地设置是否唤醒设备,可是当设备关机和重启后,闹钟将会被清除。git
在alarm的receiver的onReceive()方法被执行的时候,Alarm Manager持有一个CPU唤醒锁,这样就保证了设备在处理完广播以前不会sleep。api
一旦onReceive()方法返回,Alarm Manager就会释放这个锁,代表一些状况下可能onReceive()方法一执行完设备就会sleep。app
若是你的alarm receiver中调用了Context.startService(),那么极可能service还没起来设备就sleep了。ide
为了阻止这种状况,你的BroadcastReceiver和Service须要实现不一样的唤醒锁机制,来确保设备持续运行到service可用为止。this
注意:Alarm Manager主要是用来在特定时刻运行你的代码,即使是你的应用在那个特定时刻没有跑的状况。spa
对于常规的计时操做(ticks, timeouts, etc),使用Handler处理更加方便和有效率。操作系统
另:从API 19开始,alarm的机制都是非准确传递,操做系统将会转换闹钟,来最小化唤醒和电池使用。
有一些新的API会支持严格准确的传递,见 setWindow(int, long, long, PendingIntent)和setExact(int, long, PendingIntent)。
targetSdkVersion在API 19以前应用仍将继续使用之前的行为,全部的闹钟在要求准确传递的状况下都会准确传递。
Android Api demos中就有关于闹钟使用的Demo:
com.example.android.apis.app.AlarmController
其中设定了两种闹钟,一种是一次性的,一种是重复的。
Manifest中的声明,process属性
自定义的receiver,在manifest中声明以下:
<receiver android:name=".OneShotAlarm" android:process=":remote" /> <receiver android:name=".RepeatingAlarm" android:process=":remote" />
Demo中两个Receiver的onReceive方法中显示了各自的Toast提示,因此再也不列出。
在此讨论一下process属性,它规定了组件(activity, service, receiver等)所在的进程。
一般状况下,没有指定这个属性,一个应用全部的组件都运行在应用的默认进程中,进程的名字和应用的包名一致。
好比manifest的package="com.example.helloalarm",则默认进程名就是com.example.helloalarm。
<application>元素的process属性能够为所有的组件设置一个不一样的默认进程。
组件能够override这个默认的进程设置,这样你的应用就能够是多进程的。
若是你的process属性以一个冒号开头,进程名会在原来的进程名以后附加冒号以后的字符串做为新的进程名。当组件须要时,会自动建立这个进程。这个进程是应用私有的进程。
若是process属性以小写字母开头,将会直接以属性中的这个名字做为进程名,这是一个全局进程,这样的进程能够被多个不一样应用中的组件共享。
一次性闹钟
// When the alarm goes off, we want to broadcast an Intent to our // BroadcastReceiver. Here we make an Intent with an explicit class // name to have our own receiver (which has been published in // AndroidManifest.xml) instantiated and called, and then create an // IntentSender to have the intent executed as a broadcast. Intent intent = new Intent(AlarmController.this, OneShotAlarm.class); PendingIntent sender = PendingIntent.getBroadcast( AlarmController.this, 0, intent, 0); // We want the alarm to go off 10 seconds from now. Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.add(Calendar.SECOND, 10); // Schedule the alarm! AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
重复闹钟
闹钟设置:
// When the alarm goes off, we want to broadcast an Intent to our // BroadcastReceiver. Here we make an Intent with an explicit class // name to have our own receiver (which has been published in // AndroidManifest.xml) instantiated and called, and then create an // IntentSender to have the intent executed as a broadcast. // Note that unlike above, this IntentSender is configured to // allow itself to be sent multiple times. Intent intent = new Intent(AlarmController.this, RepeatingAlarm.class); PendingIntent sender = PendingIntent.getBroadcast( AlarmController.this, 0, intent, 0); // We want the alarm to go off 10 seconds from now. Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.add(Calendar.SECOND, 10); // Schedule the alarm! AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10 * 1000, sender);
闹钟取消:
// Create the same intent, and thus a matching IntentSender, for // the one that was scheduled. Intent intent = new Intent(AlarmController.this, RepeatingAlarm.class); PendingIntent sender = PendingIntent.getBroadcast( AlarmController.this, 0, intent, 0); // And cancel the alarm. AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); am.cancel(sender);
AlarmManager这个类提供对系统闹钟服务的访问接口。
对它的获取是经过系统服务:
Context.getSystemService(Context.ALARM_SERVICE)。
相关方法说明:
cancel(PendingIntent operation)方法将会取消Intent匹配的任何闹钟。
关于Intent的匹配,查看filterEquals(Intent other)方法的说明可知,两个Intent从intent resolution(filtering)(Intent决议或过滤)的角度来看是一致的,即认为两个Intent相等。便是说,Intent的action,data,type,class,categories是相同的,其余的数据都不在比较范围以内。
set(int type, long triggerAtMillis, PendingIntent operation)方法将会设置一个闹钟。
注意:对于计时操做,可能使用Handler更加有效率和简单。
设置闹钟的时候注意:
1.若是声明的triggerAtMillis是一个过去的时间,闹钟将会当即被触发。
2.若是已经有一个相同intent的闹钟被设置过了,那么前一个闹钟将会取消,被新设置的闹钟所代替。
注意这里说的intent相同指的都是Intent在 filterEquals(Intent)的定义下匹配。
闹钟是一个广播,接收器须要本身定义和注册,注册使用动态注册( registerReceiver(BroadcastReceiver, IntentFilter) )或者静态注册(<receiver> tag in an AndroidManifest.xml file)均可以。
setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)方法将会设置一个重复性的闹钟。
比set方法多了一个间隔参数。
type的类型是四种:
ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC, RTC_WAKEUP.
区分的是时间标准和是否在睡眠状态下唤醒设备。
具体查看官方文档吧再也不详细解释啦。
实例
好比要设置一个每晚21:30唤醒的重复闹钟:
private static final int INTERVAL = 1000 * 60 * 60 * 24;// 24h //... Intent intent = new Intent(context, RequestAlarmReceiver.class); PendingIntent sender = PendingIntent.getBroadcast(context, REQUEST_CODE, intent, PendingIntent.FLAG_CANCEL_CURRENT); // Schedule the alarm! AlarmManager am = (AlarmManager) context .getSystemService(Context.ALARM_SERVICE); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, 21); calendar.set(Calendar.MINUTE, 30); calendar.set(Calendar.SECOND, 10); calendar.set(Calendar.MILLISECOND, 0); am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), INTERVAL, sender);
AlarmManager:
http://developer.android.com/reference/android/app/AlarmManager.html
闹钟Demo解析: