28

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

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

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

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

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

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

4

6 回答 6

16

这是我在 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());
于 2017-09-22T10:49:44.027 回答
4

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

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

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

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

希望这可以帮助

于 2017-08-21T17:30:14.293 回答
2

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

/**
 * Helper class to manage notification channels, and create notifications.
 * <p>
 * Created by teocci.
 *
 * @author teocci@yandex.com 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)
}
于 2018-10-04T01:15:24.327 回答
2

这是使用反射创建通知通道的替代解决方案,因此您可以将 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);
        }
    }

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

builder.setChannelId("myChannelId");

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

compile 'com.android.support:appcompat-v7:26.1.0'
于 2018-02-19T07:11:21.377 回答
0

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

于 2018-04-01T11:24:00.873 回答
-2

使用 NotificationChannnel 非常简单。

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

创建通知通道

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

现在,在创建通知时,只需将通道 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());

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

于 2018-04-26T14:37:46.207 回答