Android O中弃用了NotificationCompat.Builder


161

将项目升级到Android O之后

buildToolsVersion "26.0.1"

Android Studio中的Lint显示了以下通知构建器方法的不建议使用的警告:

new NotificationCompat.Builder(context)

问题是: 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吗?

我发现的解决方案是将通道ID作为Notification.Builder构造函数中的参数传递。但是此解决方案并非完全可重用。

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

4
但是此解决方案并非完全可重用。为何如此?
蒂姆(Tim)

5
不推荐使用NotificationCompat.Builder而不是Notification.Builder。注意Compat部分不见了。通知是他们的新课程,他们在简化所有内容
Kapil G

1
@kapsym实际上是另一种方式。Notification.Builder较旧
Tim的

另外我不明白在这里不推荐使用developer.android.com/reference/android/support/v4/app/...。也许皮棉错误
卡皮尔摹

通道ID在构造函数中传递,也可以使用放置notificationBuild.setChannelId("channel_id")。在我的情况下,由于NotificationCompat.Builder可以通过几种方法重用我的后一种解决方案,因此可以更重用,从而节省了图标,声音和振动的参数。
GuilhermeFGL

Answers:


167

在文档中提到,NotificationCompat.Builder(Context context)不建议使用builder方法。而且我们必须使用具有channelId参数的构造函数:

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。

如果要重用构建器设置器,则可以使用来创建构建器channelId,并将该构建器传递给辅助方法,然后在该方法中设置首选设置。


3
Notification.Builder(context)在NotificationChannel会话中发布解决方案时,似乎他们在矛盾自己。但是,至少您找到了一条通知此弃用=)的帖子
GuilhermeFGL,2017年

23
您能解释什么channelId?
Santanu Sur

15
什么是channelId?
RoundTwo

3
您也仍然可以使用NotificationCompat.Builder(Context context),然后像这样分配频道:builder.setChannelId(String channelId)
deyanm

36
频道ID可以是任何字符串,太大而无法在注释中讨论,但它用于将通知分为几类,以便用户可以禁用他认为对他不重要的内容,而不是阻止应用程序中的所有通知。
yehyatt

110

在此处输入图片说明

这是自API LEVEL 26+起具有向后兼容性的所有android版本的工作代码。

 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

@BlueBoy我没有收到您的问题。你能解释一下你到底需要什么吗?
Aks4125

@ Aks4125通知不会向下滑动并显示在屏幕顶部。您会听到一声提示音,状态栏中会出现一个很小的通知图标-但是没有任何滑动下来,并显示出是否收到txt消息。
BlueBoy

@BlueBoy您需要为此行为将优先级设置为HIGH。让我知道您是否需要我更新此代码。如果您潜入高优先级通知,您将得到答案。
Aks4125 '17

2
@BlueBoy检查更新的答案。如果您的目标不是26 API,则只需使用相同的代码即可,.setPriority(Notification.PRIORITY_MAX)否则请使用26 API的更新代码。`
Aks4125

31

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

过期示例代码:几个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上下文)。)

推荐使用的类:不推荐使用整个v7NotificationCompat.Builder。(请参阅v7 NotificationCompat.Builder。)以前,NotificationCompat.Builder需要v7 来支持NotificationCompat.MediaStyle。在Android的O,有一个V4 NotificationCompat.MediaStyle媒体COMPAT库android.support.v4.media包。如果需要,请使用那个MediaStyle

API 14+:在26.0.0及更高版本的Support Library中,support-v4和support-v7软件包均支持最低API级别14。v#名称是历史名称。

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


22

除了检查Build.VERSION.SDK_INT >= Build.VERSION_CODES.O尽可能多的答案以外,还有一种更简单的方法-

将以下行添加到AndroidManifest.xml文件的application部分中,如在Android文档上设置Firebase Cloud Messaging客户端应用中所述

    <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

17

这是示例代码,可在Android Oreo中使用,而不是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());

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.

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

试试这个代码...它肯定会工作


1

API级别26.1.0中不推荐使用此构造函数。使用NotificationCompat.Builder(Context,String)代替。所有发布的通知必须指定一个NotificationChannel ID。


也许宁愿添加带有文档链接的注释,而不是复制cat并作为答案发布。
JacksOnF1re

0
  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());
...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.