如何实现Android AppWidget每日凌晨12点自动更新TextView
实现方案
你当前配置的updatePeriodMillis为3600000毫秒(1小时),且系统自带的定时更新存在误差、无法保证准点触发,要实现每天凌晨12点准点更新,推荐使用AlarmManager设置精准定时任务,适配逻辑如下:
1. 修改WidgetProvider代码
新增定时任务注册、自定义广播接收逻辑:
public class WidgetProvider extends AppWidgetProvider { // 自定义广播Action,用于触发widget更新 public static final String ACTION_UPDATE_WIDGET = "com.yourpackage.UPDATE_WIDGET"; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { updateWidgetContent(context, appWidgetManager, appWidgetIds); } // widget首次被添加到桌面时调用,注册定时任务 @Override public void onEnabled(Context context) { super.onEnabled(context); setMidnightUpdateAlarm(context); } // 最后一个widget被移除时调用,取消定时任务 @Override public void onDisabled(Context context) { super.onDisabled(context); cancelMidnightUpdateAlarm(context); } // 接收广播触发更新 @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); if (ACTION_UPDATE_WIDGET.equals(intent.getAction())) { AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, WidgetProvider.class)); updateWidgetContent(context, appWidgetManager, appWidgetIds); } } // 抽取公共更新逻辑,避免重复代码 private void updateWidgetContent(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { for(int appWidgetId : appWidgetIds) { RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.app_widget); LocalDate birthday = LocalDate.of(2020, 10, 16); LocalDate now = LocalDate.now(); long days = ChronoUnit.DAYS.between(birthday,now) + 1; views.setTextViewText(R.id.widget_days, Long.toString(days)); appWidgetManager.updateAppWidget(appWidgetId,views); } } // 设置凌晨12点的定时闹钟 private void setMidnightUpdateAlarm(Context context) { AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, WidgetProvider.class); intent.setAction(ACTION_UPDATE_WIDGET); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); // 计算下一次凌晨12点的时间戳 Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); // 如果当前时间已经过了今天零点,就设置为明天零点 if (calendar.getTimeInMillis() < System.currentTimeMillis()) { calendar.add(Calendar.DAY_OF_MONTH, 1); } // 设置重复闹钟,间隔为1天 if (alarmManager != null) { // Android 6.0+低电耗模式下用setAndAllowWhileIdle保证准点 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent); } else { alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent); } } } // 取消定时闹钟 private void cancelMidnightUpdateAlarm(Context context) { AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, WidgetProvider.class); intent.setAction(ACTION_UPDATE_WIDGET); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); if (alarmManager != null) { alarmManager.cancel(pendingIntent); } } }
注意把代码里的com.yourpackage替换成你自己应用的包名
2. 修改Manifest配置
在receiver的intent-filter里新增自定义广播的Action声明:
<receiver android:name=".widget.WidgetProvider"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/> <!-- 新增自定义更新Action --> <action android:name="com.yourpackage.UPDATE_WIDGET"/> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_info"/> </receiver>
3. 可选权限适配(Android 12+)
如果你的应用targetSdkVersion >= 31,需要在Manifest里添加闹钟权限,保证定时准点:
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> <uses-permission android:name="android.permission.WAKE_LOCK" android:maxSdkVersion="32" />
额外说明
你原来的updatePeriodMillis可以保留作为兜底更新策略,避免极端情况定时任务失效后widget长期不更新。
内容的提问来源于stack exchange,提问作者Saeedmosavyzadeh
相关产品推荐
相关产品推荐

