安卓定时任务处理

一、WorkManager
最大优点:
1、执行可靠性保证:系统重启、或应用被干掉,都能恢复任务 (任务状态持久化存储)
2、系统友好性:自动适应系统资源状态、遵循电池优化策略、不会因系统限制而崩溃

其它优点:
3、灵活的任务约束

Constraints constraints = new Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)    // 需要网络连接
    .setRequiresBatteryNotLow(true)                  // 电量充足
    .setRequiresCharging(true)                       // 充电时执行
    .setRequiresDeviceIdle(true)                     // 设备空闲时
    .setRequiresStorageNotLow(true)                  // 存储空间充足
    .build();

4、任务链支持

WorkManager.getInstance(context)
    .beginWith(Arrays.asList(workA, workB))  // 并行执行 A 和 B
    .then(workC)                             // 然后执行 C
    .then(workD)                             // 最后执行 D
    .enqueue();

5、可以观察任务状态

WorkManager.getInstance(context)
    .getWorkInfoByIdLiveData(workRequest.getId())
    .observe(lifecycleOwner, workInfo -> {
        if (workInfo != null) {
            WorkInfo.State state = workInfo.getState();
            // 处理不同状态
            switch (state) {
                case SUCCEEDED:
                    // 任务成功
                    break;
                case FAILED:
                    // 任务失败
                    break;
                case RUNNING:
                    // 任务运行中
                    break;
            }
        }
    });

6、支持任务输入输出数据

缺点:

因系统友好性,所以在某些场景下,不能精确执行
- 在系统休眠时,任务会被延迟执行
- 系统唤醒后,延迟的任务会被执行

使用建议:

- 对于需要保证执行的后台任务,优先使用 WorkManager
- 合理设置任务约束,避免过度消耗系统资源
- 利用任务链功能组织复杂的任务流程
- 注意观察任务状态,及时处理异常情况
- 对于需要精确定时的任务,可以考虑配合 AlarmManager 使用

二、AlarmManger

最大优点:

1、比较强势,保证精确执行:

- 由系统服务直接管理
- 可以在应用被干掉后继续工作
- 即使设备休眠也会准时触发
- 在低功耗模式下也能保证执行
- 可以唤醒设备执行任务

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

// 精确定时,即使设备休眠也会准时触发
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    alarmManager.setExactAndAllowWhileIdle(
        AlarmManager.RTC_WAKEUP,
        triggerTime,
        pendingIntent
    );
}

2、多种触发模式 

// 精确时间触发,会唤醒设备
alarmManager.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);

// 精确时间触发,不唤醒设备
alarmManager.setExact(AlarmManager.RTC, time, pendingIntent);

// 相对时间触发,从设备启动时开始计时
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME, time, pendingIntent);

// 允许不精确触发,系统可能会将多个闹钟合并
alarmManager.set(AlarmManager.RTC, time, pendingIntent);

3、重复任务支持 

// 设置重复闹钟
alarmManager.setRepeating(
    AlarmManager.RTC_WAKEUP,
    firstTime,
    intervalMillis,
    pendingIntent
);

实现方式
使用AlarmManager简单实现定时每天或重复执行任务,有3种方式

1)AlarmManager+Service 实现方式

2)AlarmManager+InterService 实现方式

3)AlarmManger + BoardcastReceiver 实现方式

需要在AndroidMainifast.xml 增加权限

1)增加ALARM(闹钟)权限

<uses-permission android:name="android.permission.SET_ALARM"/>

<uses-permission android:name="android.permission.WAKE_LOCK"/>

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2)增加Service和BoardcastReceiver注册

  <service android:name=".service.AlarmService" />
  <service android:name=".service.AlarmIntentService"/>
  <receiver android:name=".broadcast.AlarmBroadcastReceiver" />

3)Service和BoardcastReceiver定义

 3.1)AlarmService

public class AlarmService extends Service {

    private final String TAG = "AlarmService";
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 在这里执行你的任务
        Log.e(TAG,"调用闹钟,调用时间:"+ DateHelper.timestampToDate(System.currentTimeMillis()) );
        // 任务执行完毕后,停止Service
        stopSelf();
        return START_NOT_STICKY;
    }

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

3.2)AlarmIntentService

public class AlarmIntentService extends IntentService
{
    private final String TAG = "AlarmIntentService";

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

    @Override
    protected void onHandleIntent(Intent intent)
    {
        Log.e(TAG,"调用闹钟,调用时间:"+ DateHelper.timestampToDate(System.currentTimeMillis()) );
    }
}

 3.3)AlarmBoardcastReceiver

public class AlarmBroadcastReceiver extends BroadcastReceiver
{
    private final String TAG = "AlarmBroadcastReceiver";
    public static String alarmboradcastAction = "alarm.broadcast.upload";
    @Override
    public void onReceive(Context context, Intent intent)
    {
        if(intent.getAction().equals(alarmboradcastAction))
        {
            Log.e(TAG,"调用闹钟,调用时间:"+ DateHelper.timestampToDate(System.currentTimeMillis()));
        }

    }
}

4)AlarmManager结合Service、IntentService、boardcastReceiver使用

4.1)AlarmManager+Service 使用

  /**
     * AlarmManager + Service 实现定时任务
     * */
    public void AlarmServiceTest(){
        // 设置定时任务的代码片段
        Intent alarmIntent = new Intent(this, AlarmService.class);
        PendingIntent pendingIntent = PendingIntent.getService(this, 0, alarmIntent, 0);
        AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        // 设置单次闹钟或重复闹钟
        // 设置为单次闹钟
        long triggerAtMillis = System.currentTimeMillis() + 1000; // 10秒后触发
        alarmManager.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);

        // 或者设置重复闹钟(最小时间间隔:1 min)
        //long intervalMillis = 1000 * 60*1; // 每隔60秒触发一次
        //alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), intervalMillis, pendingIntent);
    }

4.2)AlarmManager+IntentService 使用

 /**
     * AlarmManager + IntentService 实现定时任务
     * */
    public void AlarmInterServiceTest(){
        // 设置定时任务的代码片段
        Intent alarmIntent = new Intent(this, AlarmIntentService.class);
        PendingIntent pendingIntent = PendingIntent.getService(this, 0, alarmIntent, 0);
        AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        // 设置单次闹钟或重复闹钟
        // 设置为单次闹钟
        //long triggerAtMillis = System.currentTimeMillis() + 1000; // 10秒后触发
        //alarmManager.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);

        // 或者设置重复闹钟(最小时间间隔:1 min)
        long intervalMillis = 1000 * 60*1; // 每隔60秒触发一次
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), intervalMillis, pendingIntent);

    }

4.3)AlarmManager+BroadcastReceiver 使用

  /**
     * AlarmManager+BroadcastReceiver 方式实现定时任务
     * */
    public void AlarmBroadcastTest(){
        // 设置定时任务的代码片段
        Intent alarmIntent = new Intent(this, AlarmBroadcastReceiver.class);
        alarmIntent.setAction(AlarmBroadcastReceiver.alarmboradcastAction);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
        AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        // 设置单次闹钟或重复闹钟
        // 设置为单次闹钟
        //long triggerAtMillis = System.currentTimeMillis() + 1000; // 10秒后触发
        //alarmManager.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
        // 或者设置重复闹钟
        long intervalMillis = 1000 * 60*1; // 每隔60秒触发一次1000 * 60
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), intervalMillis, pendingIntent);
    }


AlarmManager 重置延迟时间:

 public void resetAlarmDelay(Context context, long newDelayMillis) {
        // 取消现有的闹钟
        if (alarmManager != null && pendingIntent != null) {
            alarmManager.cancel(pendingIntent);
        }
        
        // 获取 AlarmManager 服务
        alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        
        // 创建 PendingIntent
        Intent intent = new Intent(context, AlarmReceiver.class);
        pendingIntent = PendingIntent.getBroadcast(
            context,
            0,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );
        
        // 设置新的延迟时间
        long triggerTime = System.currentTimeMillis() + newDelayMillis;
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // Android 6.0 及以上使用 setExactAndAllowWhileIdle
            alarmManager.setExactAndAllowWhileIdle(
                AlarmManager.RTC_WAKEUP,
                triggerTime,
                pendingIntent
            );
        } else {
            // 低版本使用 setExact
            alarmManager.setExact(
                AlarmManager.RTC_WAKEUP,
                triggerTime,
                pendingIntent
            );
        }
    }

注意事项:

1. 重置时会先取消旧的闹钟
2. 使用 FLAG_UPDATE_CURRENT 更新现有的 PendingIntent
3. 根据系统版本使用不同的设置方法
4. 记得在适当时机取消闹钟


三、其它定时处理

Handler :

- UI 相关的延时任务
- 需要在主线程执行的任务
- 简单的定时器功能
- 不能保证精确执行,且不保证执行可靠性,应用层面的

Timer:
不适合安卓系统

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值