Skip to main content

Push notifications

Notify your users when other members interact with them in the community, open the right post or comment when they tap the notification, and show how many notifications they have not seen yet.

Android availableiOS availableFlutter availableReact Native availableUnity available

Before you begin​

  • Complete the Quickstart: the SDK is initialized and the community screen opens in your app.
  • Set up push notifications in your app: Firebase Cloud Messaging for Android builds, APNs for iOS builds.
  • Send Octopus the credentials that let its servers push to your app, through the secure form the Octopus team gives you:
BuildWhat to sendWhere to get it
AndroidThe private key file (JSON) of a Firebase service accountFirebase console, Settings > Service Accounts, Generate New Private Key. See Provide credentials manually.
iOSAn APNs authentication key (.p8), its key ID, your Bundle ID and your Team IDKeys page of the Apple Developer site: create a key with Apple Push Notifications service (APNs) enabled and the Sandbox & Production environment. The key ID is in the list of keys, the Bundle ID in your Xcode project, the Team ID in the Membership details card.

The table applies to every platform: a Flutter, React Native or Unity app sends the Android credentials for its Android build and the iOS credentials for its iOS build.

warning

The service account key is not the google-services.json file that configures Firebase in your app. Octopus needs the service account key.

How it works​

The SDK never asks for the notification permission: your app requests it where it makes sense in your flow. The SDK registers the token, recognizes its own notifications and opens the community on their content.

Your app ── (1) push token ───────────────────▶ Octopus backend
FCM token on Android │
APNs token on iOS │
(2) someone interacts with the user
│
┌────────────────────────────────────┴───────────────┐
▼ ▼
FCM, data-only message APNs message
│ │
▼ ▼
(3) Android: your app builds (3) iOS: the system shows
and shows the notification the notification
└────────────────────────┬───────────────────────────┘
▼
(4) the user taps it
│
▼
(5) your app checks that it is an Octopus notification
and hands it to the SDK, which opens the post or comment
StepAndroidiOS
TokenFCM registration tokenAPNs device token
DisplayYour app. Octopus sends data-only FCM messages, which neither the system nor Firebase displays, even in the background.The system displays the APNs notification.
TapYour app routes the tap to the SDK.Your app routes the tap to the SDK.

1. Register the push token​

Register the token after the SDK is initialized, then again each time it changes. In an iOS app, whatever the SDK, always register the APNs device token. Octopus sends iOS pushes through APNs with its own key, so an FCM token registered on iOS gives a successful call and no notification.

Declare the permission and your messaging service in AndroidManifest.xml:

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<application>
<service
android:name=".notifications.MessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>

Forward every new FCM token from the service:

class MessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
super.onNewToken(token)
OctopusSDK.registerNotificationsToken(token)
}
}

onNewToken only runs when Firebase issues a token. Register the current one at startup too, so a token issued before you integrated Octopus is registered, and request the permission on Android 13 and above:

class MainActivity : ComponentActivity() {
private val requestNotificationPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED
) {
requestNotificationPermission.launch(Manifest.permission.POST_NOTIFICATIONS)
}
FirebaseMessaging.getInstance().token.addOnSuccessListener { token ->
OctopusSDK.registerNotificationsToken(token)
}
}
}

2. Display the notification​

In an iOS app, the system displays the notification. In an Android app, whatever the SDK, your app builds and posts it from the data-only FCM message, in the foreground and in the background.

In your messaging service, parse the message with getOctopusNotification, which returns null for a message that is not from Octopus. setOctopusContent sets the title, the text and a tap intent that deep-links into the Octopus screens:

override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)

val octopusNotification = OctopusSDK.getOctopusNotification(data = remoteMessage.data)
if (octopusNotification != null) {
notificationManager.notify(
octopusNotification.id,
NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stat_notification)
.setAutoCancel(true)
.setOctopusContent(
context = this,
activityClass = MainActivity::class,
octopusNotification = octopusNotification
)
.build()
)
}
}

activityClass is the activity whose Compose content holds the octopusComposables() graph. To build the tap intent yourself, use the title, body and linkPath of the OctopusNotification.


3. Handle notification taps​

When the user taps a notification, check that it comes from Octopus, then hand it to the SDK. The SDK opens the community on the post, comment or reply the notification is about. No platform opens it in a modal bottom sheet; where it opens is set per platform below.

The destination opens in your own navigation graph, so you choose its container. The tap intent built by setOctopusContent launches activityClass with the notification's deep link as its data. Navigate to it:

intent.data?.let { uri -> navController.navigate(deepLink = uri) }

4. Show the not-seen count​

Show a badge with the number of notifications the user has not seen in the community, to bring them back to what is new. The SDK publishes the count and updates it when it changes; ask for a refresh from the server when you need the latest value, for example when your app comes to the foreground.

Collect OctopusSDK.notSeenNotificationsCount, a Flow<Int>. updateNotSeenNotificationsCount() is a suspend function that fetches the count and returns it as an OctopusResult<Int, Nothing>:

lifecycleScope.launch {
OctopusSDK.notSeenNotificationsCount.collect { count ->
// Update your badge
}
}

lifecycleScope.launch {
OctopusSDK.updateNotSeenNotificationsCount()
}

The Android sample app shows a full example.

Behavior and limits​

  • The SDK never requests the notification permission and never shows a prompt.
  • Octopus sends data-only FCM messages to Android apps: the notification shows only if your app posts it, in the foreground and in the background alike.
  • isOctopusNotification and getOctopusNotification accept both payload shapes: the flat FCM data map in an Android app and the APNs userInfo in an iOS app. Pass the payload as you receive it.

Troubleshooting​

SymptomCause and fix
The token registers on iOS but no notification arrivesAn FCM token was registered. Register the APNs device token (getAPNSToken() with Firebase).
No token on the iOS SimulatorThe Simulator never issues an APNs token; test token registration on a device. You can test the tap path on the Simulator with xcrun simctl push booted <bundleId> <payload.apns>.
No notification on Android, even in the backgroundOctopus messages are data-only: post the notification from your messaging service or background handler (step 2). Check also that the credentials you sent are a service account key, not google-services.json.
Unity, Android: the sample service never receives messagesThe manifest of the sample was not merged. Move OctopusPushSample.androidlib and OctopusMessagingService.java to Assets/Plugins/Android/.

Next steps​