android后台执行定时任务(保活)&&使用AlarmManager的各种坑

最近有个需求,需要在android手机后台一直执行一个任务,有一定的时间间隔。
目前方案有以下几种
方式一:采用Handler的postDelayed(Runnable, long)方法

    handler = new Handler();
    runnable = new Runnable() {

        @Override
        public void run() {
            // handler自带方法实现定时器
            System.out.println("33331");
            handler.postDelayed(this, 1000*3);//每隔3s执行

        }
    };
    handler.postDelayed(runnable, 1000*60);//延时多长时间启动定时器

方式二:采用timer及TimerTask结合的方法

    TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {
            System.out.println("99999998");
        }
    };
    timer.schedu,
            1000,//延迟1秒执行
            Time);//周期时间

}

方式三:采用AlarmManager机制

  @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

          new Thread(new Runnable() {
              @Override
              public void run() {
//                  EventBus.getDefault().post(new EventCategory(7));
                  System.out.println("99999988");//这是定时所执行的任务
              }
          }).start();

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

        int anhour=6*1000;
        long triggerAtMillis = SystemClock.elapsedRealtime()+anhour;

        Intent alarmIntent = new Intent(this,MyService.class);

        PendingIntent pendingIntent = PendingIntent.getService(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        alarmManager.cancel(pendingIntent);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {// 6.0
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtMillis, pendingIntent);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//  4.4
            alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtMillis, pendingIntent);
        } else {
            alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtMillis, pendingIntent);
        }

        return super.onStartCommand(intent, flags, startId);
    }

这里一定要注意的是AlarmManager.ELAPSED_REALTIME_WAKEUP 后面这个类型
在这里插入图片描述
记住不要再用setRepeating了,这个方法过时了,设置了一点都不去精确
还有很多人容易写成RTC_WAKEUP ,但是取时间的时候却用的是SystemClock.elapsedRealtime()
SystemClock.elapsedRealtime()获取从设备boot后经历的时间值。
SystemClock.elapsedRealtime()计算某个时间经历了多长时间有意义,例如通话经历了多长时间,这个值是系统设置无关这是会导致一个不管怎么设置时间,结果都是5S执行一次的问题,请大家注意,一定要根据上面表格来。

记得注册服务
在这里插入图片描述
调用方式
在这里插入图片描述
这里推荐使用第三种方式

Timer并不太适用于那些需要长期在后台运行的定时任务。为了能让电池更加耐用,每种手机都会有自己的休眠策略,Android 手机就会在长时间不操作的情况下自动让 CPU 进入到睡眠状态,这就有可能导致 Timer 中的定时任务无法正常运行。
Alarm具有唤醒 CPU 的功能,即可以保证每次需要执行定时任务的时候 CPU 都能正常工作。

1,Alarm定时不需要程序自身去维护,而又系统来维护,使得程序更好避免了容易出错问题,更是占用系统资源,cpu占有率。

2,即使程序退出后,程序自身不会有任何烦恼的问题,系统到时间自动调用对应组件执行定义好的逻辑

3,定时的多样性,包括一次定时,循环定时(在xx年x月x日执行,周一至周五执行,每天几点几分执行。。。)

如果你的应用是TO C的话,保活请看这一篇,全网搜过写的最好的
https://www.jianshu.com/p/63aafe3c12af
如果你是TO B的,也就是面向企业的或者工具类的,可以这样子
比如我的测试手机小米5s,打开应用管理

**

找到我们的应用Testkill,设置自启动,设置之后,你的APK将做到即便是手动清理APP进程,也能在系统下自行重启,会重新调用我们上述的MyService,从而达到无敌保活状态,当然华为,以及别的手机都会有自己的这个东西,类似白名单,把你的APK加进去即可。

**

比如我们看微信的,为何能做到无敌保活状态呢,即便是杀掉的状态依然能接受新的微信消息,弹出消息提示

!
如果你把自启动给它关掉,经过验证,微信被杀也是无法接受新消息提醒的,over。

下面我们来说说使用AlarmManager的一些坑
测试手机系统Android 5.1.1
在这里插入图片描述
时间设置为2S,看看执行结果

在这里插入图片描述
小米5 Android8.0
在这里插入图片描述
设置成4S的话两个手机依然执行5s
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

验证成功 !!!

由于google对电量做了优化,5S是最小轮询单位
5S以内不管怎么设置时间,都是5S执行一次,
凡是>5S的,都是可以在5S以上时间执行的,ojbk.


Android JetPack有个组件WorkManager,也可以实现一些后台定时任务,https://www.jianshu.com/p/f07e4141d432
WorkManager用于那些需要保证即使APP退出了系统依然可以运行的任务,比如将应用数据上传到服务器。不要用于如果APP被杀进程,可以安全终止的后台任务

参考
定时任务,AlarmManager使用
https://www.cnblogs.com/ProtectedDream/p/6351447.html#4079768

  • 9
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
要在 Android 应用程序中发送定时通知提醒,你可以使用 AndroidAlarmManager 类。AlarmManager 提供了一种在 Android 设备上定时触发操作的方法,包括发送通知提醒。 以下是发送定时通知提醒的步骤: 1. 在 AndroidManifest.xml 文件中添加权限: ``` <uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> ``` 2. 在你的代码中创建一个 PendingIntent 对象来启动通知。 ``` Intent notificationIntent = new Intent(context, YourNotificationReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); ``` 3. 使用 AlarmManager 设置通知的触发时间和重复间隔。 ``` AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent); ``` 这里的 interval 是通知重复间隔的毫秒数。如果你只想触发一次通知,请使用 set() 方法而不是 setRepeating() 方法。 4. 创建一个 BroadcastReceiver 来接收通知触发事件,并在 onReceive() 方法中创建和发送通知。 ``` public class YourNotificationReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 创建并发送通知 NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "channel_id") .setSmallIcon(R.drawable.notification_icon) .setContentTitle("Notification Title") .setContentText("Notification Content") .setPriority(NotificationCompat.PRIORITY_DEFAULT); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); notificationManager.notify(notificationId, builder.build()); } } ``` 这样,你的应用程序就可以在后台定时发送通知提醒了。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值