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

Flutter无需Firebase实现后台本地通知:按周动态触发

实现动态week值触发后台本地通知方案

要实现应用未打开时也能根据动态变化的week值触发本地通知,核心是利用系统级的后台任务调度机制(不能依赖应用自身后台存活,系统会主动回收闲置进程),同时确保能实时获取最新的week值生成对应通知内容。以下分iOS和Android平台给出具体实现方案:

iOS 实现步骤

  • 申请通知权限:首先必须获取用户授权才能发送本地通知,可在应用启动时发起请求:
import UserNotifications

func requestNotificationPermission() {
    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
        if granted {
            // 权限获取成功,可后续调度通知
        }
    }
}
  • 调度后台触发任务:有两种可靠方式实现周期性触发,结合week值动态生成通知:
    1. 日历触发器(适合自然周场景):如果week对应日历周,可设置每周固定时间触发,触发时实时获取最新week值:
func scheduleWeeklyCalendarNotification() {
    // 每周一9点触发的日历规则
    let trigger = UNCalendarNotificationTrigger(dateMatching: DateComponents(weekday: 2, hour: 9), repeats: true)
    
    UNUserNotificationCenter.current().add(UNNotificationRequest(identifier: "WeeklyWeekReminder", content: UNMutableNotificationContent(), trigger: trigger))
}

// 监听通知即将展示的回调,动态替换内容
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    let updatedContent = UNMutableNotificationContent(contentsOf: notification.request.content)!
    let currentWeek = getCurrentWeek() // 自定义方法,获取最新week值
    updatedContent.title = "周数提醒"
    updatedContent.body = "你处于第\(currentWeek)周"
    
    // 更新通知请求
    let updatedRequest = UNNotificationRequest(identifier: notification.request.identifier, content: updatedContent, trigger: notification.request.trigger)
    center.add(updatedRequest)
    
    completionHandler([.alert, .sound])
}
  1. 后台刷新任务:允许应用在后台定期唤醒,主动获取week值并触发通知,适合非固定周周期的场景:
// Info.plist中添加BGTaskSchedulerPermittedIdentifiers,值为"com.yourapp.weekRefreshTask"
func registerBackgroundRefreshTask() {
    BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.yourapp.weekRefreshTask", using: nil) { task in
        self.handleWeekRefresh(task as! BGAppRefreshTask)
    }
}

func handleWeekRefresh(_ task: BGAppRefreshTask) {
    // 获取最新week值(从本地存储或接口)
    let currentWeek = getCurrentWeek()
    
    // 构建并发送通知
    let content = UNMutableNotificationContent()
    content.title = "周数提醒"
    content.body = "你处于第\(currentWeek)周"
    content.sound = .default
    
    UNUserNotificationCenter.current().add(UNNotificationRequest(identifier: "WeekUpdate-\(currentWeek)", content: content, trigger: nil))
    
    // 标记任务完成,避免系统限制后续后台任务
    task.setTaskCompleted(success: true)
    
    // 调度下一次任务(一周后)
    let nextRequest = BGAppRefreshTaskRequest(identifier: "com.yourapp.weekRefreshTask")
    nextRequest.earliestBeginDate = Date().addingTimeInterval(7*24*60*60)
    try? BGTaskScheduler.shared.submit(nextRequest)
}

Android 实现步骤

  • 申请必要权限:在AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
  • 使用WorkManager调度后台任务:WorkManager是Android官方推荐的后台任务组件,可保证应用未运行、设备重启后仍能执行任务:
    1. 创建Worker类:处理通知发送逻辑:
class WeekNotificationWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        // 获取最新week值(从SharedPreferences或接口)
        val currentWeek = getCurrentWeek()
        
        // 创建通知渠道(Android 8.0+必须)
        val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel("week_reminder_channel", "周数提醒", NotificationManager.IMPORTANCE_DEFAULT)
            notificationManager.createNotificationChannel(channel)
        }
        
        // 构建并发送通知
        val notification = NotificationCompat.Builder(applicationContext, "week_reminder_channel")
            .setContentTitle("周数提醒")
            .setContentText("你处于第$currentWeek周")
            .setSmallIcon(R.drawable.ic_notification)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .build()
        notificationManager.notify(1, notification)
        
        // 调度下一次任务
        scheduleWeeklyNotification(applicationContext)
        return Result.success()
    }
}
  1. 调度周期性任务:
fun scheduleWeeklyNotification(context: Context) {
    val constraints = Constraints.Builder()
        .setRequiresBatteryNotLow(true) // 可选,低电时暂停任务
        .build()
    
    val weeklyWork = PeriodicWorkRequestBuilder<WeekNotificationWorker>(7, TimeUnit.DAYS)
        .setConstraints(constraints)
        .build()
    
    WorkManager.getInstance(context).enqueueUniquePeriodicWork(
        "WeekNotificationWork",
        ExistingPeriodicWorkPolicy.REPLACE,
        weeklyWork
    )
}
  1. 处理开机自启:确保设备重启后任务能重新调度,创建广播接收器:
class BootCompleteReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
            context?.let { scheduleWeeklyNotification(it) }
        }
    }
}

在AndroidManifest.xml注册接收器:

<receiver android:name=".BootCompleteReceiver" android:enabled="true" android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>
  • 动态申请通知权限(Android 13+):
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 1001)
    }
}

通用注意事项

  • week值的持久化:必须将week值存储在本地(iOS的UserDefaults、Android的SharedPreferences)或通过接口实时获取,避免后台触发时无法拿到最新值。
  • 避免硬编码内容:通知内容必须在触发任务的瞬间动态生成,不能提前固定,防止week值更新后通知内容过时。
  • 系统限制适配:iOS的后台刷新任务、Android的WorkManager都受系统资源(电量、内存)限制,若需要高精度触发,可结合应用启动时的通知更新逻辑作为补充。

内容的提问来源于stack exchange,提问作者faizy 313

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 18:01:25