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

Android(Java)中如何实现特定时间事件的追踪与提醒?

嘿,这个需求其实在Android原生开发里完全能搞定,不用依赖Google Calendar API,也不用做复杂UI,我给你梳理两个实用的方案,都是用系统自带的API实现的:

方案一:AlarmManager + BroadcastReceiver(适合精准即时提醒)

如果你的需求是必须准点触发(比如类似闹钟的每日/每周提醒),这个组合是最优解,它可以唤醒设备执行任务,时效性很强。

步骤1:实现BroadcastReceiver处理提醒逻辑

先写一个广播接收器,当闹钟触发时,这里会收到广播,你可以在里面执行提醒操作(比如发送通知、启动后台任务):

public class ReminderReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 这里写提醒触发后的逻辑,比如弹出通知
        sendNotification(context);
    }

    private void sendNotification(Context context) {
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        
        // Android 8.0及以上必须创建通知渠道
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                "reminder_channel", 
                "定时提醒频道", 
                NotificationManager.IMPORTANCE_DEFAULT
            );
            notificationManager.createNotificationChannel(channel);
        }

        // 构建通知内容
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "reminder_channel")
                .setSmallIcon(R.drawable.ic_notification) // 替换成你的通知图标
                .setContentTitle("事件提醒")
                .setContentText("你设置的定时事件到啦!")
                .setPriority(NotificationCompat.PRIORITY_DEFAULT);
        
        notificationManager.notify(1, builder.build());
    }
}

步骤2:注册BroadcastReceiver

在AndroidManifest.xml里静态注册接收器(这样即使APP没运行,也能收到广播):

<receiver android:name=".ReminderReceiver" />

步骤3:设置定时任务

用AlarmManager来创建每日或每周的重复任务:

示例1:每日固定时段提醒(比如早上8点)

AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, ReminderReceiver.class);
// PendingIntent要加FLAG_IMMUTABLE适配Android 12+
PendingIntent pendingIntent = PendingIntent.getBroadcast(
    this, 
    0, 
    intent, 
    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);

// 设置触发时间为今天的8点
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);

// 如果当前时间已经过了8点,就把触发时间设为明天的8点
if (calendar.getTimeInMillis() < System.currentTimeMillis()) {
    calendar.add(Calendar.DAY_OF_YEAR, 1);
}

// 设置每日重复提醒
alarmManager.setRepeating(
    AlarmManager.RTC_WAKEUP, // 唤醒设备执行任务
    calendar.getTimeInMillis(),
    AlarmManager.INTERVAL_DAY, // 间隔1天
    pendingIntent
);

示例2:每周特定日期提醒(比如每周三下午3点)

Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY); // 周三
calendar.set(Calendar.HOUR_OF_DAY, 15); // 15点
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);

// 如果当前时间已经过了本周三的3点,就设为下周三
if (calendar.getTimeInMillis() < System.currentTimeMillis()) {
    calendar.add(Calendar.WEEK_OF_YEAR, 1);
}

// 设置每周重复提醒,间隔7天
alarmManager.setRepeating(
    AlarmManager.RTC_WAKEUP,
    calendar.getTimeInMillis(),
    7 * 24 * 60 * 60 * 1000L, // 7天的毫秒数
    pendingIntent
);

权限注意事项

Android 12及以上需要申请SCHEDULE_EXACT_ALARM权限,先在Manifest里声明:

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

然后动态请求权限(因为是危险权限):

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    if (!alarmManager.canScheduleExactAlarms()) {
        Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
        startActivity(intent);
    }
}
方案二:WorkManager(适合非即时、省电型任务)

如果你的提醒不需要绝对精准(比如允许系统在合适的时机执行,比如设备充电、空闲时),用WorkManager更合适,它是Jetpack组件,会自动优化任务执行时机,更省电,而且设备重启后任务会自动恢复。

步骤1:实现Worker类

创建一个Worker子类,里面写提醒逻辑:

public class ReminderWorker extends Worker {
    public ReminderWorker(@NonNull Context context, @NonNull WorkerParameters params) {
        super(context, params);
    }

    @NonNull
    @Override
    public Result doWork() {
        // 执行提醒操作
        sendNotification(getApplicationContext());
        return Result.success(); // 任务执行成功
    }

    private void sendNotification(Context context) {
        // 和之前Receiver里的通知代码一致,注意创建对应的通知渠道
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                "reminder_worker_channel", 
                "WorkManager提醒频道", 
                NotificationManager.IMPORTANCE_DEFAULT
            );
            notificationManager.createNotificationChannel(channel);
        }

        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "reminder_worker_channel")
                .setSmallIcon(R.drawable.ic_notification)
                .setContentTitle("WorkManager提醒")
                .setContentText("你设置的事件到啦!")
                .setPriority(NotificationCompat.PRIORITY_DEFAULT);
        
        notificationManager.notify(2, builder.build());
    }
}

步骤2:设置周期性任务

示例1:每日重复提醒

// 可选:设置任务约束,比如设备充电时执行
Constraints constraints = new Constraints.Builder()
        .setRequiresCharging(false) // 根据需求调整
        .build();

// 计算从当前时间到下一个8点的延迟时间
long initialDelay = calculateDailyInitialDelay(8, 0);

// 创建每日重复任务,间隔24小时
PeriodicWorkRequest dailyWorkRequest = new PeriodicWorkRequest.Builder(
        ReminderWorker.class, 
        24, 
        TimeUnit.HOURS
    )
    .setConstraints(constraints)
    .setInitialDelay(initialDelay, TimeUnit.MILLISECONDS)
    .build();

// 将任务入队
WorkManager.getInstance(this).enqueue(dailyWorkRequest);

辅助计算延迟的方法:

private long calculateDailyInitialDelay(int targetHour, int targetMinute) {
    Calendar now = Calendar.getInstance();
    Calendar target = Calendar.getInstance();
    target.set(Calendar.HOUR_OF_DAY, targetHour);
    target.set(Calendar.MINUTE, targetMinute);
    target.set(Calendar.SECOND, 0);

    if (target.before(now)) {
        target.add(Calendar.DAY_OF_YEAR, 1);
    }

    return target.getTimeInMillis() - now.getTimeInMillis();
}

示例2:每周特定日期提醒

long weeklyInitialDelay = calculateWeeklyInitialDelay(Calendar.WEDNESDAY, 15, 0);

PeriodicWorkRequest weeklyWorkRequest = new PeriodicWorkRequest.Builder(
        ReminderWorker.class, 
        7, 
        TimeUnit.DAYS
    )
    .setConstraints(constraints)
    .setInitialDelay(weeklyInitialDelay, TimeUnit.MILLISECONDS)
    .build();

WorkManager.getInstance(this).enqueue(weeklyWorkRequest);

辅助计算延迟的方法:

private long calculateWeeklyInitialDelay(int targetDayOfWeek, int targetHour, int targetMinute) {
    Calendar now = Calendar.getInstance();
    Calendar target = Calendar.getInstance();
    target.set(Calendar.DAY_OF_WEEK, targetDayOfWeek);
    target.set(Calendar.HOUR_OF_DAY, targetHour);
    target.set(Calendar.MINUTE, targetMinute);
    target.set(Calendar.SECOND, 0);

    if (target.before(now)) {
        target.add(Calendar.WEEK_OF_YEAR, 1);
    }

    return target.getTimeInMillis() - now.getTimeInMillis();
}
额外注意事项
  • AlarmManager重启问题:设备重启后,AlarmManager的任务会丢失,你需要注册BootCompletedReceiver,在设备重启后重新设置任务。
  • 精准性差异:AlarmManager的setRepeating在Android 6.0+可能会被系统调整触发时间,如果需要绝对精准,建议用setExactAndAllowWhileIdle,然后在每次触发后手动设置下一次任务。
  • WorkManager限制:PeriodicWorkRequest的最小间隔是15分钟,所以如果需要更短的重复周期,不适合用它。

内容的提问来源于stack exchange,提问作者Tanner Summers

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 02:29:15