Creating a simple todo app in Android Part III: Notification Bubbles

Maxime Dupierreux
ProAndroidDev
Published in
3 min readApr 12, 2019

--

This story concludes a series of threededicated to the development of a Todo Android app.

The main idea of this series was to achieve what we’re going to do in this last part : use the all-new notification Bubbles functionality introduced in Android Q Beta 2.

What’s a Bubble ?

Bubbles help users prioritize information and take action deep within another app, while maintaining their current context. They also let users carry an app’s functionality around with them as they move between activities on their device.

This is the definition from Google. Bubbles looks like the chats heads Facebook Messenger had for years but this time integrated directly into Android.

Implementing Bubbles in the App

I’ve mostly used the example provided by Google here.

We’re going to use the class NotificationHelper from Google’s sample.

First, Bubbles use notification channels juste like any other notification, so we must create the correct channels for our app:

fun setUpNotificationChannels() {
if (notificationManager.getNotificationChannel(CHANNEL_TODOS) == null) {
notificationManager.createNotificationChannel(
NotificationChannel(
CHANNEL_TODOS,
context.getString(R.string.channel_todos),
// The importance must be IMPORTANCE_HIGH to show Bubbles.
NotificationManager.IMPORTANCE_HIGH
).apply {
description = context.getString(R.string.channel_todos_description)
}
)
}
}

Here, we just create one channel with NotificationManager.IMPORTANCE_HIGH since it’s needed to show Bubbles.

Next, we create a showNotification function in which we’re going to create our Bubble using Notification.Builder and using its new setBubbleMetadata() method. We’ll pass to that method a BubbleMetadata object created with the provided builder.

This is the complete method :

fun showNotification(fromUser : Boolean) {

val builder = Notification.Builder(context, CHANNEL_TODOS)
.setBubbleMetadata(
Notification.BubbleMetadata.Builder()
.setDesiredHeight(context.resources.getDimensionPixelSize(R.dimen.bubble_height))
.setIcon(Icon.createWithResource(context,R.drawable.ic_file_black_24dp))
.apply {
// TODO: This does not yet work in Android Q Beta 2.
if (fromUser) {
setAutoExpandBubble(true)
setSuppressInitialNotification(true)
}
}
.setIntent(
PendingIntent.getActivity(
context,
REQUEST_BUBBLE,
Intent(context, MainActivity::class.java)
.setAction(Intent.ACTION_VIEW),
PendingIntent.FLAG_UPDATE_CURRENT
)
)
.build()
)
.setContentTitle("Todo")
.setSmallIcon(R.drawable.ic_file_black_24dp)
.setCategory(Notification.CATEGORY_STATUS)
.setShowWhen(true)
notificationManager.notify(0, builder.build())
}

Things to notice here are:

  • The .setIntent() method to which we pass the activity we want the Bubble to show.
  • In addition to what .setBubbleMetadata() we’re also calling other methods from the builder. In fact in case bubbles are not available, a classic definition will be shown to the user.
  • Some methods are not yet working (at the time of Android Q Beta 2). For example .setIcon() and .setAutoExpandBubble(). There’s also a .setSuppressInitialNotification() method but it’s not yet working either. It will allow you to suppress the classic notification.

We then create a canBubble() method, it will check if our Bubbles are allowed to be displayed.

fun canBubble(): Boolean {
val channel = notificationManager.getNotificationChannel(CHANNEL_TODOS)
return notificationManager.areBubblesAllowed() && channel.canBubble()
}

That’s it for the NotificationHelper class. Now we’re going to make some little changes to our ViewModel, the Activity and the AndroidManifest of the app.

Changes to the AndroidManifest

This is the additional tags needed in the manifest:

android:allowEmbedded="true"
android:documentLaunchMode="always"
android:resizeableActivity="true"

Note: android:documentLaunchMode=”always” is needed if you want your app to display multiple Bubbles (a chat app for example).

Changes to the TodoViewModel

In the ViewModel, we create a new function called showBubble(), it will check if we can display a bubble and display it.

fun showBubble() = scope.launch (Dispatchers.Default){

if(notificationHelper.canBubble()){
notificationHelper.showNotification(false)
}
}

We’re also adding a line calling the setUpNotificationChannels() method from the NotificationHelper into the init block of the ViewModel :

notificationHelper.setUpNotificationChannels()

Changes to the Activity

In the activity, we’ll simply call the showBubble() method from the ViewModel.

todoViewModel.showBubble()

And this is it, we now have a todo app with our… todos always one touch away with the help of Bubbles.

The Todo Bubble

I hope you enjoyed reading this series as much as I enjoyed writing it, if you have questions, you’re free to ask.

Here are some useful links :

--

--