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

如何实现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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 14:48:05