Android App Widget每分钟更新失效,倒计时功能运行数分钟后停止
问题根因
- AlarmManager触发时间设置错误:当前代码直接传入
60000作为触发时间,该值是相对于1970-01-01的时间戳,远早于当前时间,首次触发后后续调度逻辑直接异常 - PendingIntent标志不符合高版本安卓要求:安卓12(API 31)及以上要求PendingIntent必须显式指定
FLAG_IMMUTABLE或FLAG_MUTABLE,传入0会导致PendingIntent创建失败,无法接收定时广播 - 系统自动更新与自定义调度逻辑冲突:xml中设置的
updatePeriodMillis=60000小于安卓系统限制的最小值(30分钟,低于该值会被系统强制拉长到15~30分钟触发),两种更新逻辑冲突会导致更新中断 - 缺少自定义广播的处理逻辑:你定义了
ACTION_SCHEDULED_UPDATE3的定时广播,但没有在Manifest中注册该Action,也没有重写onReceive方法处理该广播,触发后无法执行更新和下一次调度
修复方案
1. 修改prayer_time_widget3_info.xml
将updatePeriodMillis改为0,禁用系统自动更新,完全走自定义Alarm调度:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialKeyguardLayout="@layout/prayer_time_widget3" android:initialLayout="@layout/prayer_time_widget3" android:minWidth="294dp" android:minHeight="90dp" android:previewImage="@drawable/ptwidget3preview" android:updatePeriodMillis="0" android:widgetCategory="home_screen" />
2. 修改AndroidManifest.xml的广播注册
添加自定义Action的intent-filter:
<receiver android:name=".PrayerTimeWidget3"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <!-- 新增自定义更新Action,替换为你应用实际的包名 --> <action android:name="你的应用包名.ACTION_SCHEDULED_UPDATE3" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/prayer_time_widget3_info" /> </receiver>
3. 修正PrayerTimeWidget3.class代码
重写onReceive方法处理自定义广播:
@Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); if (ACTION_SCHEDULED_UPDATE3.equals(intent.getAction())) { AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, PrayerTimeWidget3.class)); // 执行更新 for (int appWidgetId : appWidgetIds) { updateAppWidget(context, appWidgetManager, appWidgetId); } // 调度下一次更新 _scheduleNextUpdate(context); } }
修正_scheduleNextUpdate方法:
private static void _scheduleNextUpdate(Context context) { AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, PrayerTimeWidget3.class) .setAction(ACTION_SCHEDULED_UPDATE3); // 修正PendingIntent标志,适配高版本安卓 int pendingFlag = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT; PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, pendingFlag); // 修正触发时间:当前时间加1分钟 long triggerAtTime = System.currentTimeMillis() + 60 * 1000; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { alarmManager.setAndAllowWhileIdle(AlarmManager.RTC, triggerAtTime, pendingIntent); } else { alarmManager.set(AlarmManager.RTC, triggerAtTime, pendingIntent); } }
注意事项
- 安卓6.0及以上的低功耗模式下,
setAndAllowWhileIdle的最小触发间隔被限制为15分钟,如果必须每分钟更新,需要引导用户将你的应用加入系统电池优化白名单 - 安卓14对精确闹钟做了额外权限限制,如果需要严格准点更新,需要申请
SCHEDULE_EXACT_ALARM权限
内容的提问来源于stack exchange,提问作者Seyf
相关产品推荐
相关产品推荐

