Google has launched the first developer preview of the next Android version, currently code-named Android O (Oreo maybe?). Some exciting features were released, and one of them is Notification Channels. In this tutorial, we'll explore this feature and build a simple app that demonstrates the functionalities it provides.
What Are Notification Channels?
Notification channels enable us app developers to group our notifications into groups—channels—with the user having the ability to modify notification settings for the entire channel at once. For example, for each channel, users can completely block all notifications, override the importance level, or allow a notification badge to be shown. This new feature helps in greatly improving the user experience of an app.
We're going to learn about this feature by building a simple application called "TutsplusAlerts" that will provide two notification channels: Android and iOS. The user will receive a notification from one of these separate channels whenever a new article is submitted.
1. Set Up the Android O SDK
To begin to use Android O APIs as of this writing, you will need to have the latest Android Studio 2.4 Canary installed on your computer.
Launch Android Studio 2.4 and open the SDK Manager by clicking Tools > Android > SDK Manager.
Then, in the SDK Platforms tab, check Show Package Details. Below Android O Preview, check the following: Android SDK Platform O and Google APIs Intel x86 Atom System Image (required only for the emulator).
Then switch to the SDK Tools tab, and select the following:
- Android SDK Build-Tools 26.0.0 (rc1 or higher)
- Android SDK Platform-Tools 26.0.0 (rc1 or higher)
- Android Emulator 26.0.0
- Support Repository
Click the OK button to download all of these components.
2. Create an Android Studio Project
In your Android Studio, create a new project named TutsplusAlerts with an empty activity called MainActivity
.
3. Update build.gradle
Go to your app module build.gradle file and update compileSdkVersion
, buildToolsVersion
and targetSdkVersion
and finally the Support Library version.
android { compileSdkVersion "android-O" buildToolsVersion "26.0.0-rc1" defaultConfig { applicationId "com.chikeandroid.tutsplusalerts" minSdkVersion 'O' targetSdkVersion 'O' versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } ... } dependencies { ... compile 'com.android.support:appcompat-v7:26.0.0-alpha1' ... }
Remember to sync your project after making these changes.
4. Create Notification Channels
Create a new class and name it NotificationUtils
, extending ContextWrapper
.
import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.content.ContextWrapper; import android.graphics.Color; public class NotificationUtils extends ContextWrapper { private NotificationManager mManager; public static final String ANDROID_CHANNEL_ID = "com.chikeandroid.tutsplustalerts.ANDROID"; public static final String IOS_CHANNEL_ID = "com.chikeandroid.tutsplustalerts.IOS"; public static final String ANDROID_CHANNEL_NAME = "ANDROID CHANNEL"; public static final String IOS_CHANNEL_NAME = "IOS CHANNEL"; public NotificationUtils(Context base) { super(base); createChannels(); } public void createChannels() { // create android channel NotificationChannel androidChannel = new NotificationChannel(ANDROID_CHANNEL_ID, ANDROID_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT); // Sets whether notifications posted to this channel should display notification lights androidChannel.enableLights(true); // Sets whether notification posted to this channel should vibrate. androidChannel.enableVibration(true); // Sets the notification light color for notifications posted to this channel androidChannel.setLightColor(Color.GREEN); // Sets whether notifications posted to this channel appear on the lockscreen or not androidChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); getManager().createNotificationChannel(androidChannel); // create ios channel NotificationChannel iosChannel = new NotificationChannel(IOS_CHANNEL_ID, IOS_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH); iosChannel.enableLights(true); iosChannel.enableVibration(true); iosChannel.setLightColor(Color.GRAY); iosChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); getManager().createNotificationChannel(iosChannel); } private NotificationManager getManager() { if (mManager == null) { mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); } return mManager; } }
In the code above, we created two instances of the NotificationChannel
, passing an id (which must be unique within your package), a channel name, and also an importance level in its constructor. For each notification channel, we applied characteristics such as sound, lights, vibration, and a notification to show on the lock screen. Finally, we got the NotificationManager
from the system and then registered the channel by calling the method createNotificationChannel()
, passing the channel we have created.
We can create multiple notification channels all at once with createNotificationChannels()
, passing a Java list of NotificationChannel
instances. You can get all notification channels for an app with getNotificationChannels()
and get a specific channel with getNotificationChannel()
, passing only the channel id as an argument.
Importance Levels
Starting from Android O, priority levels are deprecated for individual notifications. Instead, you set an importance level when creating a notification channel—ranging from NotificationManager.IMPORTANCE_NONE
to NotificationManager.IMPORTANCE_HIGH
. We'll set the Android channel to be IMPORTANCE_DEFAULT
, while that of the iOS channel will be IMPORTANCE_HIGH
.
The full list of importance options available are:
IMPORTANCE_MAX
: unusedIMPORTANCE_HIGH
: shows everywhere, makes noise and peeksIMPORTANCE_DEFAULT
: shows everywhere, makes noise, but does not visually intrudeIMPORTANCE_LOW
: shows everywhere, but is not intrusiveIMPORTANCE_MIN
: only shows in the shade, below the foldIMPORTANCE_NONE
: a notification with no importance; does not show in the shade
All notifications for a channel will be given the same importance level.
5. Create Notifications and Post to Channels
We are going to create two Notifications for each of our channels in the NotificationUtils
class we created. We specify which notification should be sent to a channel in the Notification.Builder
(Android API 25) constructor, where we pass it the channel id as the second argument.
// ... public Notification.Builder getAndroidChannelNotification(String title, String body) { return new Notification.Builder(getApplicationContext(), ANDROID_CHANNEL_ID) .setContentTitle(title) .setContentText(body) .setSmallIcon(android.R.drawable.stat_notify_more) .setAutoCancel(true); } public Notification.Builder getIosChannelNotification(String title, String body) { return new Notification.Builder(getApplicationContext(), IOS_CHANNEL_ID) .setContentTitle(title) .setContentText(body) .setSmallIcon(android.R.drawable.stat_notify_more) .setAutoCancel(true); } //...
Be aware that Notification.Builder()
also has a notification channel id setter method called setChannel(String channelId)
, so you can choose to set the notification channel id either in the constructor or using the setter method.
6. Create the XML Layout
Now that we have the setup for creating and posting to notification channels, let's create the XML layout interface for posting the message in our activity_main.xml.
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:layout_margin="16dp" tools:context="com.chikeandroid.tutsplusalerts.MainActivity"><LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"><TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Tuts+ Android Channel" android:layout_gravity="center_horizontal" android:textAppearance="@style/TextAppearance.AppCompat.Title"/><EditText android:id="@+id/et_android_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title"/><EditText android:id="@+id/et_android_author" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Author"/><Button android:id="@+id/btn_send_android" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Send"/></LinearLayout><LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginTop="20dp"><TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Tuts+ IOS Channel" android:layout_gravity="center_horizontal" android:textAppearance="@style/TextAppearance.AppCompat.Title"/><EditText android:id="@+id/et_ios_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" /><EditText android:id="@+id/et_ios_author" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Author"/><Button android:id="@+id/btn_send_ios" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Send"/></LinearLayout></LinearLayout>
7. Post Notifications to Channels
Posting to Android Channel
In this section, we are going to edit our MainActivity
so that we can get the title and author from the EditText
components and then send these to the Android channel. We get the Notification.Builder
for the Android channel we created in our NotificationUtils
, and then notify the NotificationManager
.
import android.app.Notification; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.EditText; public class MainActivity extends AppCompatActivity { private NotificationUtils mNotificationUtils; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mNotificationUtils = new NotificationUtils(this); final EditText editTextTitleAndroid = (EditText) findViewById(R.id.et_android_title); final EditText editTextAuthorAndroid = (EditText) findViewById(R.id.et_android_author); Button buttonAndroid = (Button) findViewById(R.id.btn_send_android); buttonAndroid.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String title = editTextTitleAndroid.getText().toString(); String author = editTextAuthorAndroid.getText().toString(); if(!TextUtils.isEmpty(title) && !TextUtils.isEmpty(author)) { Notification.Builder nb = mNotificationUtils. getAndroidChannelNotification(title, "By " + author); mNotificationUtils.getManager().notify(101, nb.build()); } } }); } }
At this point, run the app and enter a title and an author, and then click the send button to receive the notification immediately.
Posting to the iOS Channel
Here we would post to the iOS channel. We get the Notification.Builder
for the iOS channel we created in our NotificationUtils
and then call the notify()
method in the NotificationManager
.
@Override protected void onCreate(Bundle savedInstanceState) { // ... final EditText editTextTitleIos = (EditText) findViewById(R.id.et_ios_title); final EditText editTextAuthorIos = (EditText) findViewById(R.id.et_ios_author); Button buttonIos = (Button) findViewById(R.id.btn_send_ios); buttonIos.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String title = editTextTitleIos.getText().toString(); String author = editTextAuthorIos.getText().toString(); if(!TextUtils.isEmpty(title) && !TextUtils.isEmpty(author)) { Notification.Builder nb = mNotificationUtils .getIosChannelNotification(title, "By " + author); mNotificationUtils.getManager().notify(102, nb.build()); } } }); }
Run the app again and enter a title and an author, and then click the send button to receive the notification immediately.
8. Notification Channel Settings
As of this writing, you can't programmatically change the configuration of specific notification channel settings. Instead, the only option available is for the user to go to the notification settings screen for the app in the device settings. From there, the user can access the app notification settings to modify settings such as vibration, sound, etc. Users can navigate to the app notification settings in either of the following ways:
- Long pressing on the notification on the notification drawer (left image below).
- Settings> Apps & notifications> Notifications> then selecting the app (right image below).
You can also send the user right from your app to the channel notification settings. Let's see how we can do that for the Android channel. It's recommended that you do this in your app settings to make it easy for users to access these notification options.
Edit the XML Layout
Include another button that will send the user to the channel notification settings.
<!--...--><Button android:id="@+id/btn_android_notif_settings" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Notification Settings"/><!--...-->
Code the Intent
Here we create an intent and pass it a Settings action—ACTION_CHANNEL_NOTIFICATION_SETTINGS
(API 25)—and then add some extra values: the app package name and channel id. Finally, we start the settings activity with the intent.
// ... @Override protected void onCreate(Bundle savedInstanceState) { //... Button buttonAndroidNotifSettings = (Button) findViewById(R.id.btn_android_notif_settings); buttonAndroidNotifSettings.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent i = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS); i.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName()); i.putExtra(Settings.EXTRA_CHANNEL_ID, NotificationUtils.ANDROID_CHANNEL_ID); startActivity(i); } }); } //...
Run the app and click the notification settings for the Android channel.
In the channel notification settings, users can edit settings such as enabling vibrations, changing the importance, or showing a badge (if supported) for the channel.
If you want to take users to the general notification settings for your app, you can also do that with an Intent
:
Intent i = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS); i.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName()); startActivity(i);
9. Create Notification Groups
We can also group notification channels into groups so they can be managed together. This is useful for apps that support multiple user accounts. The same notification channels are available across the individual accounts. For example, a social networking app might include support for both personal and business user accounts. The code below shows you how to create a notification channel group:
String groupId = "group_id_101"; CharSequence groupName = "Channel Name"; NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.createNotificationChannelGroup(new NotificationChannelGroup(groupId, groupName));
We used the NotificationManager
createNotificationChannelGroup()
method, passing it an instance of NotificationChannelGroup
, which needs the group id and group name to create the instance.
Once that is done, we need to connect a notification channel to a group by using the NotificationChannel.setGroup()
method and passing it the group id. If you want to create multiple notification groups all at once, use createNotificationChannelGroups()
, passing it a Java list of NotificationChannelGroup
instances.
10. Delete a Notification Channel
Deleting a notification channel is easy if it is no longer needed. Just use the notification manager method deleteNotificationChannel()
and pass the channel id.
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.deleteNotificationChannel(IOS_CHANNEL_ID);
However, be aware that deleted channels remain visible in the notification settings so as to prevent spam.
Conclusion
In this tutorial, you learned about Notification Channels for Android O: what they are and how to create one, as well as how to post a notification to a channel, how to access a channel's notification settings, how to group notification channels, and how to delete a notification channel.
To learn more about Notification Channels, do refer to the official documentation. And in the meantime, check out some of our other courses and tutorials on Android app development!
- Android SDKQuick Tip: Create Autosizing Text With Android O
- Android SDKCode an Image Gallery Android App With Glide
- Android SDKHow to Make Calls and Use SMS in Android Apps
- Android SDKGet Started With RxJava 2 for Android