Many customers find it useful to show their users how many unread inbox messages they have from outside the app by using badging. Badging will add a small red circle with a white number to your app's icon.
You can achieve this with Localytics Inbox. Follow the steps for iOS and/or Android.
iOS
iOS makes it very simple to update the App’s badge with one API call:
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:badgeNumber];
At any point you may get the unread count of your Localytics Inbox messages with the following API:
NSInteger unreadCount = [Localytics inboxCampaignsUnreadCount];
Note: The above method should not be called from the main thread.
First, you must ensure that your app has requested permissions for application badging:
if ([UNUserNotificationCenter class]) { UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; UNAuthorizationOptions options = (UNAuthorizationOptionBadge); [center requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError * _Nullable error) { [Localytics didRequestUserNotificationAuthorizationWithOptions:options granted:granted]; }]; center.delegate = self; } else if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) { UIUserNotificationType types = (UIUserNotificationTypeBadge); UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil]; [application registerUserNotificationSettings:settings]; }
Next, to make sure this number is kept up to date, you should be sure to update it whenever the app is launched and when the unread count changes.
To update the count when your app is launched, add the following code to your
UIApplicationDelegate
application:didFinishLaunchingWithOptions:
method after calling integrate
:
[Localytics refreshInboxCampaigns:^(NSArray<LLInboxCampaign *> * _Nullable inboxCampaigns) { //This callback is always made on the main thread. NSInteger unreadCount = 0; for (LLInboxCampaign *campaign in inboxCampaigns) { if (!campaign.isRead) { unreadCount++; } } [[UIApplication sharedApplication] setApplicationIconBadgeNumber:unreadCount]; }];
For users with standard inbox integrations, this will mean overriding the LLInboxViewController
class and its tableView:didSelectRowAtIndexPath:
method as follows:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [super tableView:tableView didSelectRowAtIndexPath:indexPath]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // This Localytics API should not be called on the main thread. __block NSInteger unreadCount = [Localytics inboxCampaignsUnreadCount]; dispatch_async(dispatch_get_main_queue(), ^{ // UIApplication calls should only be made on the main thread. [[UIApplication sharedApplication] setApplicationIconBadgeNumber:unreadCount]; }); }); }
Additionally, for users with Push enabled, you may send a silent Push notification which will update the badge count when the app is in the background. To do so, ensure you have properly integrated Push messaging. Next, in your AppDelegate's
application:didReceiveRemoteNotification:fetchCompletionHandler:
, update the inbox badge number:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { [Localytics handleNotification:userInfo]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // This Localytics API should not be called on the main thread. __block NSInteger unreadCount = [Localytics inboxCampaignsUnreadCount]; dispatch_async(dispatch_get_main_queue(), ^{ // UIApplication calls should only be made on the main thread. [[UIApplication sharedApplication] setApplicationIconBadgeNumber:badgeNumber]; completionHandler(UIBackgroundFetchResultNoData); }); }); }
Android
While Android doesn’t have a perfect equivalent to badging on iOS, Android O introduced a similar feature which may be used in its place.
On Android, the badge is strictly a "notification dot," which when expanded via long press will show a number of notifications and some quick text.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { (NotificationManager) notificationManager; NotificationChannel channel = new NotificationChannel("badging-updates", "Miscellaneous", NotificationManager.IMPORTANCE_MIN); channel.setShowBadge(true); notificationManager.createNotificationChannel(channel); }
Because Android will always dismiss the notification dot when a notification is received, it doesn’t make sense to update a badge number when the app is open. Instead, we will only update the badge whenever any notification is received. Your app will have to handle it’s own push messages as a result. If your app does not have a custom push handler, please consult the dev docs. The following code assumes a Firebase integration and updates code in the FirebaseMessagingService#onMessageReceived
:
@Override public void onMessageReceived(final RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); Map<String, String> data = remoteMessage.getData(); Localytics.integrate(getApplicationContext()); Localytics.handleFirebaseMessage(data); Localytics.refreshInboxCampaigns(new InboxRefreshListener() { @Override public void localyticsRefreshedInboxCampaigns(List<InboxCampaign> campaigns) { int unreadCount = 0; for (InboxCampaign campaign : campaigns) { if (!campaign.isRead()) { unreadCount++; } } Notification notification = new Notification.Builder(MainApplication.this, "badging-count") .setNumber(unreadCount) .setSmallIcon(R.drawable.ic_launcher) .build(); //Generate a random notification ID. notificationManager.notify(1, notification); } }); }
Triggering push messages to update the badge
Finally, to actually trigger a silent push notification, you can use the Localytics dashboard to send a recurring push campaign with no content (no push title, subtitle, message body or rich attachment):
This will wake the app up and cause it to update the badge, but not present any notification to the user if the proper integration was followed.
Limitations
This solution will help you keep a relatively up to date badge number but it has some limitations:
- App badging is more "native" to iOS than Android.
- The app may only update the badge client-side. Localytics does not provide any server side API’s which would allow you to retrieve the Inbox unread count and update the badge number.
- The Localytics unread count may not be 100% up to date when called from a background state (in the case of silent Push). The returned number will only be indicative of campaigns currently downloaded to the device. This means that an Inbox message that was created between the last session and the current background update may not be reflected in the unread count.
- Users may turn off app badging in their settings.
- iOS Limitations
- Background updating of badge count will only succeed if the user has an up to date push token and the app is in a backgrounded (not terminated) state.
- The Badge count is not updated in real-time but is refreshed on application launch
- Silent push notifications are not guaranteed to wake the app up as the OS itself may choose to suppress them.
- Android Limitations
- This functionality is really designed for iOS, and Android doesn’t have a proper equivalent.
- Android’s pseudo equivalent is only Android O and up, which means a number of your users on older OS versions will not benefit from badging.
- The badging number is hidden by the OS.
- Notification badging can be turned off in the settings globally(not just on a per-app basis).