Android中AlarmManager的使用

AlarmManager-系统推荐的定时任务 近期leader提了很多这样的需求:每隔几个小时拉取服务器的配置信息存在本地、每隔一段时间跟服务端校对一下本地时间、每隔一段时间上传一下本地日志等等。其实这些本质都是定时任务,隔一段时间去干xxx,那么在安卓中定时任务无非三种实现方式,Handler(CountDownTimer)、Timer、while循环、AlarmManager。(如果有遗漏还望留言告知O(∩_∩)O谢谢)前三种大家基本都用过 阅读详情

本篇博客的部分内容参考了:https://www.cnblogs.com/ProtectedDream/p/6351447.html

 

最近在写一个 “抢订羽毛球场地” 的 app,有个开抢时间的设定,抢订时需要唤醒手机,并开启目标 app 进行预订操作。

因此需要用到可以摆脱 Android Dozen 模式的 AlarmManager。

在介绍 AlarmManager 之前,先简单了解下 Calendar。

Calendar 简介

Calendar 是 JDK 提供的一个时间信息的类。

YEAR = 2018,
MONTH = 9, //0月起步,9月
WEEK_OF_YEAR = 41,
WEEK_OF_MONTH = 2,
DAY_OF_MONTH = 10, //1日起步,10日
DAY_OF_YEAR = 283,
DAY_OF_WEEK = 4, //周三,对应周日起步
DAY_OF_WEEK_IN_MONTH = 2,
AM_PM = 1,
HOUR = 5,//12小时制
HOUR_OF_DAY = 17,//24小时制
MINUTE = 35,
SECOND = 0,
MILLISECOND = 0,
ZONE_OFFSET = 28800000,
DST_OFFSET = 0

以上贴出Calendar的部分字段信息

Calendar的使用方法:

Calendar c = Calendar.getInstance();  //获取系统当前日历信息,其中包含了以上当前实时时间的字段信息

      c.set(Calendar.YEAR,2016);
      c.set(Calendar.MONTH,04); //也可以填数字,0-11,一月为0
      c.set(Calendar.DAY_OF_MONTH, 26);
      c.set(Calendar.HOUR_OF_DAY, 21);
      c.set(Calendar.MINUTE, 40);
      c.set(Calendar.SECOND, 0);
//设定时间为 2011年6月28日19点50分0秒
//c.set(2011, 05,28, 19,50, 0);

      c.get(Calendar.YEAR);
      c.get(Calendar.MONTH);
      c.set(Calendar.DAY_OF_MONTH);

以上,Calendar中分别提供了set()、get(),用于设置和获取各个字段信息。

我的 app 中使用的 AlarmManager 代码:


        AlarmManager manager = (AlarmManager) context.getSystemService(ALARM_SERVICE);//获取AlarmManager实例

        Intent intent2 = new Intent(context, TimerReceiver.class); //TimerReceiver是自己定义的一个BroadcastReceiver
        intent2.setAction("BroadcastReceiver_to_Start_Reservation");
        PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent2, 0);

        Log.w(TAG, "startAppAt: start TimerReceiver to handle");
        manager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calender.getTimeInMillis(), pi);//开启提醒

AlarmManager介绍:

AlarmManager 是 Android 中常用的一种系统级别的提示服务,在特定的时刻为我们广播一个指定的 Intent。

简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager 为我们广播一个我们设定的 Intent, 通常我们使用 PendingIntent,PendingIntent 可以理解为 Intent 的封装包,简单的说就是在Intent上在加个指定的动作。

在使用Intent的时候,我们还需要在执行 startActivity、startService 或 sendBroadcast 才能使 Intent 有用。而 PendingIntent 的话就是将这个动作包含在内了。

定义一个PendingIntent对象。


PendingIntent pi = PendingIntent.getBroadcast(this,0,intent,0);

 

AlarmManager的常用方法有三个:

(1)set(int type,long startTime,PendingIntent pi);

该方法用于设置一次性闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟执行时间,第三个参数表示闹钟响应动作。

(2)setRepeating(int type,long startTime,long intervalTime,PendingIntent pi);

该方法用于设置重复闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟首次执行时间,第三个参数表示闹钟两次执行的间隔时间,第三个参数表示闹钟响应动作。

(3)setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi);

该方法也用于设置重复闹钟,与第二个方法相似,不过其两个闹钟执行的间隔时间不是固定的而已。

 

注意: 高版本的 Android 中使用了 Dozen 模式,该模式会使以上函数的定时在生效时出现一定误差:

为此,最新版本的AlarmManager提供了setExactAndAllowWhileIdle() 函数,最大限度的保证定时操作被准时执行,即相关service,activity 或 broadcast 被准时唤起。

 

三个方法各个参数详悉:

(1)int type: 闹钟类型

常用的有5个值:

AlarmManager.ELAPSED_REALTIME

表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始),状态值为3;

AlarmManager.ELAPSED_REALTIME_WAKEUP

表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间,状态值为2;

AlarmManager.RTC

表示闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间,即当前系统时间(这个绝对时间其实是相对于1970年一月一日),状态值为1;

AlarmManager.RTC_WAKEUP

表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,状态值为0;

AlarmManager.POWER_OFF_WAKEUP

表示闹钟在手机关机状态下也能正常进行提示功能,所以是 5 个状态中用的最多的状态之一,该状态下闹钟也是用绝对时间,状态值为 4;不过本状态好像受 SDK 版本影响,某些版本并不支持;

(2)long startTime: 

闹钟的第一次执行时间,以毫秒为单位,可以自定义时间,不过一般使用当前时间。需要注意的是,本属性与第一个属性(type)密切相关

(3)long intervalTime:

对于后两个方法来说,存在本属性,表示两次闹钟执行的间隔时间,也是以毫秒为单位。

以下 AlarmManager 中的字段会用于这个参数的设置:

INTERVAL_DAY设置闹钟,间隔一天
INTERVAL_HALF_DAY设置闹钟,间隔半天
INTERVAL_FIFTEEN_MINUTES设置闹钟,间隔15分钟
INTERVAL_HALF_HOUR设置闹钟,间隔半个小时
INTERVAL_HOUR设置闹钟,间隔一个小时

(4)PendingIntent pi:

绑定了闹钟的执行动作,比如发送一个广播、给出提示等等。

PendingIntent是Intent的封装类。

需要注意的是:

如果是通过启动服务来实现闹钟提示的话,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) 方法。

如果这三种方法错用了的话,虽然不会报错,但是看不到闹钟提示效果。

注意:

1. 设置闹钟使用 AlarmManager.set() 函数。

它的 triggerAtTime 参数,如果要用 Calendar.getTimesInMillis() 获得,就必须先设置 Calendar 对象,例如要让闹钟在当天的16:30分启动,就要设置HOUR_OF_DAY(16)、MINUTE(30)、MILLISECOND(0),特别是HOUR_OF_DAY,我一开始误用了 HOUR,这是12进制计时方法,HOUR_OF_DAY 是 24 进制计时方法。

2. 针对同一个 PendingIntent,AlarmManager.set() 函数不能设置多个 alarm。

调用该函数时,假如已经有 old alarm 使用相同的PendingIntent,会先取消(cancel)old alarm,然后再设置新的 alarm。如何判断是否已经有相同的 PendingIntent,请看下条。

3. 取消 alarm 使用 AlarmManager.cancel() 函数,传入参数是个 PendingIntent 实例。

该函数会将所有跟这个 PendingIntent 相同的 Alarm 全部取消,怎么判断两者是否相同,android 使用的是 intent.filterEquals(),具体就是判断两个 PendingIntent 的 action、data、type、class 和 category 是否完全相同。

4. 在AndroidManifest.xml 中静态注册 BroadcastReceiver 时,一定使用android:process=":xxx"属性,因为SDK已注明:If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the broadcast receiver runs in that process.

 

在此讨论一下 process 属性,它规定了组件 (activity, service, receiver等)所在的进程。

  通常情况下,没有指定这个属性,一个应用所有的组件都运行在应用的默认进程中,进程的名字和应用的包名一致。

  比如 manifest 的package="com.example.helloalarm",则默认进程名就是com.example.helloalarm。

  <application>元素的 process 属性可以为全部的组件设置一个不同的默认进程。

  组件可以 override 这个默认的进程设置,这样你的应用就可以是多进程的。

 

  如果你的 process 属性以一个冒号开头,进程名会在原来的进程名之后附加冒号之后的字符串作为新的进程名。当组件需要时,会自动创建这个进程。这个进程是应用私有的进程。

  如果 process 属性以小写字母开头,将会直接以属性中的这个名字作为进程名,这是一个全局进程,这样的进程可以被多个不同应用中的组件共享。

 

针对不同版本的Android上AlarmManager机制的不同,要在不同版本上保证定时被触发的实时性,可以参考以下博客中给出的解决方案:https://www.jianshu.com/p/d69a90bc44c0

// pendingIntent 为发送广播
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), pendingIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), pendingIntent);
} else {
    alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), TIME_INTERVAL, pendingIntent);
}

private BroadcastReceiver alarmReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 重复定时任务
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + TIME_INTERVAL, pendingIntent);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + TIME_INTERVAL, pendingIntent);
        }
        // to do something
        doSomething();
    }
};

作者:俞其荣
链接:https://www.jianshu.com/p/d69a90bc44c0
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

 

 

 

 

 

 

 

 

android 定时重启设备 本文主要介绍一种定时重启设备的方案,目的是对于低内存设备,防止其由于长时间不关机且应用消耗过多RAM导致卡顿甚至无法开机的现象。基本方案是通过AlarmManager设置定时闹钟唤醒系统并且判断是否符合重启条件,从而进行弹框提醒和倒计时重启。 阅读详情

相关推荐

AlarmManager计时不准,在手机灭屏后延迟的问题

应用需要周期性的提醒用户,但是在使用alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime,delay,pendIntent) 设置周期性广播后,始终无法完美体验这一效果,搞得本书生是在是头大呀!查阅API发现对这一方法的解释为在API19后将不再准时,需要参考setWindow()或者setExac

henny1991的博客 1万+

调度重复的闹钟

闹钟的具体类型: ELAPSED_REALTIME:从设备启动之后开始算起,度过了某一段特定时间后,激活 Pending Intent,但不会唤醒设备。其中设备睡眠的时间也会包含在内。ELAPSED_REALTIME_WAKEUP:从设备启动之后开始算起,度过了某一段特定时间后唤醒设备。RTC:在某一个特定时刻激活 Pending Intent,但不会唤醒设备。RTC_WAKEUP:在某一个

mnizq的专栏 1029

Android闹钟 AlarmManager的使用

other)方法的说明可知,两个Intent从intent resolution(filtering)(Intent决议或过滤)的角度来看是一致的,即认为两个Intent相等。这个进程是应用私有的进程。通常情况下,没有指定这个属性,一个应用所有的组件都运行在应用的默认进程中,进程的名字和应用的包名一致。,将会直接以属性中的这个名字作为进程名,这是一个全局进程,这样的进程可以被多个不同应用中的组件共享。组件可以override这个默认的进程设置,这样你的应用就可以是多进程的。

2401_89224664的博客 1251

Android 使用AlarmManager实现每日定时任务触发

一、需求: 最近遇到一个需求,需要每天早上5:00触发执行一个任务,类似闹铃提醒,使用AlarmManager来实现。 二:实现 AlarmManager的基本使用大家可参考后面的文章,写的非常详细,在实现的过程中主要对闹钟的类型,及相应的triggerTime(也有starttime)设置花了点时间研究了下。 1、闹钟的类型 AlarmManager.RTC_WAKEUP 表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,即当前系统时间,状态值为0; AlarmManager

孔小乐的博客 8394

使用patchelf与独立glibc解决Cursor/VSCode远程开发环境兼容性问题

本文针对Cursor/VSCode远程开发连接Ubuntu 18.04、CentOS 7等老系统时因GLIBC版本过低导致的兼容性问题,提供了一套安全高效的解决方案。核心思路是通过编译独立的glibc-2.28环境,并利用patchelf工具修改远程服务端的node可执行文件,使其优先使用新版glibc,从而在不升级系统库、不影响系统稳定性的前提下,完美解决远程开发环境“罢工”的难题。

weixin_28835789的博客 533

避坑指南:SAP CO模块维护成本控制范围的5个常见错误及解决方法

本文深入剖析了SAP CO模块中维护成本控制范围时最易犯的5个常见错误,包括货币参数配置不当、标准层次结构缺失、财政年度变式不一致、功能激活遗漏及集成参数设置错误。重点针对事务码OKKP的配置,提供了详细的排查步骤与实战解决方案,帮助顾问有效规避陷阱,确保成本核算体系稳定运行。

stone的博客 233

android alarmmanager 收不到广播,关于安卓AlarmManager定时会失效的问题,请指点

网上查了N多资料,基本都是讲解AlarmManager要怎么用,但基本没怎么说什么情况会失效或被安卓系统杀掉。都说AlarmManager是系统级的服务,手机睡眠后都能唤醒CPU执行。但本人测试在手机不休眠时能正常功能,一旦休眠后过几个小时后不再重复定时执行。本人写了写入数据库的日志,从日志可以清晰看到定时服务确实没再执行过。下面是本人的代码,请高手指点啊!在服务的onCreate方法中启动定时发...

weixin_28809949的博客 1648

基于ESP32-S3与模块化设计的立创桌面充电站:从硬件架构到Web控制实战

本文详细介绍了基于ESP32-S3与模块化设计的立创桌面充电站项目,涵盖从硬件架构到Web控制的全流程实战。项目采用模块化设计,支持自由组合快充模块,并通过ESP32-S3实现智能监控,用户可通过本地网页实时查看各接口电压、电流与功率数据。文章重点解析了基板、连接板与充电模块三大核心部件的设计,特别是大电流PCB的“开窗贴铜”处理技巧,并提供了固件刷写与Web控制面板的配置指南。

weixin_36122351的博客 292

android alarmmanager 定时 不准确,关于安卓AlarmManager定时会失效的问题,请大神指教!...

网上查了N多资料,基本都是讲解AlarmManager要怎么用,但基本没怎么说什么情况会失效或被安卓系统杀掉。都说AlarmManager是系统级的服务,手机睡眠后都能唤醒CPU执行。但我测试在手机不休眠时能正常功能,一旦休眠后过几个小时后不再重复定时执行。我写了写入数据库的日志,从日志可以清晰看到定时服务确实没再执行过。下面是我的代码,请大神指教啊!在服务的onCreate方法中启动定时发送广播...

weixin_28676181的博客 1560

Windows安装ros2(Jazzy版本+win10/win11)-1.配置windows终端

更高版本的terminal可能设置里更加丰富, 有默认以管理员身份启动的选项等,可自行配置。打开微软应用商店, 在其中搜索并下载 Terminal 即可(注意别挂梯子)下载并安装, 安装的位置自行替换,建议别放到系统盘中。点击任务栏中的搜索, 输入store。

weixin_48398592的博客 1453

ROS 2实战:用MoveIt Task Constructor让机械臂完成抓取任务(附避坑指南)

本文详细介绍了如何在ROS 2环境中使用MoveIt Task Constructor框架,为Franka Panda机械臂构建一个完整的拾取放置任务流水线。通过分解任务阶段、配置规划器并处理实际部署中的常见问题,帮助开发者从基础运动规划升级到可靠的多步骤任务编排,并附有核心避坑指南。

vvv99的博客 505

android alarmmanager后台,Android各版本AlarmManager使用

一、长时间定时任务,比较Timer、Hnadler、AlarmManagerTimer,有一个明显的问题,它并不太适合用于需要长期在后台运行的定时任务。我们都知道,为了能让电池更加耐用,每种手机都会有自己的休眠策略,Android手机就会在长时间不操作的情况下自动让CPU进入睡眠状态,这就有可能导致Timer中的定时任务无法正常运行。Hnadler,Handler的postDelay方法也可以实现...

weixin_39674293的博客 578

HTML入门(详细教程),前端入门从这里开始

HTML基础教程,网页框架搭建,表单制作,了解HTML标签的基本用法,每个标签具备哪些属性。

wandertp的博客 1283

Android中的AlarmManager类

随时随地阅读更多技术实战干货,获取项目源码、学习资料,请关注源代码社区公众号(ydmsq666) 一、声明:public class AlarmManager extends Object 二、类结构: java.lang.Object ↳ android.app.AlarmManager ...

孤云博客 5222

手把手调试Android 14 ShellTransitions:用Log追踪ActiveTransition与Handler匹配过程

本文详细介绍了在Android 14中调试ShellTransitions机制的方法,重点通过Log追踪ActiveTransition与Handler的匹配过程。文章提供了关键日志点植入策略、Handler匹配机制解析及实战调试案例,帮助开发者解决窗口转场动画中的卡顿和错乱问题,提升系统动画性能。

weixin_42652674的博客 429

万字长文,小白新手怎么开始做YOLO实验,从零开始教!整体思路在这里,科研指南针!

万字长文,小白新手怎么开始做YOLO实验,从零开始教!整体思路在这里,科研指南针!

Coding... 1万+

Android中的AlarmManager的使用

同步自:http://www.elitor.org/?p=241 参考1:lizhanzhishang   参考2:JeetHongFei 1、AlarmManager,顾名思义,就是“提醒”,是Android中常用的一种系统级别的提示服务,在特定的时刻为我们广播一个指定的Intent。简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager为我们广播一个我们设定

elitor的专栏 7375

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Android AlarmManager闹钟实现

android 闹钟服务完全解析,教你使用系统闹钟服务

wuchuang 2478

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Android AlarmManager教程

在编写应用程序时,将来需要安排代码的执行。 您可能需要AlarmManager在指定的时间安排您的工作。 即使应用程序未运行,AlarmManager也会访问系统警报并计划代码执行。 项目信息:有关该项目的元信息。 平台版本:Android API级别10。 IDE:Eclipse Helios服务版本2 模拟器:Android 4.1 先决条件:对Android应用程序框架和In...

456

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Android AlarmManager学习

一、AlarmManager是什么 可以设置即使系统锁屏休眠之后依然可以存在。 Alarm Manager有个很好的特性就是即使在你的应用程序真正退出或手机休眠时,它仍然起作用。 Alarm Manager发出的消息通过拥有一个CPU唤醒锁,保证即使锁屏的情况下避免手机进入休眠状态,当在手机接收器的onReceive方法中处理完发送的消息后才会释放锁,手机才能进入休眠状态。

Android 2075

【转】安卓电量优化之AlarmManager使用全部解析

转自 汪磊的博客 安卓电量优化之AlarmManager使用全部解析 一、AlarmManager概述 AlarmManager是安卓系统中一种系统级别的提示服务,可以在我们设定时间或者周期性的执行一个intent,这个intent可以是启动Service服务、发送广播、跳转Activity,看到这里是不是会想这不就是定时器Timer吗,Timer确实是一般定时需求的最便捷实现方式,但是试想一下手...

skyang在路上 523

Android 中 AlarmManager的使用

AlarmManager使用 最近项目中定时提醒的功能用到了AlarmManger,在这和大家分享一下: 1.AlarmManager这个类提供对系统闹钟服务的访问接口,是android中比较常用的系统级提示服务。    使用闹钟服务,会在特定的时间为我们广播一个我们设定好的Intent,我们可以通过Intent执行startActivity,startService和sen

王广彬 800

在Android中使用AlarmManager

AlarmManager是Android中的一种系统级别的提醒服务,它会为我们在特定的时刻广播一个指定的Intent。而使用Intent的时候,我们还需要它执行一个动作,如startActivity,startService,startBroadcast,才能使Intent有用。通常我们使用PendingIntent,它可以理解为对Intent的封装,包含了指定的动作。 我们可以通过Pendin

一个码农的博客 2万+

Android AlarmManager

2.设置闹钟 //设置闹钟 Intent intent = new Intent(AlarmManagerActivity.this, AlarmActivity.class); //获取显示闹钟的PendingIntent //PendingIntent是对Intent的描述,主要用来处理即将发生的事情,这个Intent会由其他程序进行调用,这里是由闹钟调用 PendingIntent pendingIntent = PendingIntent.getActivity(AlarmManagerActivi

特立独行的博客 3271
上一篇: 数据结构与算法系列课程之二:复杂度分析(下)
下一篇: 数据结构与算法系列课程之五:链表(上)
玩火轩辕
博客等级 码龄15年 6粉丝 22原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值