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

安卓APP每日20:00定时重启后无限循环问题求助

解决APP每日20点自动重启后无限循环的问题

我来帮你排查这个问题——你遇到的无限重启困境,根源其实不在PendingIntent.FLAG_ONE_SHOT,而是Alarm设置的时间逻辑漏洞,加上APP重启后重复触发Alarm导致的循环。下面一步步拆解问题并给出解决方案:

问题根源分析

  1. 首次执行正常:第一天20点时,Alarm触发重启APP,流程符合预期。
  2. 无限重启循环:APP重启后,会重新执行App.java里的Alarm设置代码。此时当前时间已经是20点之后(比如20:00:00.100),你设置的Calendar指向的是当天的20点(已经是过去的时间),AlarmManager.setExact会立即触发这个Alarm,导致RestartReceiver再次调用重启逻辑,陷入死循环。
  3. 关于FLAG_ONE_SHOT:这个标记确实会让第一次的PendingIntent失效,但APP重启后你又重新创建了新的PendingIntent,所以每次重启都会生成新的Alarm,这就导致无限触发。

解决方案

1. 修复Calendar时间判断逻辑

最核心的是确保每次设置的Alarm都是未来的下一个20点,如果当前时间已经过了20点,就把日期往后推一天。

修改App.java的Alarm设置代码:

// 创建日历对象
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 20);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

// 关键判断:如果当前时间已经过了20点,设置为第二天的20点
if (System.currentTimeMillis() > calendar.getTimeInMillis()) {
    calendar.add(Calendar.DAY_OF_YEAR, 1);
}

// 调度重启
AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, RestartReceiver.class);

// 适配高版本的PendingIntent标记
int flags;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    flags = PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE;
} else {
    flags = PendingIntent.FLAG_UPDATE_CURRENT;
}
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, intent, flags);

// 适配Doze模式,确保低功耗下也能触发
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    alarmMgr.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), alarmIntent);
} else {
    alarmMgr.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), alarmIntent);
}

2. 优化重启逻辑(可选)

你Util.java里用AlarmManager重启的方式有点绕,可以换成更直接稳定的实现,避免额外的Alarm干扰:

private static final String TAG = "Util";

public static void restart(Context c) {
    try {
        if (c != null) {
            PackageManager pm = c.getPackageManager();
            if (pm != null) {
                Intent mStartActivity = pm.getLaunchIntentForPackage(c.getPackageName());
                if (mStartActivity != null) {
                    // 清除栈并启动新任务
                    mStartActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    c.startActivity(mStartActivity);
                    // 杀死当前进程,完成重启
                    android.os.Process.killProcess(android.os.Process.myPid());
                    System.exit(0);
                } else {
                    Log.e(TAG, "Was not able to restart application, mStartActivity null");
                }
            } else {
                Log.e(TAG, "Was not able to restart application, PM null");
            }
        } else {
            Log.e(TAG, "Was not able to restart application, Context null");
        }
    } catch (Exception ex) {
        Log.e(TAG, "Was not able to restart application", ex);
    }
}

3. 补充说明

  • PendingIntent.FLAG_UPDATE_CURRENT:确保每次设置Alarm时,会覆盖之前的PendingIntent,避免重复创建多个Alarm。
  • PendingIntent.FLAG_IMMUTABLE:Android 12及以上版本的强制要求,提升Intent的安全性。
  • setExactAndAllowWhileIdle:避免Doze模式(低功耗模式)下Alarm被延迟或忽略,确保20点能准时触发。

总结

核心问题是未处理当前时间已过20点的场景,导致APP重启后立即触发Alarm。修复时间判断逻辑,再配合适配高版本的API调用,就能实现每日20点自动重启的需求,不会再出现无限循环的问题。

内容的提问来源于stack exchange,提问作者Mr. B.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:56:12