Android AlarmManager  定时任务/报警管理

Android AlarmManager  定时任务/报警管理

 

官方解释:AlarmManager类提供对系统警报服务的访问。这些允许您安排应用程序在将来的某个时间运行。当警报响起时,Intent系统会广播为其注册的警报,如果目标应用程序尚未运行,则会自动启动它。设备处于休眠状态时会保留已注册的警报(如果设备在此期间关闭,则可以选择将设备唤醒),但如果设备关闭并重新启动,则会清除AlarmManager的任务。

 

通俗一点AlarmManager 系统提供的一个定时任务管理器,通过AlarmManager 提供的定时任务,可以在约定的时间发送广播,启动服务,启动Activity等等。AlarmManager是Android中常用的一种系统级别的提示服务,在特定的时刻为我们广播⼀个指定的Intent。简单的说就是我们设定⼀一个时间,然后在该时间到来时,AlarmManager为 我们广播一个我们设定的Intent广播因此我们需要实现⼀一个针对特定闹钟事件的⼴播接⼝器 (PendingIntent)。

 

特点:使用它既可以指定单次执行的定时任务,也可以指定重复运行的周期性任务;

注意:从API 19开始,AlarmManager的机制都是非准确传递,操作系统将会转换闹钟,来最小化唤醒和电池使用,所以时间可能没那么精确;AlarmManager非常适合Android中定时任务.并且因为他具有唤醒CPU的功能,可以保证每次需要执行特定任务时CPU都能正常工作, 或者说当CPU处于休眠时注册的闹钟会被保留(可以唤醒CPU),(老司机们请注意此处有弯道减速慢行)但是国内Rom众多.有的可能休眠时候无法唤醒。

 

简单的使用流程

eg1:

  
int time = 60 * 1000 * 30;//30分钟
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, RepetitionService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT < 19) {
      alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + time, pendingIntent);
} else {
     alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + time, pendingIntent);
}

这里time 表示30分钟后, 会启动intent对象设置的RepetitionService 

下面看下RepetitionService 代码:

public class RepetitionService extends IntentService {


    public static final String TAG = "RepetitionService";


    public RepetitionService() {
        super("RepetitionService");
    }


    @Override
    public void onCreate() {
        super.onCreate();

        Log.d(TAG, "onCreate");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        做一些逻辑,由于IntentService 会进行异步处理, 
        所以这里可以直接写耗时逻辑,不会占用主线程耗时,不需要再开启异步线程,
        onHandleIntent 执行完后, Service会自动销毁;
    }


    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy");
        super.onDestroy();
    }
}

当然这里启动的是一个Service ,可以换为通过Intent发送一自定义Action的广播,用法类似;

通常要使用 PendingIntent,PendingIntent可以理解为Intent的封装包,简单的说就是在Intent上在加个指定的动作。在使用Intent的时候,我们还需要在执行startActivity、startService或sendBroadcast才能使Intent有用。而PendingIntent的话就是将这个动作包含在内了。

 

 

eg2:   设定指定时间后执行任务(用Calendar来定义时间)

        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);
        }
public class AlarmService extends Service {

    public static String ACTION_ALARM = "action_alarm";
    private Handler mHanler = new Handler(Looper.getMainLooper());

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mHanler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(AlarmService.this, "闹钟来啦", Toast.LENGTH_SHORT).show();
            }
        });
        return super.onStartCommand(intent, flags, startId);
    }
}

AlarmManager的几个方法:

 设置一次性闹钟:  

           set(int type, long triggerAtMillis, PendingIntent operation)

          第一个参数表示闹钟类型
          第二个参数表示闹钟执行时间
          第三个参数表示闹钟响应动作

设置重复闹钟: SDK_19 Android4.4 之前是精确闹钟,19以后为了节约电量,减少系统唤醒和电池的使用,所以时间没有那么精确了,但是不会差太多

          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)

取消闹钟:

         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 ,才能取消, 否则认为不是同一个Intent ,就不能取消,时间到了之后还是会执行;

 

闹钟类型

  • AlarmManager.ELAPSED_REALTIME
    • 在指定的延时过后,发送广播,但不唤醒设备(闹钟在睡眠状态下不可用)。如果在系统休眠时闹钟触发,它将不会被传递,直到下一次设备唤醒。设备休眠时并不会唤醒设备;
  • AlarmManager.ELAPSED_REALTIME_WAKEUP
    • 在指定的延时过后,发送广播,并唤醒设备(即使关机也会执行operation所对应的组件)。与ELAPSED_REALTIME基本功能一样,只是会在设备休眠时唤醒设备;
  • AlarmManager.RTC
    • 使用绝对时间,可以通过 System.currentTimeMillis()获取,设备休眠时并不会唤醒设备;
  • AlarmManager.RTC_WAKEUP
    • 与RTC基本功能一样,只是会在设备休眠时唤醒设备

 

闹钟重复类型

  • AlarmManager.INTERVAL_FIFTEEN_MINUTES 间隔15分钟
  • AlarmManager.INTERVAL_HALF_HOUR 间隔半个小时
  • AlarmManager.INTERVAL_HOUR 间隔一个小时
  • AlarmManager.INTERVAL_HALF_DAY 间隔半天
  • AlarmManager.INTERVAL_DAY 间隔一天

 

设定多个定时闹钟为什么只有最后一个生效

AlarmManager 根据 PendingIntent requestCode 来判断是否是同一个定时服务,所以当requestCode相等的时候只有最后一个生效

1. 我们说的requestCode 是第二个参数

PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, @Flags int flags)

2. 例如:

PendingIntent pi1 = PendingIntent.getBroadcast(this, 1, intent, 0); 
AlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, startTime, intervalTime, pi1);  

PendingIntent pi2 = PendingIntent.getBroadcast(this, 2, intent, 0); 
AlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, startTime, intervalTime, pi2); 

这个样子就可以设定2个了

 

 

 

 

 

 

 

 

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
使用 AlarmManager 实现定时重置流量统计可以分为以下几个步骤: 1. 在 AndroidManifest.xml 文件中添加以下权限: ```xml <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> ``` 2. 创建一个 BroadcastReceiver,用于接收定时任务的触发事件,并在其中实现重置流量统计的逻辑。例如: ```java public class TrafficStatsResetReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 重置流量统计信息 TrafficStats.clearAllStats(); } } ``` 3. 在 AndroidManifest.xml 文件中注册 BroadcastReceiver,并且添加一个 ACTION_BOOT_COMPLETED 的 intent-filter,以便在设备启动时启动定时任务。例如: ```xml <receiver android:name=".TrafficStatsResetReceiver" android:enabled="true" android:exported="false"> <intent-filter> <action android:name="com.example.trafficstatsreset.ACTION_RESET_TRAFFIC_STATS" /> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> ``` 4. 在应用程序启动时注册一个定时任务,例如: ```java private void registerTrafficStatsResetTask(Context context) { // 创建一个 PendingIntent,用于触发定时任务 Intent intent = new Intent(context, TrafficStatsResetReceiver.class); intent.setAction("com.example.trafficstatsreset.ACTION_RESET_TRAFFIC_STATS"); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); // 获取 AlarmManager 实例 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); // 计算定时任务的触发时间 long triggerTime = System.currentTimeMillis() + 24 * 60 * 60 * 1000; // 每天重置一次流量统计 // 注册定时任务 alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerTime, 24 * 60 * 60 * 1000, pendingIntent); } ``` 在上述代码中,我们创建了一个 PendingIntent,并将其传递给 AlarmManager 的 setRepeating 方法,以便注册一个每天重置一次流量统计的定时任务。需要注意的是,我们设置的定时任务触发时间是当前时间加上一天的时间间隔,这样可以确保定时任务在第二天凌晨触发。 5. 在应用程序启动时调用 registerTrafficStatsResetTask 方法,注册定时任务即可: ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 注册定时任务 registerTrafficStatsResetTask(this); } ``` 经过上述步骤,您就可以使用 AlarmManager 来实现定时重置流量统计的功能了。需要注意的是,使用 AlarmManager 时需要仔细管理定时任务的触发时间和间隔,以确保应用程序的稳定性和安全性。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值