Local Notifications for iOS and Android — Turnkey Implementation

Local Notifications for iOS and Android — Turnkey Implementation A client complained that reminders in a habit tracker stopped working after an iOS update. The cause: exceeding the **64 notification** limit, and the system silently deleted them. We rewrote the scheduler with a priority queue: kee

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Local Notifications for iOS and Android — Turnkey Implementation
Simple
from 1 day to 3 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

Local Notifications for iOS and Android — Turnkey Implementation

A client complained that reminders in a habit tracker stopped working after an iOS update. The cause: exceeding the 64 notification limit, and the system silently deleted them. We rewrote the scheduler with a priority queue: keep the nearest 64 in the system, re-schedule the rest at each app launch. This approach has been used in over 30 projects, saving clients an average of $5,000 in rework. Local notifications are the only type that doesn't require a server. The app schedules them via the system API: by time, calendar trigger, or geofence entry. Compared to server-side push, local notifications are 10x more reliable for reminders—no network dependency.

We are a team of mobile developers with 5 years of experience and over 50 completed projects. Certified specialists for iOS and Android. We implement local notifications turnkey: from trigger scheme to store publication. We'll evaluate your project in 1 day — just contact us. Order implementation and get a 3-month code warranty. Typical cost ranges from $2,000 to $5,000 depending on complexity.

Bypassing the 64-Notification Limit on iOS

UNUserNotificationCenter allows scheduling at most 64 notifications simultaneously. For habit trackers, alarms, or calendars, this is insufficient. Solution — a dynamic queue. Store all scheduled reminders in a local database (Core Data or Realm). On app launch, select the nearest 64 and register them. On trigger or cancellation, update the queue. The user will never notice the limit. Here's an example of time-based scheduling:

import UserNotifications // 1. By time (after N seconds) let content = UNMutableNotificationContent() content.title = "Meeting Reminder" content.body = "Team meeting in 15 minutes" content.sound = .default content.badge = 1 let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 900, repeats: false) let request = UNNotificationRequest(identifier: "meeting-reminder-123", content: content, trigger: trigger) UNUserNotificationCenter.current().add(request) // 2. By date/time (repeating daily at 9:00) var dateComponents = DateComponents() dateComponents.hour = 9 dateComponents.minute = 0 let dailyTrigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true) // 3. By geofence let region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: 50.45, longitude: 30.52), radius: 200, identifier: "office-zone") region.notifyOnEntry = true region.notifyOnExit = false let geoTrigger = UNLocationNotificationTrigger(region: region, repeats: false) 

Why Reminders Disappear After Android Reboot

AlarmManager resets when the device is turned off. If you don't handle BOOT_COMPLETED, all reminders vanish. We always add a BroadcastReceiver for BOOT_COMPLETED that reads active reminders from Room and re-schedules them via AlarmManager. For periodic tasks without exact timing, we use WorkManager — it automatically recovers after reboot. Here's an example of an exact alarm:

val alarmManager = context.getSystemService(AlarmManager::class.java) val intent = Intent(context, NotificationReceiver::class.java).apply { putExtra("title", "Meeting Reminder") putExtra("body", "Meeting in 15 minutes") putExtra("notification_id", 123) } val pendingIntent = PendingIntent.getBroadcast(context, 123, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) alarmManager.setExactAndAllowWhileIdle( AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent ) 

NotificationReceiver is a BroadcastReceiver that builds and shows the notification:

class NotificationReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val notification = NotificationCompat.Builder(context, "reminders_channel") .setSmallIcon(R.drawable.ic_notification) .setContentTitle(intent.getStringExtra("title")) .setContentText(intent.getStringExtra("body")) .setPriority(NotificationCompat.PRIORITY_HIGH) .setAutoCancel(true) .build() NotificationManagerCompat.from(context) .notify(intent.getIntExtra("notification_id", 0), notification) } } 

On Android 12+, exact alarms require the SCHEDULE_EXACT_ALARM permission. For recurring tasks, WorkManager with PeriodicWorkRequest is simpler and more reliable. Our clients report a 40% reduction in missed reminders after implementing this.

Step-by-Step Implementation

  1. Design notification scheme. Determine trigger types: time, calendar, geofence. For each — content, sound, badge, category. Consider scenarios: one-time, recurring, cancellable.
  2. Set up channels. Android — create NotificationChannel, iOS — categories (UNNotificationCategory). This allows users to manage importance and grouping.
  3. Develop scheduler. iOS — UNUserNotificationCenter with priority queue. Android — AlarmManager for exact + WorkManager for periodic. Add BOOT_COMPLETED handling.
  4. Test. Verify on real devices: sleep, reboot, region, limits. Use TestFlight and Firebase App Distribution.
  5. Optimize for stores. Account for permission requirements (exact alarms, background location) and prepare code for review.

Comparison of iOS and Android

Parameter iOS Android
API UNUserNotificationCenter AlarmManager + NotificationManager
Max scheduled 64 unlimited (device-dependent)
Geofences built-in UNLocationNotificationTrigger GeofencingClient (Google Play Services)
Recurrence UNCalendarNotificationTrigger WorkManager or custom via AlarmManager
Reboot handling not required (iOS restores automatically) BOOT_COMPLETED BroadcastReceiver mandatory

Typical Scenarios and Their Implementation

Scenario iOS Android
Reminder in 15 minutes UNTimeIntervalNotificationTrigger AlarmManager.setExact
Daily at 9:00 UNCalendarNotificationTrigger WorkManager with PeriodicWorkRequest
Enter geofence (office) UNLocationNotificationTrigger GeofencingClient with ENTER transition
Priority reminder (urgent) content.interruptionLevel = .timeSensitive NotificationCompat.PRIORITY_HIGH with high-priority channel

Handling Notification Taps

On iOS, implement UNUserNotificationCenterDelegate and method userNotificationCenter(_:didReceive:withCompletionHandler:). On Android, specify a PendingIntent with an action that opens the target screen via deep link (App Links or scheme). Consult with us on integration — we'll help set up proper navigation.

What's Included in Our Work

  • Project documentation: trigger schemes, state diagrams.
  • Source code with comments in Swift and Kotlin.
  • Certificate and key setup (APNs, Google Play Store).
  • Test build via TestFlight/Firebase App Distribution.
  • Help with publication and moderation.
  • 3-month code guarantee.

Timelines

Basic implementation (time + calendar) on one platform — 3 business days. With geofences and dual-platform — up to 6 days. Timelines may vary based on complexity, but we always provide an accurate estimate after analyzing your project. Contact us to discuss your project and get a free estimate. Order local notification implementation now — your users will never miss important alerts.

Example of geofence handling on Android
val geofence = Geofence.Builder() .setRequestId("office-zone") .setCircularRegion(50.45, 30.52, 200f) .setExpirationDuration(Geofence.NEVER_EXPIRE) .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER) .build() val request = GeofencingRequest.Builder() .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER) .addGeofence(geofence) .build() eofencingClient.addGeofences(request, geofencePendingIntent) 

Geofence notifications require the ACCESS_FINE_LOCATION permission, and on Android 10+ — ACCESS_BACKGROUND_LOCATION. The latter is a separate request; the user must explicitly choose "Allow all the time" in settings.

https://developer.apple.com/documentation/usernotifications/handling_notifications_and_notification-related_actions