如何在Flutter中实现本地价格预警通知功能
基于价格的本地预警功能实现方案
核心逻辑梳理
- 存储用户目标金额:用本地数据库(如iOS的Core Data、Android的Room)保存用户设置的目标金额及对应监控标的信息。
- 定期拉取API数据:无论应用处于前台还是后台,定时请求价格接口,对比实际金额与目标金额。
- 触发通知:当实际金额等于目标金额时,立即推送本地通知。
- 权限前置:必须先获取用户的通知权限,否则无法推送通知。
iOS平台实现步骤
1. 申请通知权限
App启动时发起权限请求,代码示例:
import UserNotifications func requestNotificationPermission() { UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in if let error = error { print("通知权限申请失败:\(error.localizedDescription)") } } }
2. 后台任务配置
- 在
Info.plist中添加UIBackgroundModes,勾选fetch(后台数据获取)或processing(后台任务处理)。 - 配置后台刷新任务定期拉取API:
func setupBackgroundFetch() { UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplication.backgroundFetchIntervalMinimum) } // 实现AppDelegate的后台刷新回调 func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { fetchPriceDataFromAPI { [weak self] price in guard let self = self, let targetPrice = self.getTargetPriceFromLocalStorage() else { completionHandler(.failed) return } if price == targetPrice { self.sendLocalNotification(title: "价格预警", body: "目标金额已达成!") } completionHandler(.newData) } }
3. 推送本地通知
func sendLocalNotification(title: String, body: String) { let content = UNMutableNotificationContent() content.title = title content.body = body content.sound = .default let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil) UNUserNotificationCenter.current().add(request) { error in if let error = error { print("推送通知失败:\(error.localizedDescription)") } } }
4. 前台显示通知
默认iOS前台不弹出通知,需实现UNUserNotificationCenterDelegate方法开启前台通知:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.alert, .sound]) }
Android平台实现步骤
1. 申请通知权限
- Android 13及以上需在Manifest中添加权限:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
- 动态申请权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.POST_NOTIFICATIONS), 1001) }
2. 后台任务配置
用WorkManager实现定时拉取,保证后台可执行:
class PriceCheckWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { val price = fetchPriceFromAPI() val targetPrice = getTargetPriceFromRoom() if (price == targetPrice) { sendLocalNotification(applicationContext, "价格预警", "目标金额已达成!") } // 配置每15分钟重复执行 val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build() val request = PeriodicWorkRequestBuilder<PriceCheckWorker>(15, TimeUnit.MINUTES) .setConstraints(constraints) .build() WorkManager.getInstance(applicationContext).enqueue(request) return Result.success() } }
- 启动Worker:
val request = PeriodicWorkRequestBuilder<PriceCheckWorker>(15, TimeUnit.MINUTES) .setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()) .build() WorkManager.getInstance(this).enqueue(request)
3. 推送本地通知
fun sendLocalNotification(context: Context, title: String, body: String) { val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Android 8.0+需创建通知渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel("price_alert_channel", "价格预警", NotificationManager.IMPORTANCE_DEFAULT) notificationManager.createNotificationChannel(channel) } val intent = context.packageManager.getLaunchIntentForPackage(context.packageName) val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE) val notification = NotificationCompat.Builder(context, "price_alert_channel") .setContentTitle(title) .setContentText(body) .setSmallIcon(R.drawable.ic_notification) .setContentIntent(pendingIntent) .setPriority(NotificationCompat.PRIORITY_DEFAULT) .build() notificationManager.notify(1, notification) }
4. 前台通知处理
Android前台默认会显示通知,权限正常即可生效,无需额外配置。
注意事项
- API请求频率:建议设置15分钟以上间隔,避免系统限制或过度耗电。
- 异常处理:拉取API时需处理网络异常,可添加重试或缓存策略。
- 多标的支持:数据库设计要兼容多用户、多监控标的的场景。
内容的提问来源于stack exchange,提问作者Himani Upadhyay
相关产品推荐
相关产品推荐

