java Android O - 通知渠道和 NotificationCompat

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/45015803/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 08:27:46  来源:igfitidea点击:

Android O - Notification Channels and NotificationCompat

javaandroid-notificationsandroid-support-libraryandroid-8.0-oreo

提问by Zordid

I cannot change this feeling: again, the Android developers came up with something new and leave everybody in the dark about how they would think the feature is used.

我无法改变这种感觉:再次,Android 开发人员提出了一些新的东西,让每个人都对他们认为该功能的使用方式一无所知。

I am talking about Notification Channels in Android O.

我说的是 Android O 中的通知通道。

For years I have been using the compatibility support libraries to avoid dealing with specific platform details. Namely: NotificationCompat.

多年来,我一直在使用兼容性支持库来避免处理特定平台的细节。即:NotificationCompat

Now, the Builderrequires me to supply a notification channel id, which is nice, but completely leaves me alone with creating such a channel. I cannot find any compat support for creating channels. Nor can I find a reasonable way to create them at the right point.

现在,这Builder要求我提供一个通知频道 id,这很好,但完全让我独自创建这样一个频道。我找不到任何用于创建频道的兼容支持。我也找不到合理的方法在正确的点创建它们。

The docs simply state that it should be done "somewhere" and "probably not when issuing a notification". But what exactly am I supposed to do? I hate writing version specific stuff for simple tasks - that's why I use the compat libraries.

文档只是声明它应该在“某处”完成并且“在发布通知时可能不是”。但我到底该怎么做?我讨厌为简单的任务编写特定于版本的东西 - 这就是我使用 compat 库的原因。

Does anybody have a suggestion on how to handle it? Is it "expensive" to do the creating each and every time when I want a notification to be displayed?

有人对如何处理它有任何建议吗?当我想要显示通知时,每次都进行创建是否“昂贵”?

回答by AlexPad

This is my solution to generate notifications on Android O and maintain backward compatibility:

这是我在 Android O 上生成通知并保持向后兼容性的解决方案:

        String idChannel = "my_channel_01";
        Intent mainIntent;

        mainIntent = new Intent(context, LauncherActivity.class);

        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, mainIntent, 0);

        NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        NotificationChannel mChannel = null;
        // The id of the channel.

        int importance = NotificationManager.IMPORTANCE_HIGH;

        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, null);
        builder.setContentTitle(context.getString(R.string.app_name))
                .setSmallIcon(getNotificationIcon())
                .setContentIntent(pendingIntent)
                .setContentText(context.getString(R.string.alarm_notification) + ManagementDate.getIstance().hourFormat.format(getAlarm(context, 0)));

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            mChannel = new NotificationChannel(idChannel, context.getString(R.string.app_name), importance);
            // Configure the notification channel.
            mChannel.setDescription(context.getString(R.string.alarm_notification));
            mChannel.enableLights(true);
            mChannel.setLightColor(Color.RED);
            mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
            mNotificationManager.createNotificationChannel(mChannel);
        } else {
            builder.setContentTitle(context.getString(R.string.app_name))
                    .setPriority(NotificationCompat.PRIORITY_HIGH)
                    .setColor(ContextCompat.getColor(context, R.color.transparent))
                    .setVibrate(new long[]{100, 250})
                    .setLights(Color.YELLOW, 500, 5000)
                    .setAutoCancel(true);
        }
        mNotificationManager.notify(1, builder.build());

回答by Milad Moosavi

It's not as expensive as you think! All you need to do is creating a notification channel and bind it to notification.

没你想的那么贵!您需要做的就是创建一个通知通道并将其绑定到通知。

You can solve this in two ways but for both of them you need to create a notification channel with a specific channel id.

您可以通过两种方式解决此问题,但对于这两种方式,您都需要创建一个具有特定频道 ID 的通知频道。

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String id = "my_channel_01";
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = new NotificationChannel(id, name,importance);
mChannel.enableLights(true);
mNotificationManager.createNotificationChannel(mChannel);

First way is to set channel for notification in constructor:

第一种方法是在构造函数中设置通知通道:

Notification notification = new Notification.Builder(MainActivity.this , id).setContentTitle("Title");
mNotificationManager.notify("your_notification_id", notification);

Second way is to set the channel by Notificiation.Builder.setChannelId()

第二种方式是通过 Notificiation.Builder.setChannelId() 设置通道

Notification notification = new Notification.Builder(MainActivity.this).setContentTitle("Title").
setChannelId(id);
mNotificationManager.notify("your_notification_id", notification);

Hope this helps

希望这可以帮助

回答by Teocci

If you want to support previous versions of Android (< Oreo). We may wrap the NotificationManagerto create and build Notification.Builderinstance in a NotificationHelperlike this:

如果您想支持以前版本的 Android (< Oreo)。我们可以像这样包装NotificationManager来创建和构建Notification.Builder实例NotificationHelper

/**
 * Helper class to manage notification channels, and create notifications.
 * <p>
 * Created by teocci.
 *
 * @author [email protected] on 2018-Oct-02
 */
public class NotificationHelper extends ContextWrapper
{
    public static final String NOTIFICATION_CHANNEL_PRIMARY = "notification_channel_primary";
    public static final int NOTIFICATION_ID_PRIMARY = 1100;

    private NotificationManager manager;

    /**
     * Registers notification channels, which can be used later by individual notifications.
     *
     * @param ctx The application context
     */
    public NotificationHelper(Context ctx)
    {
        super(ctx);

        // For API 26+ create notification channels
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_PRIMARY,
                    getString(R.string.channel_name),
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            channel.setLightColor(Color.BLUE);
            channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
            channel.setDescription(getString(R.string.channel_description));
            getManager().createNotificationChannel(channel);
        }
    }
    /**
     * Cancel a previously shown notification.  If it's transient, the view
     * will be hidden.  If it's persistent, it will be removed from the status
     * bar.
     *
     * @param id    The ID of the notification
     */
    public void remove(int id){
        manager.cancel(id);
    }

    /**
     * Get a notification of type 1
     * <p>
     * Provide the builder rather than the notification it's self as useful for making notification
     * changes.
     *
     * @return the builder as it keeps a reference to the notification (since API 24)
     */
    public Notification getNotification()
    {
        return getNotification(getTitle(), getBody()).build();
    }

    /**
     * Get a notification of type 1
     * <p>
     * Provide the builder rather than the notification it's self as useful for making notification
     * changes.
     *
     * @param title the title of the notification
     * @param body  the body text for the notification
     * @return the builder as it keeps a reference to the notification (since API 24)
     */
    public Notification.Builder getNotification(String title, String body)
    {
        Notification.Builder builder = new Notification.Builder(getApplicationContext())
                .setOngoing(true)  // Persistent notification!
                .setAutoCancel(true)
                .setTicker(title)
                .setContentTitle(title)
                .setContentText(body)
                .setSmallIcon(getSmallIcon());

        // Set the Channel ID for Android O.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            builder.setChannelId(NOTIFICATION_CHANNEL_PRIMARY); // Channel ID
        }

        return builder;
    }

    /**
     * Send a notification.
     *
     * @param id           The ID of the notification
     * @param notification The notification object
     */
    public void notify(int id, Notification.Builder notification)
    {
        getManager().notify(id, notification.build());
    }

    /**
     * Get the notification manager.
     * <p>
     * Utility method as this helper works with it a lot.
     *
     * @return The system service NotificationManager
     */
    private NotificationManager getManager()
    {
        if (manager == null) {
            manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        }

        return manager;
    }

    /**
     * Get the small icon for this app
     *
     * @return The small icon resource id
     */
    private int getSmallIcon()
    {
        return R.drawable.ic_smart_audio_noti_icon;
    }

    /**
     * Get the notification title for this app
     *
     * @return The notification title as string
     */
    private String getTitle()
    {
        return getString(R.string.notification_title);
    }

    /**
     * Get the notification content for this app
     *
     * @return The notification content as string
     */
    private String getBody()
    {
        return getString(R.string.notification_content);
    }
}

Then we can use it easily like this:

然后我们可以像这样轻松使用它:

@Override
public void onCreate()
{
    ...
    notificationHelper = new NotificationHelper(this);
    notificationHelper.notify(NotificationHelper.NOTIFICATION_ID_PRIMARY, "App is running");
    ...
}

@Override
public void onDestroy()
{
    notificationHelper.remove(NotificationHelper.NOTIFICATION_ID_PRIMARY)
}

回答by Elad Nava

Here is an alternative solution that uses reflectionto create the Notification Channel so you can set a compileSdkVersionof lower than 26.

这是使用反射创建通知通道的替代解决方案,因此您可以将 a 设置compileSdkVersion为小于 26。

   private void createNotificationChannel(NotificationManager notificationManager) {
        // Channel details
        String channelId = "myChannelId";
        String channelName = "Notifications";

        // Channel importance (3 means default importance)
        int channelImportance = 3;

        try {
            // Get NotificationChannel class via reflection (only available on devices running Android O or newer)
            Class notificationChannelClass = Class.forName("android.app.NotificationChannel");

            // Get NotificationChannel constructor
            Constructor<?> notificationChannelConstructor = notificationChannelClass.getDeclaredConstructor(String.class, CharSequence.class, int.class);

            // Instantiate new notification channel
            Object notificationChannel = notificationChannelConstructor.newInstance(channelId, channelName, channelImportance);

            // Get notification channel creation method via reflection
            Method createNotificationChannelMethod =  notificationManager.getClass().getDeclaredMethod("createNotificationChannel", notificationChannelClass);

            // Invoke method on NotificationManager, passing in the channel object
            createNotificationChannelMethod.invoke(notificationManager, notificationChannel);

            // Log success to console
            Log.d("MyApp", "Notification channel created successfully");
        }
        catch (Exception exc) {
            // Log exception to console
            Log.e("MyApp", "Creating notification channel failed", exc);
        }
    }

Then, when you're building your notifications, simply call the .setChannelId()method of NotificationCompat.Builder:

然后,当您构建通知时,只需调用以下.setChannelId()方法NotificationCompat.Builder

builder.setChannelId("myChannelId");

Note:You need to update your appcompat-v7library to version 26.x.xin build.gradle:

注意:您需要将更新appcompat-v7库版本26.x.xbuild.gradle

compile 'com.android.support:appcompat-v7:26.1.0'

回答by Khalid Ali

If your notification codehas the same structureevery time so you should create a static method and passall what you want and put the code which check the API Levelinside this method.

如果您的通知代码每次都具有相同的结构,那么您应该创建一个静态方法并传递您想要的所有内容,并将检查API 级别的代码放入此方法中。

回答by IrshadKumail

Its pretty simple to work with NotificationChannnel.

使用 NotificationChannel 非常简单。

NotificationChannel actually group multiple notifications into channels. It basically gives more control of the notification behavior to the user. You can read more about Notification Channel and its implementation at Working with Notification Channel | With Example

NotificationChannel 实际上将多个通知分组到通道中。它基本上为用户提供了对通知行为的更多控制。您可以在使用通知频道 |阅读有关通知频道及其实现的更多信息。举例

Creating Notification Channel

创建通知渠道

 // This is the Notification Channel ID. More about this in the next section
public static final String NOTIFICATION_CHANNEL_ID="channel_id";

//User visible Channel Name
public static final String CHANNEL_NAME="Notification Channel";

// Importance applicable to all the notifications in this Channel
int importance=NotificationManager.IMPORTANCE_DEFAULT;

//Notification channel should only be created for devices running Android 26
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

      NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, CHANNEL_NAME, importance);

      //Boolean value to set if lights are enabled for Notifications from this Channel
      notificationChannel.enableLights(true);

      //Boolean value to set if vibration is enabled for Notifications from this Channel
      notificationChannel.enableVibration(true);

      //Sets the color of Notification Light
      notificationChannel.setLightColor(Color.GREEN);

      //Set the vibration pattern for notifications. Pattern is in milliseconds with the format {delay,play,sleep,play,sleep...}
      notificationChannel.setVibrationPattern(new long[]{500,500,500,500,500});

      //Sets whether notifications from these Channel should be visible on Lockscreen or not
      notificationChannel.setLockscreenVisibility( 
 Notification.VISIBILITY_PUBLIC);
}
// Creating the Channel
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(notificationChannel);

Now while creating the Notification just pass the Channel ID to the Notification Builder constructor as shown below

现在在创建通知时只需将通道 ID 传递给通知构建器构造函数,如下所示

//We pass the unique channel id as the second parameter in the constructor
NotificationCompat.Builder notificationCompatBuilder=new NotificationCompat.Builder(this,NOTIFICATION_CHANNEL_ID);

//Title for your notification
notificationCompatBuilder.setContentTitle("This is title");

//Subtext for your notification
notificationCompatBuilder.setContentText("This is subtext");

//Small Icon for your notificatiom
notificationCompatBuilder.setSmallIcon(R.id.icon);

//Large Icon for your notification 
notificationCompatBuilder.setLargeIcon(  BitmapFactory.decodeResource(getResources(),R.id.icon));

notificationManager.notify( NOTIFICATION_ID,notificationCompatBuilder.build());

WIth this above notification becomes a part of the Notification Channel created in the first step and its behavior will now be with respect to the Channel Settings

有了上面的通知成为第一步中创建的通知通道的一部分,它的行为现在将与通道设置有关