安卓APP每日20:00定时重启后无限循环问题求助
解决APP每日20点自动重启后无限循环的问题
我来帮你排查这个问题——你遇到的无限重启困境,根源其实不在PendingIntent.FLAG_ONE_SHOT,而是Alarm设置的时间逻辑漏洞,加上APP重启后重复触发Alarm导致的循环。下面一步步拆解问题并给出解决方案:
问题根源分析
- 首次执行正常:第一天20点时,Alarm触发重启APP,流程符合预期。
- 无限重启循环:APP重启后,会重新执行
App.java里的Alarm设置代码。此时当前时间已经是20点之后(比如20:00:00.100),你设置的Calendar指向的是当天的20点(已经是过去的时间),AlarmManager.setExact会立即触发这个Alarm,导致RestartReceiver再次调用重启逻辑,陷入死循环。 - 关于
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.
相关产品推荐
相关产品推荐

