172

After upgrading my project to Android O

buildToolsVersion "26.0.1"

Lint in Android Studio is showing a deprecated warning for the follow notification builder method:

new NotificationCompat.Builder(context)

The problem is: Android Developers update their Documentation describing NotificationChannel to support notifications in Android O, and provide us with a snippet, yet with the same deprecated warning:

Notification notification = new Notification.Builder(MainActivity.this)
        .setContentTitle("New Message")
        .setContentText("You've received new messages.")
        .setSmallIcon(R.drawable.ic_notify_status)
        .setChannelId(CHANNEL_ID)
        .build();  

Notifications Overview

My question: Is there is any other solution for building notification, and still support Android O?

A solution I found is to pass the channel ID as a parameter in Notification.Builder constructor. But this solution is not exactly reusable.

new Notification.Builder(MainActivity.this, "channel_id")
Shree
  • 344
  • 2
  • 20
GuilhermeFGL
  • 2,660
  • 2
  • 11
  • 31
  • 5
    *But this solution is not exactly reusable.* how so? – Tim Aug 02 '17 at 13:45
  • 5
    NotificationCompat.Builder is deprecated not Notification.Builder. Notice the Compat part gone. Notification is their new class where they are streamlining everything – Kapil G Aug 02 '17 at 13:50
  • 2
    @kapsym it's the other way around actually. Notification.Builder is older – Tim Aug 02 '17 at 13:52
  • Plus i dont see it deprecated here https://developer.android.com/reference/android/support/v4/app/NotificationCompat.html. Maybe a bug in Lint – Kapil G Aug 02 '17 at 13:54
  • The channel id is passed at the constructor, or can be placed using `notificationBuild.setChannelId("channel_id")`. In my case this last solution is more reusabled as my `NotificationCompat.Builder` is reused in a couple methods, saving up parameters for icons, sounds and vibrates. – GuilhermeFGL Aug 02 '17 at 13:57
  • @kapsym that is my concern. The is no warning about this solution in Android Developer Documentation – GuilhermeFGL Aug 02 '17 at 13:59
  • The only thing they say is that if you want to use notifications in O and above, you can have to use the channels, otherwise you can use the old method. So maybe we would have to just place version check in code before building the right notification solution – Kapil G Aug 02 '17 at 14:01
  • Related post - [NotificationCompat.Builder doesn't accept 2nd argument](https://stackoverflow.com/q/50765964/465053) – RBT Sep 03 '18 at 04:43

9 Answers9

184

It is mentioned in the documentation that the builder method NotificationCompat.Builder(Context context) has been deprecated. And we have to use the constructor which has the channelId parameter:

NotificationCompat.Builder(Context context, String channelId)

NotificationCompat.Builder Documentation:

This constructor was deprecated in API level 26.0.0-beta1. use NotificationCompat.Builder(Context, String) instead. All posted Notifications must specify a NotificationChannel Id.

Notification.Builder Documentation:

This constructor was deprecated in API level 26. use Notification.Builder(Context, String) instead. All posted Notifications must specify a NotificationChannel Id.

If you want to reuse the builder setters, you can create the builder with the channelId, and pass that builder to a helper method and set your preferred settings in that method.

Aleksandar G
  • 963
  • 2
  • 19
  • 23
Bob
  • 11,833
  • 5
  • 30
  • 43
  • 4
    It seems they are contradicting themselves when posting the `Notification.Builder(context)` solution in the NotificationChannel session. But well, at least you found a post notifying this deprecating =) – GuilhermeFGL Aug 02 '17 at 16:00
  • 27
    What is the channelId can you please explain ? – Santanu Sur Jan 26 '18 at 08:39
  • 19
    what is channelId ? – RoundTwo Jan 30 '18 at 16:55
  • 3
    You can also still use `NotificationCompat.Builder(Context context)`, and then assign the channel like so: `builder.setChannelId(String channelId)` – deyanm Apr 30 '18 at 10:27
  • 43
    A channel Id can be any string , it is too big to discuss in comments, but it is used to separate your notifications into categories so that the user can disable what he thinks is not important to him rather than blocking all notifications from your app. – yehyatt May 15 '18 at 08:16
  • I was missing the `channelId` parameter. Thank you so much – viper Sep 14 '18 at 05:08
  • 1
    The channel related description can be found at https://developer.android.com/training/notify-user/channels – Samantha Nov 05 '19 at 02:55
  • Also, the new Notification related Anatomy can be found at https://developer.android.com/guide/topics/ui/notifiers/notifications.html#Templates – Samantha Nov 05 '19 at 03:07
  • @deyanm t's not OK to use the old constructor as of March 2021. Using the constructor with only a `Context` parameter sets up a `NotificationCompat.Builder` that uses an old version of `Notification.Builder` internally. If you then pass certain style objects to the `Builder`, you get crashes, because the styles derive from a mismatched support library. Please see https://stackoverflow.com/questions/44408000/android-notification-with-decoratedcustomviewstyle – Ari Lacenski Mar 18 '21 at 16:33
117

enter image description here

Here is working code for all android versions as of API LEVEL 26+ with backward compatibility.

 NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getContext(), "M_CH_ID");

        notificationBuilder.setAutoCancel(true)
                .setDefaults(Notification.DEFAULT_ALL)
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.drawable.ic_launcher)
                .setTicker("Hearty365")
                .setPriority(Notification.PRIORITY_MAX) // this is deprecated in API 26 but you can still use for below 26. check below update for 26 API
                .setContentTitle("Default notification")
                .setContentText("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
                .setContentInfo("Info");

NotificationManager notificationManager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, notificationBuilder.build());

UPDATE for API 26 to set Max priority

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    String NOTIFICATION_CHANNEL_ID = "my_channel_id_01";

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_MAX);

        // Configure the notification channel.
        notificationChannel.setDescription("Channel description");
        notificationChannel.enableLights(true);
        notificationChannel.setLightColor(Color.RED);
        notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
        notificationChannel.enableVibration(true);
        notificationManager.createNotificationChannel(notificationChannel);
    }


    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);

    notificationBuilder.setAutoCancel(true)
            .setDefaults(Notification.DEFAULT_ALL)
            .setWhen(System.currentTimeMillis())
            .setSmallIcon(R.drawable.ic_launcher)
            .setTicker("Hearty365")
       //     .setPriority(Notification.PRIORITY_MAX)
            .setContentTitle("Default notification")
            .setContentText("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
            .setContentInfo("Info");

    notificationManager.notify(/*notification id*/1, notificationBuilder.build());
Aks4125
  • 4,294
  • 4
  • 29
  • 45
  • How can you make the notification actually show on the screen in the app or if in another app? – BlueBoy Nov 19 '17 at 01:27
  • @BlueBoy i am not getting your question. could you please explain what exactly you need? – Aks4125 Nov 20 '17 at 04:20
  • @Aks4125 The notification doesn't slide down and show at the top of the screen. You hear a tone, and a tiny notification icon appears in the status bar - but nothing slides down and shows like if you got a txt message. – BlueBoy Nov 20 '17 at 20:26
  • @BlueBoy you need to set priority to HIGH for that behaviour. let me know if you need me to update this code. if you sneak around for high priority notification you will get your answer. – Aks4125 Dec 04 '17 at 05:10
  • 2
    @BlueBoy check updated answer. if you're not targeting 26 API then just use same code with `.setPriority(Notification.PRIORITY_MAX)` else use updated code for 26 API. ` – Aks4125 Dec 04 '17 at 08:03
  • What can I use in place of channel id? WIll any random string cause a problem? – sziraqui Dec 19 '17 at 17:23
  • @sziraqui there won't be any issue. – Aks4125 Jan 29 '18 at 04:30
  • @Aks4125 I tried the code after "UPDATE for API 26 to set Max priority" on device Google pixel android version 8.0 the app keeps crashing and hanged all phone! – MML Mar 28 '18 at 16:04
  • @MML I am using pixel 2 api 27 and working fine. I suggest you to ask a new question with your crash log and let's see what's the deal. – Aks4125 Mar 29 '18 at 04:21
  • IMPORTANCE_MAX is not allowed for services, use IMPORTANCE_HIGH – SanVed Jun 06 '18 at 11:20
  • is it work for Android 6.0 - Android 7.1.1 as well ? – Raju yourPepe Dec 10 '18 at 14:37
31

Call the 2-arg constructor: For compatibility with Android O, call support-v4 NotificationCompat.Builder(Context context, String channelId). When running on Android N or earlier, the channelId will be ignored. When running on Android O, also create a NotificationChannel with the same channelId.

Out of date sample code: The sample code on several JavaDoc pages such as Notification.Builder calling new Notification.Builder(mContext) is out of date.

Deprecated constructors: Notification.Builder(Context context) and v4 NotificationCompat.Builder(Context context) are deprecated in favor of Notification[Compat].Builder(Context context, String channelId). (See Notification.Builder(android.content.Context) and v4 NotificationCompat.Builder(Context context).)

Deprecated class: The entire class v7 NotificationCompat.Builder is deprecated. (See v7 NotificationCompat.Builder.) Previously, v7 NotificationCompat.Builder was needed to support NotificationCompat.MediaStyle. In Android O, there's a v4 NotificationCompat.MediaStyle in the media-compat library's android.support.v4.media package. Use that one if you need MediaStyle.

API 14+: In Support Library from 26.0.0 and higher, the support-v4 and support-v7 packages both support a minimum API level of 14. The v# names are historical.

See Recent Support Library Revisions.

Jerry101
  • 8,582
  • 2
  • 32
  • 48
24

Instead of checking for Build.VERSION.SDK_INT >= Build.VERSION_CODES.O as many answers suggest, there is a slightly simpler way -

Add the following line to the application section of AndroidManifest.xml file as explained in the Set Up a Firebase Cloud Messaging Client App on Android doc:

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id" 
        android:value="@string/default_notification_channel_id" />

Then add a line with a channel name to the values/strings.xml file:

<string name="default_notification_channel_id">default</string>

After that you will be able to use the new version of NotificationCompat.Builder constructor with 2 parameters (since the old constructor with 1 parameter has been deprecated in Android Oreo):

private void sendNotification(String title, String body) {
    Intent i = new Intent(this, MainActivity.class);
    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pi = PendingIntent.getActivity(this,
            0 /* Request code */,
            i,
            PendingIntent.FLAG_ONE_SHOT);

    Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, 
        getString(R.string.default_notification_channel_id))
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(title)
            .setContentText(body)
            .setAutoCancel(true)
            .setSound(sound)
            .setContentIntent(pi);

    NotificationManager manager = 
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    manager.notify(0, builder.build());
}
Alexander Farber
  • 18,345
  • 68
  • 208
  • 375
  • 1
    how is this simpler? :S – Nactus Jan 20 '19 at 01:57
  • I HATE the SDK version conditional statements. So I want to try this 'https://developer.android.google.cn/reference/androidx/core/app/NotificationChannelCompat.Builder', but I can not import it. How to resolve? Thank you. – Prog Quester Sep 04 '20 at 01:30
19

Here is the sample code, which is working in Android Oreo and less than Oreo.

  NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationCompat.Builder builder = null;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                int importance = NotificationManager.IMPORTANCE_DEFAULT;
                NotificationChannel notificationChannel = new NotificationChannel("ID", "Name", importance);
                notificationManager.createNotificationChannel(notificationChannel);
                builder = new NotificationCompat.Builder(getApplicationContext(), notificationChannel.getId());
            } else {
                builder = new NotificationCompat.Builder(getApplicationContext());
            }

            builder = builder
                    .setSmallIcon(R.drawable.ic_notification_icon)
                    .setColor(ContextCompat.getColor(context, R.color.color))
                    .setContentTitle(context.getString(R.string.getTitel))
                    .setTicker(context.getString(R.string.text))
                    .setContentText(message)
                    .setDefaults(Notification.DEFAULT_ALL)
                    .setAutoCancel(true);
            notificationManager.notify(requestCode, builder.build());
Arpit
  • 1,089
  • 10
  • 21
  • NotificationCompat is used to resolve the compatible problem. But your solution still use SDK version conditional statement. I guess maybe there is a better solution. – Prog Quester Sep 04 '20 at 01:32
  • This method worked for me, (using Xamarin), whereas Alexander Farber's didn't: that worked on Nougat but not on Oreo – quilkin Nov 22 '20 at 13:27
8

Simple Sample

    public void showNotification (String from, String notification, Intent intent) {
        PendingIntent pendingIntent = PendingIntent.getActivity(
                context,
                Notification_ID,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT
        );


        String NOTIFICATION_CHANNEL_ID = "my_channel_id_01";
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_DEFAULT);

            // Configure the notification channel.
            notificationChannel.setDescription("Channel description");
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.RED);
            notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
            notificationChannel.enableVibration(true);
            notificationManager.createNotificationChannel(notificationChannel);
        }


        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
        Notification mNotification = builder
                .setContentTitle(from)
                .setContentText(notification)

//                .setTicker("Hearty365")
//                .setContentInfo("Info")
                //     .setPriority(Notification.PRIORITY_MAX)

                .setContentIntent(pendingIntent)

                .setAutoCancel(true)
//                .setDefaults(Notification.DEFAULT_ALL)
//                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher))
                .build();

        notificationManager.notify(/*notification id*/Notification_ID, mNotification);

    }
Community
  • 1
  • 1
Mehul
  • 2,500
  • 18
  • 30
4
Notification notification = new Notification.Builder(MainActivity.this)
        .setContentTitle("New Message")
        .setContentText("You've received new messages.")
        .setSmallIcon(R.drawable.ic_notify_status)
        .setChannelId(CHANNEL_ID)
        .build();  

Right code will be :

Notification.Builder notification=new Notification.Builder(this)

with dependency 26.0.1 and new updated dependencies such as 28.0.0.

Some users use this code in the form of this :

Notification notification=new NotificationCompat.Builder(this)//this is also wrong code.

So Logic is that which Method you will declare or initilize then the same methode on Right side will be use for Allocation. if in Leftside of = you will use some method then the same method will be use in right side of = for Allocation with new.

Try this code...It will sure work

Tim Diekmann
  • 5,740
  • 9
  • 30
  • 53
Pradeep Sheoran
  • 367
  • 5
  • 13
2
  1. Need to declare a Notification channel with Notification_Channel_ID
  2. Build notification with that channel ID. For example,

...
 public static final String NOTIFICATION_CHANNEL_ID = MyLocationService.class.getSimpleName();
...
...
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
                NOTIFICATION_CHANNEL_ID+"_name",
                NotificationManager.IMPORTANCE_HIGH);

NotificationManager notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

notifManager.createNotificationChannel(channel);


NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setContentTitle(getString(R.string.app_name))
                .setContentText(getString(R.string.notification_text))
                .setOngoing(true)
                .setContentIntent(broadcastIntent)
                .setSmallIcon(R.drawable.ic_tracker)
                .setPriority(PRIORITY_HIGH)
                .setCategory(Notification.CATEGORY_SERVICE);

        startForeground(1, builder.build());
...

Zaman
  • 141
  • 1
  • 3
1

This constructor was deprecated in API level 26.1.0. use NotificationCompat.Builder(Context, String) instead. All posted Notifications must specify a NotificationChannel Id.

Sandeep Singh
  • 852
  • 1
  • 9
  • 21