在Android O中,NotificationCompat.Builder已被弃用。

186

升级我的项目到Android O

buildToolsVersion "26.0.1"

Android Studio的Lint工具在以下通知构建器方法中显示已弃用警告:

new NotificationCompat.Builder(context)

问题是:Android开发者更新了他们的文档,描述NotificationChannel支持在Android O中的通知,并提供了一小段代码片段,但仍带有相同的弃用警告:

Translated:

问题是: Android开发者更新了文档,描述NotificationChannel支持在Android O上通知,并提供一段示例代码,但仍带有相同的废弃警告:

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();  

通知概述

我的问题:除了在Android O上使用的通知渠道之外,还有其他构建通知的解决方案吗?

我发现的一种解决方案是在Notification.Builder构造函数中将渠道ID作为参数传递。但这个解决方案并不能完全重用。

new Notification.Builder(MainActivity.this, "channel_id")

5
这个解决方案并不完全可复用。为什么? - Tim
5
NotificationCompat.Builder已经被弃用,而不是Notification.Builder。请注意Compat部分已经被删除。Notification是他们新的类,他们正在优化整个流程。 - Kapil G
2
@kapsym 实际上是相反的。Notification.Builder 更早。 - Tim
另外我在这里没有看到它被弃用的信息 https://developer.android.com/reference/android/support/v4/app/NotificationCompat.html。可能是 Lint 的一个 bug。 - Kapil G
频道ID可以在构造函数中传递,或者可以使用notificationBuild.setChannelId("channel_id")进行设置。在我的情况下,这个最后的解决方案更具可重用性,因为我的NotificationCompat.Builder在几个方法中被重复使用,节省了图标、声音和振动参数。 - GuilhermeFGL
显示剩余3条评论
10个回答

200

文档中提到,构建器方法NotificationCompat.Builder(Context context)已被弃用。我们必须使用具有channelId参数的构造函数:

在文档中提到,NotificationCompat.Builder(Context context)这个构建器方法已经被废弃了。现在我们需要使用带有channelId参数的构造函数来替代它:

(Two versions provided, please choose the one that fits your needs.)
NotificationCompat.Builder(Context context, String channelId)

NotificationCompat.Builder文档:

此构造函数在API级别26.0.0-beta1中已弃用。请改用 NotificationCompat.Builder(Context, String)。所有发布的 通知都必须指定NotificationChannel Id。

Notification.Builder文档:

此构造函数在API级别26中已弃用。请改用 Notification.Builder(Context, String)。所有发布的 通知都必须指定NotificationChannel Id。

如果您想重复使用builder设置,可以使用channelId创建builder,并将该builder传递给辅助方法,在该方法中设置首选设置。


4
在NotificationChannel会话中发布了Notification.Builder(context)解决方案时,它们似乎自相矛盾。但是,至少你找到了一篇通知这个过时问题的帖子。 - GuilhermeFGL
28
什么是频道ID?能否请您解释一下? - Santanu Sur
20
"channelId"是什么意思?(翻译) - RoundTwo
3
дҪ д»Қ然еҸҜд»ҘдҪҝз”ЁNotificationCompat.Builder(Context context)пјҢ然еҗҺеғҸиҝҷж ·еҲҶй…ҚйҖҡйҒ“пјҡbuilder.setChannelId(String channelId)гҖӮ - deyanm
46
一个频道ID可以是任何字符串,它太大了无法在评论中讨论,但它用于将您的通知分成类别,以便用户可以禁用他认为不重要的内容,而不是阻止来自您的应用的所有通知。 - yehyatt
显示剩余4条评论

121

enter image description here

这里是适用于所有安卓版本(API LEVEL 26+)的工作代码,具备向后兼容性。

 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());

更新API 26以设置最大优先级

    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());

@BlueBoy,你需要将优先级设置为HIGH以实现该行为。如果需要我更新这段代码,请告诉我。如果你想要高优先级通知,可以试着绕过去获取答案。 - Aks4125
2
@BlueBoy,请检查更新后的答案。如果您不针对26 API,则只需使用相同的代码.setPriority(Notification.PRIORITY_MAX),否则请使用更新后的26 API代码。 - Aks4125
@sziraqui,不会有任何问题。 - Aks4125
不允许在服务中使用 IMPORTANCE_MAX,请使用 IMPORTANCE_HIGH。 - Sanved
太棒了,但不要忘记添加Intent intent = new Intent(this, MainActivity.class);PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);notification.setContentIntent(pendingIntent); - Raj Kanchan
显示剩余7条评论

32

调用2个参数的构造函数:为了兼容Android O,在调用support-v4的NotificationCompat.Builder(Context context, String channelId)时传入ContextchannelId。在Android N或更早版本上运行时,channelId将被忽略。在Android O上运行时,还需创建一个与该channelId相同的NotificationChannel

过时的示例代码:在多个JavaDoc页面如Notification.Builder所示,调用new Notification.Builder(mContext)的示例代码已过时。

弃用的构造函数:Notification.Builder(Context context)v4 NotificationCompat.Builder(Context context)已被弃用,推荐使用Notification[Compat].Builder(Context context, String channelId)。(请参见Notification.Builder(android.content.Context)和v4 NotificationCompat.Builder(Context context))。

弃用的类:整个v7 NotificationCompat.Builder类已被弃用。(请参见v7 NotificationCompat.Builder。)之前,需要使用v7 NotificationCompat.Builder来支持NotificationCompat.MediaStyle。在Android O上,位于media-compat库android.support.v4.media包中有一个v4 NotificationCompat.MediaStyle。如果需要MediaStyle,请使用它。

API 14+:从版本号为26.0.0及以上的支持库开始,support-v4和support-v7包均支持最低API级别14。v#名称是历史遗留而已。

请参阅最近的支持库修订版


25

与许多答案建议的检查Build.VERSION.SDK_INT >= Build.VERSION_CODES.O不同,有一种略微更简单的方法 -

将以下行添加到AndroidManifest.xml文件的application部分中,如在 Android 上设置 Firebase 云消息传递客户端应用程序 文档中所述:

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

然后在 values/strings.xml 文件中添加一行频道名称:

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

此后,您将能够使用具有2个参数的新版本NotificationCompat.Builder构造函数(自Android Oreo以来,旧的具有1个参数的构造函数已被弃用):

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());
}

1
这个更简单?:S - Nactus

21

这是示例代码,在Android 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());

NotificationCompat 用于解决兼容性问题。但是你的解决方案仍然使用 SDK 版本条件语句。我猜可能有更好的解决方案。 - progquester
这种方法对我很有效(使用Xamarin),而Alexander Farber的方法则不行:它在Nougat上可以,但在Oreo上不行。 - quilkin

8

简单示例

    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);

    }

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();  

正确的代码应该是:

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

使用依赖版本为26.0.1,以及更新的依赖版本如28.0.0。

有些用户会用以下形式的代码:

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

因此,逻辑就是你将要声明或初始化的方法,然后在右侧使用相同的方法进行分配。如果在=的左侧使用了某个方法,则在=的右侧使用相同的方法进行新的分配。

尝试这段代码...它一定会起作用


2
  1. 需要使用 Notification_Channel_ID 声明通知渠道。
  2. 使用该渠道 ID 构建通知。例如:

...
 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());
...


1

我编写了这段代码,可以让您在 Android API 等级 < 26 或 API 等级 >= 26 上显示通知。

  private void showNotifcation(String title, String body) {
        //Este método muestra notificaciones compatibles con Android Api Level < 26 o >=26
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //Mostrar notificacion en Android Api level >=26
            final String CHANNEL_ID = "HEADS_UP_NOTIFICATIONS";
            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID,
                    "MyNotification",
                    NotificationManager.IMPORTANCE_HIGH);

            getSystemService(NotificationManager.class).createNotificationChannel(channel);
            Notification.Builder notification = new Notification.Builder(this, CHANNEL_ID)
                    .setContentTitle(title)
                    .setContentText(body)
                    .setSmallIcon(R.drawable.ic_launcher_background)
                    .setAutoCancel(true);
            NotificationManagerCompat.from(this).notify(1, notification.build());

        }else{
            //Mostrar notificación para Android Api Level Menor a 26
            String NOTIFICATION_CHANNEL_ID = "my_channel_id_01";
            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                    .setContentTitle(title)
                    .setContentText(body)
                    .setSmallIcon(R.drawable.ic_launcher_background)
                    .setAutoCancel(true);

            NotificationManager notificationManager =
                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.notify(/*notification id*/1, notificationBuilder.build());

        }

    }

干杯!


1
这个构造函数在API 26.1.0级别已经被弃用。 请使用NotificationCompat.Builder(Context, String)。所有发布的通知都必须指定一个NotificationChannel Id。

1
也许最好不要抄袭并将其作为答案发布,而是添加一个带有文档链接的评论。 - JacksOnF1re

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接