Push Notification: registration, receipt, and a client-triggered send
Messaging and Player-to-Player Events. Both reach a player who has the app open or checks it later. Push Notification is the one mechanism aimed at a player who currently has neither.
brainCloud supports push notifications across iOS, Android, and Facebook, with advanced features including Localization, Segments, Promotions, Scheduled sends, and Groups. Two reference apps, each real on its own platform, cover the actual client-side work: iOS via Basic Example (repositories/swift-examples/Basic Example), and Android via ConcentrationGame (repositories/java-examples/ConcentrationGame). Getting a device token in the first place is platform-native work brainCloud has no part in, APNs on iOS, Firebase Cloud Messaging on Android, but handing that token to brainCloud is one call either way, RegisterPushNotificationDeviceToken. ConcentrationGame goes further and shows the receiving side too: a real FirebaseMessagingService override that turns an incoming push into an actual on-screen Android notification.
How it works
- iOS asks the OS for permission and a token first. UIApplication.shared. registerForRemoteNotifications() is native iOS API; brainCloud has no part in it. It triggers the OS permission prompt, and didRegisterForRemoteNotificationsWithDeviceToken delivers the raw APNs token once granted.
- Android's token comes from Firebase instead, and arrives asynchronously. FirebaseMessaging.getInstance().getToken() returns a task; the token isn't available until that task's completion listener fires, not immediately after the call.
- Hand the token to brainCloud once you have it, with a platform argument on Android. iOS calls pushNotificationService.registerDeviceToken(PlatformObjc.iOS(), token, ...). Android calls getPushNotificationService().registerPushNotificationToken( Platform.GooglePlayAndroid, token, ...), an explicit platform argument iOS's call doesn't take.
- Receiving is a platform-native override, not a brainCloud callback, and ConcentrationGame actually implements it. MyFirebaseMessagingService. onMessageReceived(RemoteMessage) reads the payload and builds a real Android Notification to display it. brainCloud's job ends at delivering the push to FCM/APNs; turning it into something the user sees on screen is the app's job, and this is what that looks like done for real.
- A client can trigger its own test push. Basic Example wires sendSimplePushNotification to a UI button, sending a push to the logged-in profile on demand. Real production sends normally go through the portal or S2S (Localization, Segments, Promotions, Scheduled, Groups, all outside client code), but the client-callable send exists and is real here, useful for exactly this kind of manual testing.
Code
UIApplication.shared.registerForRemoteNotifications()
// ...
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
AppDelegate.pushToken = deviceToken.base64EncodedString()
print("pushToken:\((AppDelegate.pushToken ?? ""))")
}@IBAction func onRegisterPushNotificationsClicked(_ sender: Any) {
AppDelegate._bc.pushNotificationService.registerDeviceToken(
PlatformObjc.iOS(),
deviceToken: AppDelegate.pushToken,
completionBlock: onPushNotificationSuccess,
errorCompletionBlock: nil,
cbObject: nil)
}
@IBAction func onDeregisterPushNotificationsClicked(_ sender: Any) {
AppDelegate._bc.pushNotificationService.deregisterAllPushNotificationDeviceTokens(
onPushNotificationSuccess,
errorCompletionBlock: nil,
cbObject: nil)
}
@IBAction func onSendPushNotificationsClicked(_ sender: Any) {
AppDelegate._bc.pushNotificationService.sendSimplePushNotification(
AppDelegate._bc.getBCClient()?.authenticationService.profileID,
message: "Message_" + String(describing: arc4random_uniform(2000)),
completionBlock: onPushNotificationSuccess,
errorCompletionBlock: nil,
cbObject: nil)
}//this is the new way to get the firebase token.
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> {
if (!task.isSuccessful()) {
Log.w("NEW_TOKEN", "getInstanceId failed", task.getException());
return;
}
// Get new Instance ID token
String token = task.getResult();
Log.i("NEW_TOKEN", token);
brainCloudManager.getBrainCloudWrapper().getPushNotificationService().registerPushNotificationToken(Platform.GooglePlayAndroid, token, theCallback);
});@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
// Used for displaying old school GCM messages
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
NotificationManagerCompat manager = NotificationManagerCompat.from(this);
Notification notification = new NotificationCompat.Builder(this, "Messages")
.setContentText(remoteMessage.getData().get("message"))
.setContentTitle(remoteMessage.getData().get("title"))
.setSmallIcon(R.drawable.ic_launcher_background)
.build();
manager.notify(0, notification);
}
}Gotchas worth knowing up front
- The registration call's shape differs by platform, and it's not just the platform argument. iOS's registerDeviceToken takes a PlatformObjc.iOS() constant. Android's registerPushNotificationToken takes Platform.GooglePlayAndroid plus a token that only exists after an async Firebase callback fires, not synchronously after the call that requests it. Porting one platform's registration call to the other by pattern-matching the arguments will not compile, let alone work.
- A Firebase token isn't available until its completion listener fires. Calling registerPushNotificationToken before FirebaseMessaging.getInstance().getToken()'s listener has run has nothing to register yet. ConcentrationGame nests the registration call inside that listener specifically to avoid this.
- Turning a received push into something visible is entirely the app's responsibility. brainCloud and FCM/APNs's job ends at delivering the payload to the OS layer. onMessageReceived building and posting an Android Notification by hand, reading title/message straight out of the raw data payload, is what that responsibility looks like; nothing does this automatically.
- sendSimplePushNotification being client-callable doesn't mean production sends should go through it. It's real and useful for manual testing, exactly what Basic Example uses it for, but brainCloud's Localization, Segments, Promotions, Scheduled, and Groups push features (portal/S2S concerns) are the tools for anything beyond a developer triggering their own test notification.