对应AlarmManage有一个AlarmManagerServie服务程 序,该服务程序才是正真提供闹铃服务的,它主要维护应用程序注册下来的各类闹铃并适时的设置即将触发的闹铃给闹铃设备(在系统中,linux实现的设备名 为”/dev/alarm”),并且一直监听闹铃设备,一旦有闹铃触发或者是闹铃事件发生,AlarmManagerServie服务程序就会遍历闹铃列 表找到相应的注册闹铃并发出广播。该服务程序在系统启动时被系统服务程序system_service启动并初始化闹铃设备(/dev/alarm)。当 然,在JAVA层的AlarmManagerService与Linux Alarm驱动程序接口之间还有一层封装,那就是JNI。

  AlarmManager将应用与服务分割开来后,使得应用程序开发者不用 关心具体的服务,而是直接通过AlarmManager来使用这种服务。这也许就是客户/服务模式的好处吧。AlarmManager与AlarmManagerServie之间是通过Binder来通信的,他们之间是多对一的关系。

在android系统中,AlarmManage提供了3个接口5种类型的闹铃服务。

3个接口:

 

 

Java代码
  1. // 取消已经注册的与参数匹配的闹铃
  2. void cancel(PendingIntent operation)
  3. //注册一个新的闹铃
  4. void set(int type, long triggerAtTime, PendingIntent operation)
  5. //注册一个重复类型的闹铃
  6. void setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation)
  7. //设置时区
  8. void setTimeZone(String timeZone)

5个闹铃类型

public static final int ELAPSED_REALTIME
  1. //当系统进入睡眠状态时,这种类型的闹铃不会唤醒系统。直到系统下次被唤醒才传递它,该闹铃所用的时间是相对时间,是从系统启动后开始计时的,包括睡眠时 间,可以通过调用SystemClock.elapsedRealtime()获得。系统值是3 (0x00000003)。
  2. public static final int ELAPSED_REALTIME_WAKEUP
  3. //能唤醒系统,用法同ELAPSED_REALTIME,系统值是2 (0x00000002) 。
  4. public static final int RTC
  5. //当系统进入睡眠状态时,这种类型的闹铃不会唤醒系统。直到系统下次被唤醒才传递它,该闹铃所用的时间是绝对时间,所用时间是UTC时间,可以通过调用 System.currentTimeMillis()获得。系统值是1 (0x00000001) 。
  6. public static final int RTC_WAKEUP
  7. //能唤醒系统,用法同RTC类型,系统值为 0 (0x00000000) 。
  8. Public static final int POWER_OFF_WAKEUP
  9. //能唤醒系统,它是一种关机闹铃,就是说设备在关机状态下也可以唤醒系统,所以我们把它称之为关机闹铃。使用方法同RTC类型,系统值为4(0x00000004)。

 

 

 

 1,首先实现一个BroadcastReceiver类,用于处理闹钟时间到后的事情。

AlarmReceiver.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package net.androidla.clock;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "闹钟时间到" , Toast.LENGTH_LONG).show();
}
}

2,ClockActivity.java 程序入口类。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package net.androidla.clock;
import java.util.Calendar;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.TimePickerDialog;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.TimePicker;
public class ClockActivity extends Activity {
private Button btnSet;
private Button btnCancel;
private TextView textView;
private Calendar c;
@Override
public void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.main);
btnSet = (Button) findViewById(R.id.btnSet);
btnSet.setOnClickListener(onClickListener);
btnCancel = (Button) findViewById(R.id.btnCancel);
btnCancel.setOnClickListener(onClickListener);
textView = (TextView) findViewById(R.id.lbl);
c = Calendar.getInstance();
}
private OnClickListener onClickListener = new OnClickListener() {
Intent intent;
PendingIntent pIntent;
AlarmManager am;
@Override
public void onClick(View v) {
Button btn = (Button) v;
switch (btn.getId()) {
case R.id.btnSet:
c.setTimeInMillis(System.currentTimeMillis());
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
new TimePickerDialog(ClockActivity. this , new OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
c.setTimeInMillis(System.currentTimeMillis());
c.set(Calendar.HOUR_OF_DAY, hourOfDay);
c.set(Calendar.MINUTE, minute);
c.set(Calendar.SECOND, 0 );
c.set(Calendar.MILLISECOND, 0 );
intent = new Intent(ClockActivity. this , AlarmReceiver. class );
pIntent = PendingIntent.getBroadcast(ClockActivity. this , 0 , intent, 0 );
am = (AlarmManager) getSystemService(Activity.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pIntent);
am.setRepeating(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), 10 * 1000 , pIntent);
textView.setText( "设置的闹钟时间为:" + hourOfDay + ":" + minute);
}
}, hour, minute, true ).show();
break ;
case R.id.btnCancel:
intent = new Intent(ClockActivity. this , AlarmReceiver. class );
pIntent = PendingIntent.getBroadcast(ClockActivity. this , 0 , intent, 0 );
am = (AlarmManager) getSystemService(Activity.ALARM_SERVICE);
am.cancel(pIntent);
textView.setText( "闹钟取消" );
break ;
}
}
};
}

3,在AndroidManifest.xml中声明广播接收器。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
< ? xml version = "1.0" encoding = "utf-8" ?>
< manifest xmlns:android = "http://schemas.android.com/apk/res/android"
package = "net.androidla.clock"
android:versionCode = "1"
android:versionName = "1.0" >
< uses -sdk android:minSdkVersion = "10" />
< application android:icon = "@drawable/icon" android:label = "@string/app_name" >
< activity android:name = ".ClockActivity"
android:label = "@string/app_name" >
< intent -filter>
< action android:name = "android.intent.action.MAIN" />
< category android:name = "android.intent.category.LAUNCHER" />
</ intent >
</ activity >
<!-- 声明广播接收器 -->
< receiver android:name = ".AlarmReceiver" android:process = ":remote" />
</ application >
</ manifest >
 
 
---------------------------------\\
 
 

Android---AlarmManager(全局定时器/闹钟)指定时长或以周期形式执行某项操作

AlarmManager的使用机制有的称呼为全局定时器,有的称呼为闹钟。通过对它的使用,个人觉得叫全局定时器比较合适,其实它的作用和Timer有点相似。都有两种相似的用法:(1)在指定时长后执行某项操作(2)周期性的执行某项操作

AlarmManager对象配合Intent使用,可以定时的开启一个Activity,发送一个BroadCast,或者开启一个Service.

下面的代码详细的介绍了两种定时方式的使用:

1)在指定时长后执行某项操作

代码 

      //操作:发送一个广播,广播接收后Toast提示定时操作完成

    Intent intent =new Intent(Main.this, alarmreceiver.class);
    intent.setAction("short");
    PendingIntent sender=
        PendingIntent.getBroadcast(Main.
this
, 0, intent, 0);
   
   
//
设定一个五秒后的时间

   Calendar calendar=Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.add(Calendar.SECOND, 5);
   
    AlarmManager alarm=(AlarmManager)getSystemService(ALARM_SERVICE);
    alarm.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
   
//
或者以下面方式简化

   //alarm.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+5*1000, sender);
   
    Toast.makeText(Main.
this, "
五秒后alarm开启", Toast.LENGTH_LONG).show();

//注意:receiver记得在manifest.xml注册

代码

   publicstaticclass alarmreceiverextends BroadcastReceiver{

        @Override
       
publicvoid
onReceive(Context context, Intent intent) {
           
// TODO Auto-generated method stub
           if
(intent.getAction().equals("short")){
                Toast.makeText(context, "short alarm", Toast.LENGTH_LONG).show();
            }
else
{
                Toast.makeText(context, "repeating alarm",

                     Toast.LENGTH_LONG).show();
            }
        }
    }

2)周期性的执行某项操作

代码

   Intent intent =new Intent(Main.this, alarmreceiver.class);
    intent.setAction("repeating");
    PendingIntent sender=PendingIntent
        .getBroadcast(Main.
this
, 0, intent, 0);
   

   //开始时间
   
long firstime=SystemClock.elapsedRealtime();

   AlarmManager am=(AlarmManager)getSystemService(ALARM_SERVICE);

  //5秒一个周期,不停的发送广播
   am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP
            , firstime, 5*1000, sender);

AlarmManagersetRepeating()相当于TimerSchedule(task,delay,peroid);有点差异的地方时Timer这个方法是指定延迟多长时间

以后开始周期性的执行task;

AlarmManager的取消:(其中需要注意的是取消的Intent必须与启动Intent保持绝对一致才能支持取消AlarmManager

代码

 Intent intent =new Intent(Main.this, alarmreceiver.class);
  intent.setAction("repeating");
  PendingIntent sender=PendingIntent
         .getBroadcast(Main.
this
, 0, intent, 0);
  AlarmManager alarm=(AlarmManager)getSystemService(ALARM_SERVICE);
 
alarm.cancel(sender);

-----------------------------------------------------------------------------------------------------------------------------

Alarm manager 主要管理硬件时钟。

一些与时间相关的应用,如日历,闹钟等需要使用Alarm Manager的服务。Alarm manager功能相对比较简单,相关代码位于
frameworks/base/core/jni/server/com_android_server_AlarmManagerService.cpp
frameworks/base/services/java/com/android/server/AlarmManagerService.java

一. frameworks/base/core/jni/server/com_android_server_AlarmManagerService.cpp
这部分代码直接管理硬件时钟,设备名为/dev/alarm。包括打开设备,关闭设备,设置时区,设置触发时间(timeout),以及等待时钟触发。
二. frameworks/base/services/java/com/android/server/AlarmManagerService.java
这部分封装目录一中的代码,向上提供java接口,同时与客户端(如calendar)交互,接收来自客户端的时钟设置请求,并在时钟触发时通知客户端。

Alarm是在预定的时间上触发Intent的一种独立的方法。

Alarm超出了应用程序的作用域,所以它们可以用于触发应用程序事件或动作,甚至在应用程序关闭之后。与Broadcast Receiver结合,它们可以变得尤其的强大,可以通过设置Alarm来启动应用程序或者执行动作,而应用程序不需要打开或者处于活跃状态。

举个例子,你可以使用Alarm来实现一个闹钟程序,执行正常的网络查询,或者在“非高峰”时间安排耗时或有代价的操作。

对于仅在应用程序生命周期内发生的定时操作,Handler类与Timer和Thread类的结合是一个更好的选择,它允许Android更好地控制系统资源。

Android中的Alarm在设备处于睡眠模式时仍保持活跃,它可以设置来唤醒设备;然而,所有的Alarm在设备重启时都会被取消。

Alarm的操作通过AlarmManager来处理,通过getSystemService可以获得其系统服务,如下所示:

AlarmManager alarms = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

为了创建一个新的Alarm,使用set方法并指定一个Alarm类型、触发时间和在Alarm触发时要调用的Intent。如果你设定的Alarm发生在过去,那么,它将立即触发。

这里有4种Alarm类型。你的选择将决定你在set方法中传递的时间值代表什么,是特定的时间或者是时间流逝:

❑ RTC_WAKEUP

在指定的时刻(设置Alarm的时候),唤醒设备来触发Intent。

❑ RTC

在一个显式的时间触发Intent,但不唤醒设备。

❑ ELAPSED_REALTIME

从设备启动后,如果流逝的时间达到总时间,那么触发Intent,但不唤醒设备。流逝的时间包括设备睡眠的任何时间。注意一点的是,时间流逝的计算点是自从它最后一次启动算起。

❑ ELAPSED_REALTIME_WAKEUP

从设备启动后,达到流逝的总时间后,如果需要将唤醒设备并触发Intent。

Alarm的创建过程演示如下片段所示:

int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;

long timeOrLengthofWait = 10000;

String ALARM_ACTION = “ALARM_ACTION”;

Intent intentToFire = new Intent(ALARM_ACTION);

PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intentToFire, 0);

alarms.set(alarmType, timeOrLengthofWait, pendingIntent);

当Alarm到达时,你指定的PendingIntent将被触发。设置另外一个Alarm并使用相同的PendingIntent来替代之前存在的Alarm。

取消一个Alarm,调用AlarmManager的cancel方法,传入你不再希望被触发的PendingIntent,如下面的代码所示:

alarms.cancel(pendingIntent);

接下来的代码片段中,设置了两个Alarm,随后马上取消了第一个Alarm。第一个Alarm显式地设置了在特定的时间唤醒设备并发送Intent。第二个设置为从设备启动后,流逝时间为30分钟,到达时间后如果设备在睡眠状态也不会唤醒它。

AlarmManager alarms = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

String MY_RTC_ALARM = “MY_RTC_ALARM”;

String ALARM_ACTION = “MY_ELAPSED_ALARM”;

PendingIntent rtcIntent = PendingIntent.getBroadcast(this, 0, new Intent(MY_RTC_ALARM), 1);

PendingIntent elapsedIntent = PendingIntent.getBroadcast(this, 0, new Intent(ALARM_ACTION), 1);

// Wakeup and fire intent in 5 hours.(注释可能有错)

Date t = new Date();

t.setTime(java.lang.System.currentTimeMillis() + 60*1000*5);

alarms.set(AlarmManager.RTC_WAKEUP, t.getTime(), rtcIntent);

// Fire intent in 30 mins if already awake.

alarms.set(AlarmManager.ELAPSED_REALTIME, 30*60*1000, elapsedIntent);

// Cancel the first alarm.

alarms.cancel(rtcIntent);

Logo

更多推荐