Notifications are a crucial part of the mobile app experience. While one can debate about their harmful effects on cognitive overload and associated dopamine triggers in this attention economy, notifications nevertheless play an intrinsic role in messaging apps such as Status because how else will users know when they have received messages.
So it's no surprise that this has been one of the most anticipated features in Status app. Version 1.4 of Status app brings notification support on Android.
Until now, Status app users would receive no indication when messages were sent to them. If they happened to be using the app when someone sent them a message they would receive it. If not, such messages would propagate among Status peer nodes for a little while, until their Time-to-Live (TTL) expires which is currently set to 15 seconds, and then get saved in the Status history nodes for up to 30 days.
History nodes save messages for users while they’re offline. These nodes can not know the content or recipient of messages and only have access to the message topic. (These concepts will be covered in a future article.)
If the intended recipients did not use Status app in the next 30 days, their messages (along with others) would be deleted from the history nodes and they would never receive them. This clearly would be a terrible user experience for a messaging app. The assumption is that most users would check their app for messages within a month. Even then, users would understandably want to read their messages in a timely manner.
The obvious solution would have been to use notifications to let recipients know that they’ve received a message on their Status app. But in today’s notification frameworks, this comes at the cost of privacy which is the core value proposition of the Status app and hence a point of zero compromise.
To highlight this aspect, this article gives an overview of how Status has worked around the lack of privacy with push notifications to implement privacy-preserving local notifications.
Notifications can be triggered either locally from within the app/device or they can be "pushed" to the app from associated servers, even when the app is not running. The latter category of notifications are called push notifications.
On Android, push notifications are sent using Google's Firebase Cloud Messaging (FCM) system. FCM push notifications work by using client app specific registration tokens along with FCM servers and push notification servers. The registration tokens are tracked by the push notification servers to send client app specific push notifications via the FCM servers. The push notification servers themselves might be operated by the client app service provider or a third-party provider.
As is apparent in the above architectural framework of push notifications, both FCM servers and push notification servers can associate and track notifications sent to specific devices. This framework is not designed for privacy. So how does Status app solve this problem?
Notifications in Status App
In Status app, only the intended message recipients know which messages are meant for them based on partitioned or negotiated topic (included in the message envelope) and the fact that they have the cryptographic keys to decrypt them.
None of the other nodes in the network, including the peer and history nodes, can know the specific recipient of message envelopes because of the privacy-centric design. These nodes simply keep relaying the received message envelopes to their peers until their TTL expires. Given this, they have no way of notifying the intended message recipient(s). Push notifications are therefore not possible with the current Status design.
To solve this, Status app v1.4 discards the notion of push notifications and instead implements a foreground service whose sole purpose is to allow the implementation of “local" notifications. Local notifications are generated by the Status app when it receives messages. But how can the Status app receive messages when it is not in the foreground? The answer lies in the concept of foreground service.
In Android, a foreground service is “a service that the user is actively aware of and isn't a candidate for the system to kill when low on memory. This service must provide a notification for the status bar which cannot be dismissed until the service is either stopped or removed from the foreground.”
Implementing a foreground service in the Status app prevents it from getting killed when in background. This means that even when a user has the Status app in the background, it continues to receive messages. And when messages are received by the app while in background, a notification is generated by the app to alert the user.
With this approach, there are no push notifications in Status app, but only local notifications which work without requiring the use of any device-specific tokens or servers keeping track of devices. This allows Status to implement a privacy-preserving message notification service for Android. A user has to opt-in to enable notifications.
The impact of this feature on battery usage was measured to be less than 1% in our experiments which should barely be noticeable by users.
In Status app implementation, events from status-go are handled by the handleSignal method of im.status.ethereum.module. Those signals are passed to the clojurescript part of the app. This is the current behavior when the app is in the foreground. To support local notifications, these signals are generated even when the app is in the background and then passed to NewMessageSignalHandler which takes care of managing the notifications.
Notifications are a separate process in Android. Interacting with a notification generates an Intent. To handle intents, NewMessageSignalHandler uses a BroadcastReceiver to update the state of local notifications when the user taps or dismisses a notification. If the user taps on a notification, BroadcastReceiver generates a new intent to open the app and uses universal links to take the user to the right place.
Currently, Status app v1.4 supports notifications only for 1-1 messages but not for private or public chats. Extending this to other message types is planned for a future release.
Notifications are a must-have feature for mobile apps, especially messaging apps. Android apps typically enable push notifications using centralised servers and device-specific tokens which are not privacy friendly.
With the latest v1.4 release, Status enables notifications which are generated locally on the device without requiring trusted third-party servers and device identifying tokens. This approach does not trade-off the core value proposition of privacy to get the desired benefits of notifications.
While this solves the problem of notifications on Android, the iOS platform does not support the technical building blocks required for this approach. The Status team is exploring different solutions for the iOS platform. We will keep you notified of the progress.
But until then, Status users on Android can enjoy the notifications from their Status network and never miss a message again. Ping!
(Thanks to Eric Dvorsak and Andrea Maria Piana for reviewing drafts of this article and providing helpful feedback. Thanks to Alex Howell for the thoughtful illustration.)