Android O - 通知渠道和NotificationCompat

问题描述 投票:19回答:7

我无法改变这种感觉:再次,Android开发人员想出了一些新的东西,让所有人都不知道他们会如何看待这个功能。

我在谈论Android O中的通知频道。

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

现在,Builder要求我提供一个通知通道ID,这很好,但完全不用我创建这样一个频道。我找不到任何compat支持创建频道。我也找不到合适的方法来在正确的点上创建它们。

文档只是声明它应该“在某处”和“在发出通知时可能不会”。但究竟我应该做什么?我讨厌为简单的任务编写特定版本的东西 - 这就是我使用compat库的原因。

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

java android-notifications android-support-library android-8.0-oreo
7个回答
12
投票

这是我在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());

2
投票

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

您可以通过两种方式解决此问题,但对于这两种方法,您需要创建具有特定通道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);

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

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

第二种方法是通过Notification.Builder.setChannelId()设置通道

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

希望这可以帮助


2
投票

以下是使用反射创建通知通道的替代解决方案,因此您可以设置低于26的compileSdkVersion

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

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

builder.setChannelId("myChannelId");

注意:您需要将appcompat-v7库更新为26.x.x中的build.gradle版本:

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

0
投票

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


0
投票

如果您想支持以前版本的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);
    }
}

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

@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)
}

-1
投票

使用NotificationChannnel非常简单。

NotificationChannel实际上将多个通知分组到通道中。它基本上可以更好地控制用户的通知行为。您可以在Working with Notification Channel | With Example上阅读有关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);

现在,在创建Notification时,只需将Channel ID传递给Notification Builder构造函数,如下所示

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

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

© www.soinside.com 2019 - 2024. All rights reserved.