zoukankan      html  css  js  c++  java
  • Android利用AlarmManager执行定时任务

    Android中的AlarmManager功能很强大,它是一个全局定时器,可以在指定时间或者指定周期启动其他组件(包括Activity、Service、BroadcastReceiver)。

    使用AlarmManager编程也很简单,只要按照以下步骤即可:

    1.获取AlarmManager对象;

    2.创建PendingIntent对象;

    3.设定执行任务的时间和周期。

    下面将详细介绍各个步骤:

    AlarmManager是一个系统服务,在Android应用中可以通过Context对象的getSystemService()方法来获取AlarmManager对象,如下代码所示:

    1. AlarmManager aManager=(AlarmManager)getSystemService(Service.ALARM_SERVICE);  

    获取了AlarmManager对象之后就可以调用它的方法来设置定时启动指定组件。

    常用的有如下几个方法:

    • set(int type,long triggerAtTime,PendingIntent operation):设置在triggerAtTime时间启动由operation参数指定的组件。
    • setInexactRepeating(int type,long triggerAtTime,long interval, PendingIntent operation):设置一个非精确的周期性任务。任务近似地以interval参数指定的时间间隔执行,如果果由于某些原因(如垃圾回收或其他后台活动)使得某一个任务延迟执行了,那么系统就会调整后续任务的执行时间,保证不会因为一个任务的提前或滞后而影响到所有任务的执行,这样看来,任务就没有精确地按照interval参数指定的间隔执行。
    • setRepeating(int type,long triggerAtTime,long interval,PendingIntent operation):设置一个周期性执行的定时任务,和上面的方法相比,这个方法执行的是精确的定时任务,系统会尽量保证时间间隔固定不变,如果某一个任务被延迟了,那么后续的任务也相应地被延迟。
    上面几个方法中几个参数含义如下:

    1. type 定时任务的类型,该参数可以接收如下值:

    • ELAPSED_REALTIME:表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始)。
    • ELAPSED_REALTIME_WAKEUP: 表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间。
    • RTC:表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用绝对时间(即系统时间)。当系统调用System.currentTimeMillis()方法的返回值与triggerAtTime相等时启动operation所对应的组件。
    • RTC_WAKEUP:表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用绝对时间。

    2. triggerAtTime 定时任务首次触发的时间,是一个毫秒值,该参数值的含义受type参数影响,二者具体的对应关系如下:

    type triggerAtTime

    ELAPSED_REALTIME

    ELAPSED_REALTIME_WAKEUP

    相对系统启动的时间。要获取当前时间相对系统启动的时间用SystemClock.elapsedRealtime()方法。

    例如:我想在开机一个小时后执行某个任务,那么这里的triggerAtTime的值就应该是1小时的毫秒值(360 0000 millis).

    RTC

    RTC_WAKEUP

    绝对时间,即和1970年1月1日00:00:00时间上的差值,以毫秒为单位。此时定时任务第一次触发的条件是当系统调用System.currentTimeMillis()方法的返回值与triggerAtTime相等。

    3. interval 定时任务执行的周期

    4. operation 是一个PendingIntent对象,代表闹钟需要执行的动作,如启动Activity、Service,发送广播等。

    PendingIntent是Intent的封装类,代表一个延迟执行的意图。需要注意的是,如果希望到设定的时间启动Service,则应该采用PendingIntent.getService(Context context, int requestCode, Intent intent, int flags)方法来获取PendingIntent对象;如果希望到设定的时间发送Broadcast,则PendingIntent对象的获取就应该采用PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags)方法;如果希望到设定的时间启动Activity,则PendingIntent对象的获取就应该采用PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags)方法。如果这三种方法错用了的话,虽然不会报错,但是看不到闹钟提示效果。另外,还有一个PendingIntent.getActivities(Context context, int requestCode, Intent[] intents, int flags)方法,允许传入一个Intent数组,这样就可以同时启动多个Activity。

    说了这么多,接下来就用代码来演示一下吧。

    1. package com.example.androidtest;  
    2.   
    3. import android.os.Bundle;  
    4. import android.app.Activity;  
    5. import android.app.AlarmManager;  
    6. import android.app.PendingIntent;  
    7. import android.app.Service;  
    8. import android.content.Intent;  
    9.   
    10. public class AlarmDemoActivity extends Activity {  
    11.   
    12.     @Override  
    13.     protected void onCreate(Bundle savedInstanceState) {  
    14.         super.onCreate(savedInstanceState);  
    15.         setContentView(R.layout.activity_alarm_demo);  
    16.         // 获取AlarmManager对象  
    17.         AlarmManager aManager=(AlarmManager)getSystemService(Service.ALARM_SERVICE);  
    18.         Intent intent=new Intent();  
    19.         // 启动一个名为DialogActivity的Activity  
    20.         intent.setClass(this, DialogActivity.class);  
    21.         // 获取PendingIntent对象  
    22.         // requestCode 参数用来区分不同的PendingIntent对象  
    23.         // flag 参数常用的有4个值:  
    24.         //      FLAG_CANCEL_CURRENT 当需要获取的PendingIntent对象已经存在时,先取消当前的对象,再获取新的;  
    25.         //  FLAG_ONE_SHOT 获取的PendingIntent对象只能使用一次,再次使用需要重新获取  
    26.         //  FLAG_NO_CREATE 如果获取的PendingIntent对象不存在,则返回null  
    27.         //  FLAG_UPDATE_CURRENT 如果希望获取的PendingIntent对象与已经存在的PendingIntent对象相比,如果只是Intent附加的数据不      //  同,那么当前存在的PendingIntent对象不会被取消,而是重新加载新的Intent附加的数据  
    28.         PendingIntent pi=PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);  
    29.         // 设置定时任务,这里使用绝对时间,即使休眠也提醒,程序启动后过1s钟会启动新的Activity  
    30.         aManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+1000, pi);  
    31.     }  
    32. }  

    那么问题又来了,如果设定的闹钟想取消怎么办?

    很简单,AlarmManager有一个方法cancel(PendingIntent operation),需要注意的是,这里传入的PendingIntent 对象必须和前面设定闹钟时传入的PendingIntent 对象相等才行。两个PendingIntent 如何才算相等?

    the same kind of PendingIntent (same operation, same Intent action, data, categories, and components, and same flags)

    可见,要求还是挺严格的,几乎所有的东西都要一样,如果我们的程序中需要频繁地设定和取消闹钟,我们可以把这两个方法封装一下,方便使用:

    1. /** 
    2.      * 设定提醒 
    3.      * @param context 
    4.      * @param aManager 
    5.      * @param reminder 自定义的一个实体类,封装了提醒相关的东西,如提醒的编号ID,提醒的时间等 
    6.      */  
    7.     public static void setAlarm(Context context,AlarmManager aManager,Reminder reminder)  
    8.     {  
    9.           
    10.         // 注册AlarmManager的定时服务  
    11.         Intent intent=new Intent(Constants.ACITON_REMIND);// Constants.ACITON_REMIND是自定义的一个action  
    12.   
    13.         // 使用Reminder实体的ID作为PendingIntent的requestCode可以保证PendingIntent的唯一性  
    14.         PendingIntent pi=PendingIntent.getBroadcast(context, (int)reminder.getId(), intent,  
    15.                 PendingIntent.FLAG_UPDATE_CURRENT);  
    16.         // 设定的时间是Reminder实体中封装的时间  
    17.         aManager.set(AlarmManager.RTC_WAKEUP, reminder.getReminderDate().getTime(), pi);  
    18.     }  
    19.     /** 
    20.      * 取消提醒 
    21.      * @param context 
    22.      * @param aManager 
    23.      * @param reminder 
    24.      */  
    25.     public static void cancelAlarm(Context context,AlarmManager aManager,Reminder reminder)  
    26.     {  
    27.         // 取消AlarmManager的定时服务  
    28.         Intent intent=new Intent(Constants.ACITON_REMIND);// 和设定闹钟时的action要一样  
    29.   
    30.         // 这里PendingIntent的requestCode、intent和flag要和设定闹钟时一样  
    31.         PendingIntent pi=PendingIntent.getBroadcast(context, (int)reminder.getId(), intent,  
    32.                 PendingIntent.FLAG_UPDATE_CURRENT);  
    33.         aManager.cancel(pi);  
    34.     }  

    在使用AlarmManager的时候还有几点需要注意:

    1. 闹钟在关机或重启之后会失效。如果希望闹钟一直有效,先把闹钟信息存储到本地,然后开机启动一个Service,通过Service重新设定闹钟。

    2. 如果闹钟设定的时间小于当前时间,那么闹钟事件会立即触发,如果想避免这种情况,可以在设定闹钟之前先添加一个判断,判断需要设定的时间如果小于当前时间则什么也不做。

    3. 后续再发现需要注意的问题会继续补充……


    转载请指明原文出处http://blog.csdn.net/fxdaniel/article/details/41150129

  • 相关阅读:
    分布图
    针对回归训练卷积神经网络
    polyfit 多项式曲线拟合matlab
    Re-run failed tests in testng
    URI 和 URL的区别
    十分钟理解Gradle
    移动App测试实战—专项测试(转)
    adb 常用命令
    MySQL基本操作
    Java注解
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/6402351.html
Copyright © 2011-2022 走看看