You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

安卓定时推送通知仅在应用打开时生效问题咨询

问题根因

  • 你当前使用的alarmManager.setExact()是一次性闹钟,触发后会自动失效,不会自动循环执行后续任务,所以只有首次打开App注册的那次闹钟会生效,后续没有新的闹钟注册自然不会触发
  • 你写死了固定的闹钟时间为20:01,没有动态计算下一次的执行时间,就算闹钟支持重复也无法按每小时的逻辑执行
  • 高版本Android存在后台限制:Android 6.0+的低电耗模式会拦截后台闹钟、Android12+要求PendingIntent必须显式指定可变性标记,国产ROM的省电策略也会默认杀死退后台的App闹钟任务

修复方案

1. 适配高版本Android的闹钟注册逻辑

修改setAlarm方法,补充PendingIntent标记和低电耗模式适配:

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private void setAlarm(Calendar calendar) {
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(this, AlarmReceiver.class);
    // 适配Android12+的PendingIntent可变性要求,不需要修改intent内容就用FLAG_IMMUTABLE
    int flag = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT;
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1, intent, flag);
    // 适配低电耗模式,保证熄屏状态下也能触发闹钟
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
    } else {
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
    }
}

2. 改造广播接收器实现循环触发

每次闹钟触发完成任务后,自动注册下一小时的闹钟:

public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 先执行文本文件变更检查逻辑,有变更再发通知
        NotificationHelper notificationHelper = new NotificationHelper(context);
        NotificationCompat.Builder nb = notificationHelper.getChannelNotification();
        notificationHelper.getManager().notify(1, nb.build());

        // 计算下一次闹钟时间:当前时间+1小时
        Calendar nextCalendar = Calendar.getInstance();
        nextCalendar.add(Calendar.HOUR_OF_DAY, 1);
        nextCalendar.set(Calendar.MINUTE, 0);
        nextCalendar.set(Calendar.SECOND, 0);
        // 注册下一次闹钟
        setNextAlarm(context, nextCalendar);
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void setNextAlarm(Context context, Calendar calendar) {
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(context, AlarmReceiver.class);
        int flag = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT;
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, intent, flag);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
        } else {
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
        }
    }
}

3. 修改初始闹钟逻辑

如果需要App启动后从当前时间开始每小时执行,修改onCreate里的初始闹钟设置:

notificationManager = NotificationManagerCompat.from(this);
// 初始闹钟设为当前时间往后推1小时的整点
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.HOUR_OF_DAY, 1);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
setAlarm(calendar);

补充注意事项

国内机型需要引导用户开启App的自启动权限、后台活动权限、关闭电池优化,否则App退后台后闹钟会被系统强制拦截。

内容的提问来源于stack exchange,提问作者blocks1245

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 10:24:03