如何在Objective-C中通过本地通知每日8点调用Web Service并展示数据计数
实现每日8点调用Web Service并展示本地通知的方案
没问题!我来帮你梳理一套完整的实现方案,分通用核心逻辑和主流平台(iOS/Swift、Android/Kotlin)的具体代码示例,你可以按需参考:
通用核心逻辑
不管是iOS还是Android,核心流程都是这三步:
- 定时触发任务:每天上午8点精准触发任务,必须用系统级的定时机制,避免设备休眠导致任务“躺平”不执行;
- 拉取数据并计数:调用你的Web Service获取数组数据,计算数组长度(也就是新通知的条数);
- 展示本地通知:把计数结果拼进通知文案,调用系统API弹出通知,比如“您有10条新通知”。
iOS(Swift)具体实现
1. 先配置权限
在Info.plist里添加通知权限和后台刷新权限,不然系统会限制你的操作:
<key>NSNotificationUsageDescription</key> <string>需要向您推送新通知提醒</string> <key>UIBackgroundModes</key> <array> <string>fetch</string> <string>remote-notification</string> </array>
2. 启动时申请通知权限
在AppDelegate或者SceneDelegate里申请用户授权,不然弹不出通知:
import UserNotifications func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in if granted { DispatchQueue.main.async { application.registerForRemoteNotifications() } } // 可以在这里处理权限被拒绝的情况 } // 别忘了设置代理,用来更新通知内容 UNUserNotificationCenter.current().delegate = self // 初始化定时任务 setupDailyNotificationTask() return true }
3. 设置每日8点的定时任务
用UNCalendarNotificationTrigger来实现精准的每日触发,然后在通知即将展示时拉取数据更新内容:
func setupDailyNotificationTask() { let content = UNMutableNotificationContent() content.title = "新通知提醒" content.sound = UNNotificationSound.default // 设置每天8点整触发 var dateComponents = DateComponents() dateComponents.hour = 8 dateComponents.minute = 0 let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true) // 创建唯一的通知请求 let request = UNNotificationRequest(identifier: "DailyNotificationCheck", content: content, trigger: trigger) // 把任务交给系统 UNUserNotificationCenter.current().add(request) { error in if let error = error { print("定时任务添加失败:\(error.localizedDescription)") } } } // 实现代理方法,在通知展示前更新内容 extension AppDelegate: UNUserNotificationCenterDelegate { func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { // 调用Web Service拉取数据 fetchNewNotifications { count in // 复制原通知内容并更新文案 let updatedContent = UNMutableNotificationContent(notification.content) updatedContent.body = "您有\(count)条新通知" // 更新通知请求 let updatedRequest = UNNotificationRequest(identifier: notification.request.identifier, content: updatedContent, trigger: notification.request.trigger) center.add(updatedRequest) { _ in // 展示通知 completionHandler([.alert, .sound]) } } } } // 封装Web Service调用逻辑 func fetchNewNotifications(completion: @escaping (Int) -> Void) { guard let url = URL(string: "https://your-web-service-url.com/notifications") else { completion(0) return } URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data, error == nil else { completion(0) return } do { // 替换成你的数据模型 let notifications = try JSONDecoder().decode([NotificationModel].self, from: data) completion(notifications.count) } catch { print("数据解析失败:\(error)") completion(0) } }.resume() } // 定义你的数据模型(根据Web Service返回字段调整) struct NotificationModel: Codable { let id: Int let title: String // 其他字段... }
Android(Kotlin)具体实现
1. 配置权限和组件
在AndroidManifest.xml里添加必要的权限和组件,保证任务能正常执行:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <!-- 开机自启,避免任务丢失 --> <uses-permission android:name="android.permission.INTERNET"/> <application ...> <!-- 注册广播接收器(处理开机自启) --> <receiver android:name=".DailyNotificationReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> <!-- 注册JobService(处理后台任务) --> <service android:name=".NotificationJobService" android:permission="android.permission.BIND_JOB_SERVICE"/> </application>
2. 申请通知权限(Android 13+)
在MainActivity里申请通知权限,不然Android 13及以上版本弹不出通知:
import android.Manifest import android.content.pm.PackageManager import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat class MainActivity : AppCompatActivity() { private val POST_NOTIFICATIONS_REQUEST = 1001 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 申请通知权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.POST_NOTIFICATIONS), POST_NOTIFICATIONS_REQUEST) } // 初始化定时任务 setupDailyNotificationTask(this) } }
3. 设置每日定时任务(用JobScheduler)
JobScheduler是Android推荐的后台任务调度器,能适配系统的省电策略:
import android.app.job.JobInfo import android.app.job.JobScheduler import android.content.ComponentName import android.content.Context fun setupDailyNotificationTask(context: Context) { val jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler // 构建任务信息:每天执行一次,需要网络 val jobInfo = JobInfo.Builder(1001, ComponentName(context, NotificationJobService::class.java)) .setPeriodic(24 * 60 * 60 * 1000) // 24小时周期 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) // 需要网络才能执行 .setPersisted(true) // 重启设备后任务保留 .build() // 提交任务 jobScheduler.schedule(jobInfo) }
4. 实现JobService处理任务
在NotificationJobService里完成Web Service调用和通知展示:
import android.app.job.JobParameters import android.app.job.JobService import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context import android.os.Build import androidx.core.app.NotificationCompat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.json.JSONArray import java.net.URL class NotificationJobService : JobService() { private val CHANNEL_ID = "DailyNotificationChannel" private val NOTIFICATION_ID = 1 override fun onStartJob(params: JobParameters?): Boolean { // 用协程处理网络请求,避免阻塞主线程 CoroutineScope(Dispatchers.IO).launch { val count = fetchNewNotifications() showNotification(count) // 任务完成,告诉系统不需要重新调度 jobFinished(params, false) } return true // 表示任务在后台执行 } override fun onStopJob(params: JobParameters?): Boolean { return true // 如果任务被系统中断,重新调度 } // 调用Web Service并计数 private suspend fun fetchNewNotifications(): Int { return try { val url = URL("https://your-web-service-url.com/notifications") val response = url.readText() // 解析JSON数组(根据实际返回格式调整) val notifications = JSONArray(response) notifications.length() } catch (e: Exception) { e.printStackTrace() 0 } } // 展示本地通知 private fun showNotification(count: Int) { val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Android 8.0+需要创建通知渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( CHANNEL_ID, "每日通知提醒", NotificationManager.IMPORTANCE_DEFAULT ) notificationManager.createNotificationChannel(channel) } val notification = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("新通知提醒") .setContentText("您有$count条新通知") .setSmallIcon(R.drawable.ic_notification) // 替换成你的通知图标 .setPriority(NotificationCompat.PRIORITY_DEFAULT) .build() notificationManager.notify(NOTIFICATION_ID, notification) } }
5. 开机自启广播接收器
保证设备重启后定时任务能重新生效:
import android.content.BroadcastReceiver import android.content.Context import android.content.Intent class DailyNotificationReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action == Intent.ACTION_BOOT_COMPLETED) { context?.let { setupDailyNotificationTask(it) } } } }
一些注意事项
- 异常处理:网络请求一定要处理失败情况(比如无网络、解析错误),避免任务崩溃,默认可以返回0条;
- iOS后台限制:如果App被用户强制关闭,定时任务会暂停,这种情况可以结合远程推送来唤醒App;
- Android省电策略:
JobScheduler在Doze模式下可能延迟执行,如果需要更精准的定时,可以考虑AlarmManager配合WakeLock,但要注意控制耗电。
内容的提问来源于stack exchange,提问作者Manju Sreejith
相关产品推荐
相关产品推荐

