当前位置: 首页 > news >正文

Android 周期任务

AlarmManager使用

1.创建意图

// 创建意图,启动MonthlyTaskServiceIntent intent = new Intent(getContext(), TimeTaskService.class);
// 传递数据intent.putExtra(TimeTaskService.KEY_TITLE,userRemind.getTitle());intent.putExtra(TimeTaskService.KEY_DEC,userRemind.getDescription());

TimeTaskService.class 是任务执行的具体内容。是一个服务

public class TimeTaskService extends Service {public static final String KEY_TITLE = "key_title";public static final String KEY_DEC = "key_dsc";public TimeTaskService() {}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// 执行任务逻辑LogUtil.i("shawn", "onStartCommand 任务执行");String string = intent.getStringExtra(KEY_TITLE);String dec = intent.getStringExtra(KEY_DEC);// 任务完成后,停止服务stopSelf();return START_NOT_STICKY;}@Overridepublic IBinder onBind(Intent intent) {return null;}
}

创建通知

private void showNotification(String title, String description) {if (StringUtils.isEmpty(title) || StringUtils.isEmpty(description)) {return;}NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);// 设置通知点击事件Intent notificationIntent = new Intent(getContext(), MainActivity.class);notificationIntent.putExtra(NotificationConstants.NOTIFICATION_KEY, NotificationConstants.NOTIFICATION_VALUE);PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);Notification.Builder notificationBuilder;// 创建通知渠道if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {NotificationChannel channel = new NotificationChannel(NotificationConstants.NOTIFICATION_CHANNEL_ID, NotificationConstants.NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);channel.setDescription(NotificationConstants.NOTIFICATION_CHANNEL_DESC);notificationManager.createNotificationChannel(channel);// 构建通知notificationBuilder = (new Notification.Builder(getContext(), NotificationConstants.NOTIFICATION_CHANNEL_ID))
//                    .setLargeIcon(BitmapFactory.decodeResource(this.getResources(), R.drawable.app_icon)).setSmallIcon(R.drawable.app_icon).setContentTitle(title).setContentText(description).setContentIntent(pendingIntent).setAutoCancel(true);// 设置点击通知后自动取消通知// 启动前台服务startForeground(NotificationConstants.FOREGROUND_ID, notificationBuilder.build());} else {// 构建通知notificationBuilder = new Notification.Builder(getContext())
//                    .setLargeIcon(BitmapFactory.decodeResource(this.getResources(), R.drawable.app_icon)).setSmallIcon(R.drawable.app_icon).setContentTitle(title).setContentText(description).setContentIntent(pendingIntent).setPriority(Notification.PRIORITY_DEFAULT).setAutoCancel(true);// 设置点击通知后自动取消通知}// 发送通知notificationManager.notify(NotificationConstants.NOTIFICATION_ID, notificationBuilder.build());}

注意:在android 8.0以上 启动服务时,要启动前台通知。告知用户。否则会崩溃

2.创建PendingIntent

PendingIntent pendingIntent;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {pendingIntent = PendingIntent.getForegroundService(getContext(),(int) requestCode,intent,PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);} else {pendingIntent = PendingIntent.getService(getContext(),(int) requestCode,intent,PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);}

注意:在使用场景中,经过测试发现。如果把进程杀掉,则任务不执行。所以,在上面的代码中,判断当前版本,大于等于 android 26时,使用PendingIntent.getForegroundService 启动前台服务的方式获取pendingIntent 。经测试,就算杀掉进程,任务也可以执行。

3.启动任务

闹钟触发方式

// 注意:在实际应用中,你可能需要根据实际需求选择合适的触发方式,// 例如使用RTC_WAKEUP替代RTC,确保在设备休眠时也能唤醒系统执行任务// 闹钟类型// ELAPSED_REALTIME - 基于自设备启动以来所经过的时间触发待定 intent,但不会唤醒设备。经过的时间包括设备处于休眠状态期间的任何时间。// ELAPSED_REALTIME_WAKEUP - 唤醒设备,并在自设备启动以来特定时间过去之后触发待定 Intent。// RTC - 在指定的时间触发待定 Intent,但不会唤醒设备。// RTC_WAKEUP - 唤醒设备以在指定的时间触发待定 Intent。

执行1次性任务

// 获取AlarmManager实例AlarmManager alarmManager = (AlarmManager) getApplication().getSystemService(Context.ALARM_SERVICE);if (repetitionType == MyConstants.REPEAT_NO) {if (alarmManager != null && pendingIntent != null) {// 设置一次性闹钟LogUtil.i("shawn", "设置一次性闹钟");
//                alarmManager.set(
//                        AlarmManager.RTC_WAKEUP,
//                        triggerAtMillis,
//                        pendingIntent
//                );
// 设置精确闹钟
// 设置精确重复闹钟//低电耗模式和应用待机模式的影响//为了延长设备的电池续航时间,我们在 Android 6.0(API 级别 23)中引入了低电耗模式和应用待机模式。// 当设备处于低电耗模式时,所有标准闹钟都会推迟,直到设备退出低电耗模式或维护期开始。// 如果必须让某个闹钟在低电耗模式下也能触发,// 可以使用 setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle()。// 您的应用将在处于空闲状态时(即用户在一段时间内未使用应用,并且应用没有前台进程时)进入应用待机模式。// 当应用处于应用待机模式时,闹钟会像设备处于低电耗模式一样被延迟。// 当应用不再处于空闲状态或者当设备接通电源时,该限制便会解除alarmManager.setExact(AlarmManager.RTC_WAKEUP,triggerAtMillis,pendingIntent);}return;}

上面代码有2种任务执行类型,alarmManager.set 设置的不精确闹钟,setExact设置的是精确闹钟,如果对任务的执行时间没有严格的要求,建议使用set方法,对设备的电量友好。

triggerAtMillis:任务执行的时间

设置重复闹钟

if (alarmManager != null && pendingIntent != null) {// 设置重复闹钟alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,triggerAtMillis,intervalMillis,pendingIntent);}

参数解释:

AlarmManager.RTC_WAKEUP:闹钟触发方式
triggerAtMillis:执行时间
intervalMillis:间隔时间
pendingIntent:任务执行内容

4.任务取消

Intent intent = new Intent(getContext(), TimeTaskService.class);intent.setAction("com.calendar.timeTaskService");AlarmManager alarmManager = (AlarmManager) getApplication().getSystemService(Context.ALARM_SERVICE);PendingIntent pendingIntent;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {pendingIntent = PendingIntent.getForegroundService(getContext(),(int) aLong,intent,PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);LogUtil.i("shawn","getForegroundService job");} else {pendingIntent = PendingIntent.getService(getContext(),(int) aLong,intent,PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);LogUtil.i("shawn","getService job");}if (pendingIntent != null) {LogUtil.i("shawn","cancel job");alarmManager.cancel(pendingIntent);} else {LogUtil.i("shawn","pendingIntent is null");}

5.任务查看

adb shell dumpsys alarm > abc.txt

通过使用adb命令,可以查看当前系统的所有alarm任务,然后筛选包名,查看任务

 u0a647:com.calendar.master.gp +11ms running, 1 wakeups:+11ms 1 wakes 1 alarms, last -2m15s264ms:*walarm*:com.calendar.master.gp/.ui.calendar.TimeTaskService

6.参考

关于Android中设置闹钟的相对完善的解决方案

http://www.lryc.cn/news/118897.html

相关文章:

  • 修改第三方组件默认样式
  • 【游戏客户端】制作你玩我猜Like玩法
  • 分页查询从接口到实现,统一对日期类型进行格式化处理
  • 栈和队列详解(1)
  • 苏州OV泛域名RSA加密算法https
  • 凯迪正大—微机继电保护校验仪
  • Linux文件属性与权限管理(可读、可写、可执行)
  • Centos7.9安装lrzsz进行文件传输---Linux工作笔记059
  • 酒吧座位全解析 小白必看
  • DAY19
  • Data analysis|Tableau基本介绍及可实现功能
  • 单元测试优化:为什么要对程序进行测试?测试有什么好处?
  • 自动装配在Spring Boot中的重要性及实现方式
  • 校对软件在司法系统中的应用:加强刑事文书审查
  • 微信小程序上传图片和文件
  • 拥抱AIGC浪潮,亚信科技将如何把握时代新增量?
  • 【opencv】指定宽或高按比例缩放图片 拼接图片
  • 使用C#加载TOOLBLOCK
  • MPAS-A原理及陆面模式的基本概念
  • 前端技术Html,Css,JavaScript,Vue3
  • 实战项目——多功能电子时钟
  • 【es6】对象解构赋值
  • 腾讯云服务器CVM标准型S6详细介绍_性能测评
  • 时间序列预测任务下探索深度学习参数对模型预测性能的影响
  • React Dva项目 简单引入models中的所有JS文件
  • ROS入门-第 1 章 ROS概述与环境搭建
  • spring之AOP简单介绍
  • 使用Spark ALS模型 + Faiss向量检索实现用户扩量实例
  • Jmeter入门之digest函数 jmeter字符串连接与登录串加密应用
  • uni-app实现图片上传功能