一、简介
AlarmManage有一个AlarmManagerServie服务程序,该服务程序才是正真提供闹铃服务的,它主要维护应用程序注册下来的各类闹铃并适时的设置即将触发的闹铃给闹铃设备(在系统中,linux实现的设备名 为”/dev/alarm”),并且一直监听闹铃设备,一旦有闹铃触发或者是闹铃事件发生,AlarmManagerServie服务程序就会遍历闹铃列 表找到相应的注册闹铃并发出广播。该服务程序在系统启动时被系统服务程序system_service启动并初始化闹铃设备(/dev/alarm)。当 然,在JAVA层的AlarmManagerService与Linux Alarm驱动程序接口之间还有一层封装,那就是JNI。
AlarmManager将应用与服务分割开来后,使得应用程序开发者不用关心具体的服务,而是直接通过AlarmManager来使用这种服务。这也许就是客户/服务模式的好处吧。AlarmManager与 AlarmManagerServie之间是通过Binder来通信的,他们之间是多对一的关系。
二、API
// 取消已经注册的与参数匹配的闹铃
void cancel(PendingIntent operation)
//注册一个新的闹铃
void set(int type, long triggerAtTime, PendingIntent operation)
//注册一个重复类型的闹铃
void setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation)
//设置时区
void setTimeZone(String timeZone)
全局定时器的五种类型:
其中PendingIntent可以说是 Intent的进一步封装,他既包含了Intent的描述又是Intent行为的执行(这种定义也许不太严格),如果将Intent比作成一个订单的 话,PendingIntent更像是一个下订单的人,因为它既要负责将订单发出去,也要负责订单发送后的处理,比如发送成功后要准备验收订单货物,发送 失败后要重发还是取消订单等操作。开发者可以通过调用getActivity(Context, int, Intent, int),getBroadcast(Context, int, Intent, int),
getService(Context, int, Intent, int)三种不同方式来得到一个PendingIntent实例。
1.getBroadcast——通过该函数获得的PendingIntent将会 扮演一个广播的功能,就像调用 Context.sendBroadcast()函数一样。当系统通过它要发送一个intent时要采用广播的形式,并且在该intent中会包含相应的 intent接收对象,当然这个对象我们可以在创建PendingIntent的时候指定,也可以通过ACTION 和CATEGORY等描述让系统自动找到该行为处理对象。
2.getActivity——通过该函数获得的PendingIntent可以直 接启动新的activity, 就像调用 Context.startActivity(Intent)一样.不过值得注意的是要想这个新的Activity不再是当前进程存在的Activity 时。我们在intent中必须使用Intent.FLAG_ACTIVITY_NEW_TASK.
3.getService——通过该函数获得的PengdingIntent可以直接启动新的Service,就像调用Context.startService()一样。
需要注意的是:如果是通过启动服务来实现闹钟提 示的话,PendingIntent对象的获取就应该采用Pending.getService(Context c,int i,Intent intent,int j)方法;如果是通过广播来实现闹钟提示的话,PendingIntent对象的获取就应该采用 PendingIntent.getBroadcast(Context c,int i,Intent intent,int j)方法;如果是采用Activity的方式来实现闹钟提示的话,PendingIntent对象的获取就应该采用 PendingIntent.getActivity(Context c,int i,Intent intent,int j)方法。如果这三种方法错用了的话,虽然不会报错,但是看不到闹钟提示效果。
三、DEMO
先看下效果图:
我们通过一个全局定时器来开启一个广播,广播接收者接收到广播后周期性显示Toast或者定时显示Toast,我们可以观察到周期性显示Toast,无论我们锁屏后打开还是关闭了app,都可以周期性的显示Toast!
最后我们来看下代码的实现:
先来看下AlarmTimer的工具类:
package com.liangdianshui.utils;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
public class AlarmTimer {
/**
* 设置周期性闹钟
*
* @param context
* @param firstTime
* @param cycTime
* @param action
* @param AlarmManagerType
* 闹钟的类型,常用的有5个值:AlarmManager.ELAPSED_REALTIME、
* AlarmManager.ELAPSED_REALTIME_WAKEUP、AlarmManager.RTC、
* AlarmManager.RTC_WAKEUP、AlarmManager.POWER_OFF_WAKEUP
*/
public static void setRepeatingAlarmTimer(Context context, long firstTime,
long cycTime, String action, int AlarmManagerType) {
Intent myIntent = new Intent();
myIntent.setAction(action);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, myIntent,
0);
AlarmManager alarm = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManagerType, firstTime, cycTime, sender);
}
/**
* 设置定时闹钟
*
* @param context
* @param firstTime
* @param cycTime
* @param action
* @param AlarmManagerType
* 闹钟的类型,常用的有5个值:AlarmManager.ELAPSED_REALTIME、
* AlarmManager.ELAPSED_REALTIME_WAKEUP、AlarmManager.RTC、
* AlarmManager.RTC_WAKEUP、AlarmManager.POWER_OFF_WAKEUP
*/
public static void setAlarmTimer(Context context, long cycTime,
String action, int AlarmManagerType) {
Intent myIntent = new Intent();
myIntent.setAction(action);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, myIntent,
0);
AlarmManager alarm = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManagerType, cycTime, sender);
}
/**
* 取消闹钟
*
* @param context
* @param action
*/
public static void cancelAlarmTimer(Context context, String action) {
Intent myIntent = new Intent();
myIntent.setAction(action);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, myIntent,
0);
AlarmManager alarm = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(sender);
}
}
然后是广播接受者,接收到广播后显示Toast
package com.liangdianshui.receiver;
import com.liangdianshui.data.GlobalValues;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class AlarmReceiver extends BroadcastReceiver {
private Toast mToast;
private Context mContext;
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
mContext = context;
if (intent.getAction().equals(GlobalValues.TIMER_ACTION_REPEATING)) {
showToast("AlarmTimer-------->Repeating");
} else if (intent.getAction().equals(GlobalValues.TIMER_ACTION)) {
showToast("AlarmTimer-------->Timer");
}
}
private void showToast(String text) {
if (mToast == null) {
mToast = Toast.makeText(mContext, text, Toast.LENGTH_SHORT);
} else {
mToast.setText(text);
}
mToast.show();
}
}
主界面是四个Button,分别用来启动全局定时器和关闭取消全局定时器
package com.liangdianshui.alarmmanager;
import com.liangdianshui.data.GlobalValues;
import com.liangdianshui.utils.AlarmTimer;
import android.app.Activity;
import android.app.AlarmManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
private Button mBtSetRepeatingAlarmTimer;
private Button mBtSetAlarmTimer;
private Button mBtCancelAlarmTimer;
private Button mBtCancelRepeatingAlarmTimer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
// TODO Auto-generated method stub
mBtSetRepeatingAlarmTimer = (Button) findViewById(R.id.bt_setRepeatingAlarmTimer);
mBtSetAlarmTimer = (Button) findViewById(R.id.bt_setAlarmTimer);
mBtCancelAlarmTimer = (Button) findViewById(R.id.bt_cancelAlarmTimer);
mBtCancelRepeatingAlarmTimer = (Button) findViewById(R.id.bt_cancelRepeatingAlarmTimer);
mBtSetRepeatingAlarmTimer.setOnClickListener(this);
mBtSetAlarmTimer.setOnClickListener(this);
mBtCancelAlarmTimer.setOnClickListener(this);
mBtCancelRepeatingAlarmTimer.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.bt_setRepeatingAlarmTimer:
AlarmTimer.setRepeatingAlarmTimer(MainActivity.this,
System.currentTimeMillis(), 3 * 1000,
GlobalValues.TIMER_ACTION_REPEATING,
AlarmManager.RTC_WAKEUP);
break;
case R.id.bt_setAlarmTimer:
AlarmTimer.setAlarmTimer(MainActivity.this,
System.currentTimeMillis() + 3 * 1000,
GlobalValues.TIMER_ACTION, AlarmManager.RTC_WAKEUP);
break;
case R.id.bt_cancelRepeatingAlarmTimer:
AlarmTimer.cancelAlarmTimer(MainActivity.this,
GlobalValues.TIMER_ACTION_REPEATING);
break;
case R.id.bt_cancelAlarmTimer:
AlarmTimer.cancelAlarmTimer(MainActivity.this,
GlobalValues.TIMER_ACTION);
break;
}
}
}
最后只是一个全局的数据类:
package com.liangdianshui.data;
public class GlobalValues {
// 周期性的闹钟
public final static String TIMER_ACTION_REPEATING = "com.liangdianshui.TIMER_ACTION_REPEATING";
// 定时闹钟
public final static String TIMER_ACTION = "com.liangdianshui.TIMER_ACTION";
}
Demo的下载地址:http://download.csdn.net/detail/two_water/9584146
因为电脑有加密系统,所以只要把上面的类复制到对应的java文件就可以运行了。