Push notifications
Push transport and notification rendering differ by platform:
Engage does not route its iOS pushes through FCM.
Permission, subscription, and token readiness
Three states are independent:
- System permission: Android/iOS permits notifications.
- Engage subscription: the installation has opted in through
Engage.push.optIn(). - Token registration: FCM or APNs issued a token and Engage synchronized it.
The host application owns the permission prompt and its explanation UI. Engage deliberately does not prompt the user.
private val permission = registerForActivityResult(
ActivityResultContracts.RequestPermission(),
) { granted ->
if (granted) lifecycleScope.launch { Engage.push.optIn() }
}
fun enablePush() {
if (Build.VERSION.SDK_INT >= 33) {
permission.launch(Manifest.permission.POST_NOTIFICATIONS)
} else {
lifecycleScope.launch { Engage.push.optIn() }
}
}Android notification appearance
Android small icons must be monochrome status-bar resources. Configure channels, icon, accent, and action categories before push processing begins:
Engage.start(
this,
EngageConfig(
appKey = BuildConfig.ENGAGE_APP_KEY,
push = PushConfig(
foregroundPresentation = ForegroundPresentation.SHOW,
android = AndroidPushConfig(
smallIcon = R.drawable.ic_stat_notification,
accentColor = R.color.notification_accent,
defaultChannelKey = "general",
channels = listOf(
AndroidPushChannel(
key = "general",
name = R.string.notification_channel_general,
description = R.string.notification_channel_general_description,
importance = NotificationImportance.HIGH,
),
),
),
),
),
)SHOW posts foreground notifications. SILENT still processes and records the delivery without foreground UI.
The Flutter configuration names Android resources because Dart cannot reference the host R class.
iOS APNs callbacks
Forward successful and failed APNs registration from UIApplicationDelegate as shown in the iOS guide. Configure APNs credentials in Engage, not Firebase.
For rich images, add a Notification Service Extension and link only EngagePushServiceExtension:
import EngagePushServiceExtension
final class NotificationService: EngageNotificationServiceExtension {}If attachment download fails, the original notification is still delivered.
Observe interaction events
Engage.push.events.collect { event ->
when (event) {
is PushEvent.Opened -> openDestination(event.deepLink)
is PushEvent.ActionSelected -> handleAction(event.actionKey, event.data)
else -> Unit
}
}Web URLs are opened by the native SDK. Deep links are surfaced to application navigation. Do not handle the same open in both native and Flutter layers.
Background and terminated applications
No SDK process stays alive permanently.
- Android creates the application before delivering FCM to the Engage service.
Engage.startinApplication.onCreaterestores the SDK and processes the message. - iOS/APNs displays eligible notifications while the app is terminated. Engage resumes analytics and action processing on launch or interaction through its buffering delegate.
- Network receipts and mutations are persisted and retried later. A killed process is not expected to complete arbitrary application networking in real time.
Avoid duplicate notifications
Do not register a second FirebaseMessagingService that independently posts Engage payloads. The Engage FCM module owns its service, deduplication, workers, open receiver, action receiver, and dismiss receiver. A host handler may process non-Engage messages, but it must route without displaying Engage messages again.