Android|Android 8.0中各种通知写法汇总

概述 通知(Notification)是应用为用户显示重要信息提示的一种工具。系统为开发者提供了不同种类的通知样式模板可以使用,开发者也可以根据自己需要自定义通知样式。
之前写过类似的通知demo,时间长代码找不到了。另外,Google在Android N版本新增了可以直接回复的通知样式,Android O版本新增了通知渠道(NotificationCannel),也是时候更新一下知识库了。
代码结构 与通知相关的主要逻辑在Notifications、NotificationChannels和NotificationService这三个类中。

  • MainActivity.class
    主要是处理按钮点击事件,发送对应种类的通知。

    Android|Android 8.0中各种通知写法汇总
    文章图片
  • LaunchActivity.class
    点击通知后启动的Activity。
  • Notifications.class
    封装了一个单实例来发送通知,里面定义了发送各种通知的方法。
  • NotificationChannels.class
    把demo中用到的所有NotificationChannel封装到一个方法里面,在应用启动的时候一次性创建。
  • CustomApplication.class
    在应用启动后一次性创建所有需要的NotificationChannel。
  • NotificationService.class
    后台服务,负责处理与通知相关的所有响应事件。
  • NotificationContentWrapper.class
    封装的通知数据结构体,通过一个对象传递所有相关数据。
通知渠道(NotificationChannel) 通知渠道是Google在Android O中新增加的功能或是增强,新的版本中把振动、音效和灯效(实际上很多手机已经没有呼吸灯了)等相关效果放在了通知渠道中控制,这样用户就可以有选择的控制应用的某一类通知的通知效果,而不像之前版本中应用所有通知都受控于一种设置。需要注意的是,在Android O版本中,发送通知的时候必须要为通知设置通知渠道,否则通知不会被发送。
public class NotificationChannels { public final static String CRITICAL = "critical"; public final static String IMPORTANCE = "importance"; public final static String DEFAULT = "default"; public final static String LOW = "low"; public final static String MEDIA = "media"; public static void createAllNotificationChannels(Context context) { NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); if(nm == null) { return; }NotificationChannel mediaChannel = new NotificationChannel( MEDIA, context.getString(R.string.channel_media), NotificationManager.IMPORTANCE_DEFAULT); mediaChannel.setSound(null,null); mediaChannel.setVibrationPattern(null); nm.createNotificationChannels(Arrays.asList( new NotificationChannel( CRITICAL, context.getString(R.string.channel_critical), NotificationManager.IMPORTANCE_HIGH), new NotificationChannel( IMPORTANCE, context.getString(R.string.channel_importance), NotificationManager.IMPORTANCE_DEFAULT), new NotificationChannel( DEFAULT, context.getString(R.string.channel_default), NotificationManager.IMPORTANCE_LOW), new NotificationChannel( LOW, context.getString(R.string.channel_low), NotificationManager.IMPORTANCE_MIN), //custom notification channel mediaChannel )); } }

创建通知渠道的时候如果不额外设置音效、振动和灯光效果,通知在播放的时候会根据通知渠道中设置的重要等级(importance)来播放对应的通知效果。当然系统也提供了对应的方法来设置这些效果,实现方法可以参见上面代码中的meidiaChannel的实现。
各种优先级及对应效果如下:
/** * A notification with no importance: does not show in the shade. */ public static final int IMPORTANCE_NONE = 0; /** * Min notification importance: only shows in the shade, below the fold. */ public static final int IMPORTANCE_MIN = 1; /** * Low notification importance: shows everywhere, but is not intrusive. */ public static final int IMPORTANCE_LOW = 2; /** * Default notification importance: shows everywhere, makes noise, but does not visually * intrude. */ public static final int IMPORTANCE_DEFAULT = 3; /** * Higher notification importance: shows everywhere, makes noise and peeks. May use full screen * intents. */ public static final int IMPORTANCE_HIGH = 4; /** * Unused. */ public static final int IMPORTANCE_MAX = 5;

各种样式的通知 下面给出各种式样的通知的效果图和写法,可以根据实际需求选择合适的方法,也可以自行组合。
简单通知
  • 效果图

    Android|Android 8.0中各种通知写法汇总
    文章图片
  • 示例代码
public void sendSimpleNotification(Context context,NotificationManager nm) { //创建点击通知时发送的广播 Intent intent = new Intent(context,NotificationService.class); intent.setAction(ACTION_SIMPLE); PendingIntent pi = PendingIntent.getService(context,0,intent,0); //创建删除通知时发送的广播 Intent deleteIntent = new Intent(context,NotificationService.class); deleteIntent.setAction(ACTION_DELETE); PendingIntent deletePendingIntent = PendingIntent.getService(context,0,deleteIntent,0); //创建通知 Notification.Builder nb = new Notification.Builder(context,NotificationChannels.LOW) //设置通知左侧的小图标 .setSmallIcon(R.mipmap.ic_notification) //设置通知标题 .setContentTitle("Simple notification") //设置通知内容 .setContentText("Demo for simple notification !") //设置点击通知后自动删除通知 .setAutoCancel(true) //设置显示通知时间 .setShowWhen(true) //设置通知右侧的大图标 .setLargeIcon(BitmapFactory.decodeResource(context.getResources(),R.mipmap.ic_notifiation_big)) //设置点击通知时的响应事件 .setContentIntent(pi) //设置删除通知时的响应事件 .setDeleteIntent(deletePendingIntent); //发送通知 nm.notify(NOTIFICATION_SAMPLE,nb.build()); }

带Action按钮通知
  • 效果图

    Android|Android 8.0中各种通知写法汇总
    文章图片
  • 示例代码
public void sendActionNotification(Context context,NotificationManager nm) { //创建点击通知时发送的广播 Intent intent = new Intent(context,NotificationService.class); intent.setAction(ACTION_ACTION); PendingIntent pi = PendingIntent.getService(context,0,intent,0); //创建通知 Notification.Builder nb = new Notification.Builder(context,NotificationChannels.DEFAULT) //设置通知左侧的小图标 .setSmallIcon(R.mipmap.ic_notification) //设置通知标题 .setContentTitle("Action notification") //设置通知内容 .setContentText("Demo for action notification !") //设置点击通知后自动删除通知 .setAutoCancel(true) //设置显示通知时间 .setShowWhen(true) //设置点击通知时的响应事件 .setContentIntent(pi); //创建点击通知 YES 按钮时发送的广播 Intent yesIntent = new Intent(context, NotificationService.class); yesIntent.setAction(ACTION_YES); PendingIntent yesPendingIntent = PendingIntent.getService(context,0,yesIntent,0); Notification.Action yesActionBuilder = new Notification.Action.Builder( Icon.createWithResource("", R.mipmap.ic_yes), "YES", yesPendingIntent) .build(); //创建点击通知 NO 按钮时发送的广播 Intent noIntent = new Intent(context,NotificationService.class); noIntent.setAction(ACTION_NO); PendingIntent noPendingIntent = PendingIntent.getService(context,0,noIntent,0); Notification.Action noActionBuilder = new Notification.Action.Builder( Icon.createWithResource("", R.mipmap.ic_no), "NO", noPendingIntent) .build(); //为通知添加按钮 nb.setActions(yesActionBuilder,noActionBuilder); //发送通知 nm.notify(NOTIFICATION_ACTION,nb.build()); }

带快速回复功能通知
  • 效果图

    Android|Android 8.0中各种通知写法汇总
    文章图片

    Android|Android 8.0中各种通知写法汇总
    文章图片
  • 示例代码
public void sendRemoteInputNotification(Context context,NotificationManager nm) { //创建点击通知时发送的广播 Intent intent = new Intent(context,NotificationService.class); intent.setAction(ACTION_REMOTE_INPUT); PendingIntent pi = PendingIntent.getService(context,0,intent,0); //创建通知 Notification.Builder nb = new Notification.Builder(context,NotificationChannels.IMPORTANCE) //设置通知左侧的小图标 .setSmallIcon(R.mipmap.ic_notification) //设置通知标题 .setContentTitle("Remote input notification") //设置通知内容 .setContentText("Demo for remote input notification !") //设置点击通知后自动删除通知 .setAutoCancel(true) //设置显示通知时间 .setShowWhen(true) //设置点击通知时的响应事件 .setContentIntent(pi); //创建带输入框的按钮 RemoteInput remoteInput = new RemoteInput.Builder(REMOTE_INPUT_RESULT_KEY) .setLabel("Reply").build(); Intent remoteInputIntent = new Intent(context,NotificationService.class); remoteInputIntent.setAction(ACTION_REPLY); PendingIntent replyPendingIntent = PendingIntent.getService(context,2,remoteInputIntent,0); Notification.Action replyAction = new Notification.Action.Builder( Icon.createWithResource("",R.mipmap.ic_reply), "Reply", replyPendingIntent) .addRemoteInput(remoteInput) .build(); //为通知添加按钮 nb.setActions(replyAction); //发送通知 nm.notify(NOTIFICATION_REMOTE_INPUT,nb.build()); }

大图效果通知(BigPictureStyle)
  • 效果图

    Android|Android 8.0中各种通知写法汇总
    文章图片
  • 示例代码
public void sendBigPictureStyleNotification(Context context,NotificationManager nm) { //创建点击通知时发送的广播 Intent intent = new Intent(context,NotificationService.class); intent.setAction(ACTION_BIG_PICTURE_STYLE); PendingIntent pi = PendingIntent.getService(context,0,intent,0); //创建大视图样式 Notification.BigPictureStyle bigPictureStyle = new Notification.BigPictureStyle() .setBigContentTitle("Big picture style notification ~ Expand title") .setSummaryText("Demo for big picture style notification ! ~ Expand summery") .bigPicture(BitmapFactory.decodeResource(context.getResources(),R.mipmap.big_style_picture)); //创建通知 Notification.Builder nb = new Notification.Builder(context,NotificationChannels.DEFAULT) //设置通知左侧的小图标 .setSmallIcon(R.mipmap.ic_notification) //设置通知标题 .setContentTitle("Big picture style notification") //设置通知内容 .setContentText("Demo for big picture style notification !") //设置点击通知后自动删除通知 .setAutoCancel(true) //设置显示通知时间 .setShowWhen(true) //设置点击通知时的响应事件 .setContentIntent(pi) //设置大视图样式通知 .setStyle(bigPictureStyle); //发送通知 nm.notify(NOTIFICATION_BIG_PICTURE_STYLE,nb.build()); }

多文字效果通知(BigTextStyle) Android|Android 8.0中各种通知写法汇总
文章图片
  • 示例代码
public void sendBigTextStyleNotification(Context context,NotificationManager nm) { //创建点击通知时发送的广播 Intent intent = new Intent(context,NotificationService.class); intent.setAction(ACTION_BIG_TEXT_STYLE); PendingIntent pi = PendingIntent.getService(context,0,intent,0); //创建大文字样式 Notification.BigTextStyle bigTextStyle = new Notification.BigTextStyle() .setBigContentTitle("Big text style notification ~ Expand title") .setSummaryText("Demo for big text style notification ! ~ Expand summery") .bigText("We are the champions\n" + "We are the champions\n" + "No time for losers\n" + "Cause we are the champions of the World"); //创建通知 Notification.Builder nb = new Notification.Builder(context,NotificationChannels.DEFAULT) //设置通知左侧的小图标 .setSmallIcon(R.mipmap.ic_notification) //设置通知标题 .setContentTitle("Big text style notification") //设置通知内容 .setContentText("Demo for big text style notification !") //设置点击通知后自动删除通知 .setAutoCancel(true) //设置显示通知时间 .setShowWhen(true) //设置点击通知时的响应事件 .setContentIntent(pi) //设置大文字样式通知 .setStyle(bigTextStyle); //发送通知 nm.notify(NOTIFICATION_BIG_TEXT_STYLE,nb.build()); }

信箱效果通知(InboxStyle)
  • 效果图

    Android|Android 8.0中各种通知写法汇总
    文章图片
  • 示例代码
public void sendInboxStyleNotification(Context context, NotificationManager nm) { //创建点击通知时发送的广播 Intent intent = new Intent(context,NotificationService.class); intent.setAction(ACTION_INBOX_STYLE); PendingIntent pi = PendingIntent.getService(context,0,intent,0); //创建信箱样式 Notification.InboxStyle inboxStyle = new Notification.InboxStyle() .setBigContentTitle("Inbox style notification ~ Expand title") .setSummaryText("Demo for inbox style notification ! ~ Expand summery") //最多六行 .addLine("1. I am email content.") .addLine("2. I am email content.") .addLine("3. I am email content.") .addLine("4. I am email content.") .addLine("5. I am email content.") .addLine("6. I am email content."); //创建通知 Notification.Builder nb = new Notification.Builder(context,NotificationChannels.DEFAULT) //设置通知左侧的小图标 .setSmallIcon(R.mipmap.ic_notification) //设置通知标题 .setContentTitle("Inbox style notification") //设置通知内容 .setContentText("Demo for inbox style notification !") //设置点击通知后自动删除通知 .setAutoCancel(true) //设置显示通知时间 .setShowWhen(true) //设置点击通知时的响应事件 .setContentIntent(pi) //设置信箱样式通知 .setStyle(inboxStyle); //发送通知 nm.notify(NOTIFICATION_INBOX_STYLE,nb.build()); }

媒体效果通知(MediaStyle)
  • 效果图

    Android|Android 8.0中各种通知写法汇总
    文章图片
  • 示例代码
public void sendMediaStyleNotification(Context context, NotificationManager nm, boolean isPlaying) { //创建点击通知时发送的广播 Intent intent = new Intent(context,NotificationService.class); intent.setAction(ACTION_MEDIA_STYLE); PendingIntent pi = PendingIntent.getService(context,0,intent,0); //创建Action按钮 Intent playOrPauseIntent = new Intent(context,NotificationService.class); playOrPauseIntent.setAction(ACTION_MEDIA_STYLE); playOrPauseIntent.putExtra(EXTRA_OPTIONS, isPlaying ? MEDIA_STYLE_ACTION_PAUSE : MEDIA_STYLE_ACTION_PLAY); PendingIntent playOrPausePendingIntent = PendingIntent.getService(context,0, playOrPauseIntent,PendingIntent.FLAG_UPDATE_CURRENT); Notification.Action playOrPauseAction = new Notification.Action.Builder( Icon.createWithResource(context,isPlaying ? R.mipmap.ic_pause : R.mipmap.ic_play), isPlaying ? "PAUSE" : "PLAY", playOrPausePendingIntent) .build(); Intent nextIntent = new Intent(context,NotificationService.class); nextIntent.setAction(ACTION_MEDIA_STYLE); nextIntent.putExtra(EXTRA_OPTIONS, MEDIA_STYLE_ACTION_NEXT); PendingIntent nextPendingIntent = PendingIntent.getService(context,1, nextIntent,PendingIntent.FLAG_UPDATE_CURRENT); Notification.Action nextAction = new Notification.Action.Builder( Icon.createWithResource(context,R.mipmap.ic_next), "Next", nextPendingIntent) .build(); Intent deleteIntent = new Intent(context,NotificationService.class); deleteIntent.setAction(ACTION_MEDIA_STYLE); deleteIntent.putExtra(EXTRA_OPTIONS,MEDIA_STYLE_ACTION_DELETE); PendingIntent deletePendingIntent = PendingIntent.getService(context,2, deleteIntent,PendingIntent.FLAG_UPDATE_CURRENT); Notification.Action deleteAction = new Notification.Action.Builder( Icon.createWithResource(context,R.mipmap.ic_delete), "Delete", deletePendingIntent) .build(); //创建媒体样式 Notification.MediaStyle mediaStyle = new Notification.MediaStyle() //最多三个Action .setShowActionsInCompactView(0,1,2); //创建通知 Notification.Builder nb = new Notification.Builder(context,NotificationChannels.MEDIA) //设置通知左侧的小图标 .setSmallIcon(R.mipmap.ic_notification) //设置通知标题 .setContentTitle("Media style notification") //设置通知内容 .setContentText("Demo for media style notification !") //设置通知不可删除 .setOngoing(true) //设置显示通知时间 .setShowWhen(true) //设置点击通知时的响应事件 .setContentIntent(pi) //设置Action按钮 .setActions(playOrPauseAction,nextAction,deleteAction) //设置信箱样式通知 .setStyle(mediaStyle); //发送通知 nm.notify(NOTIFICATION_MEDIA_STYLE,nb.build()); }

信息效果通知(MessagingStyle)
  • 效果图

    Android|Android 8.0中各种通知写法汇总
    文章图片
  • 示例代码
public void sendMessagingStyleNotification(Context context, NotificationManager nm) { //创建点击通知时发送的广播 Intent intent = new Intent(context,NotificationService.class); intent.setAction(ACTION_MESSAGING_STYLE); PendingIntent pi = PendingIntent.getService(context,0,intent,0); //创建信息样式 Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("peter") .setConversationTitle("Messaging style notification") .addMessage("This is a message for you", System.currentTimeMillis(),"peter"); //创建通知 Notification.Builder nb = new Notification.Builder(context,NotificationChannels.DEFAULT) //设置通知左侧的小图标 .setSmallIcon(R.mipmap.ic_notification) //设置通知标题 .setContentTitle("Messaging style notification") //设置通知内容 .setContentText("Demo for messaging style notification !") //设置点击通知后自动删除通知 .setAutoCancel(true) //设置显示通知时间 .setShowWhen(true) //设置点击通知时的响应事件 .setContentIntent(pi) //设置信箱样式通知 .setStyle(messagingStyle); //发送通知 nm.notify(NOTIFICATION_MESSAGING_STYLE,nb.build()); }

带进度条通知
  • 效果图

    Android|Android 8.0中各种通知写法汇总
    文章图片
  • 示例代码
public void sendProgressViewNotification(Context context,NotificationManager nm, int progress) { //创建点击通知时发送的广播 Intent intent = new Intent(context,NotificationService.class); intent.setAction(ACTION_PROGRESS); PendingIntent pi = PendingIntent.getService(context,0,intent,0); //创建通知 Notification.Builder nb = new Notification.Builder(context,NotificationChannels.LOW) //设置通知左侧的小图标 .setSmallIcon(R.mipmap.ic_notification) //设置通知标题 .setContentTitle("Downloading...") //设置通知内容 .setContentText(String.valueOf(progress) + "%") //设置通知不可删除 .setOngoing(true) //设置显示通知时间 .setShowWhen(true) //设置点击通知时的响应事件 .setContentIntent(pi) .setProgress(100,progress,false); //发送通知 nm.notify(NOTIFICATION_PROGRESS,nb.build()); }

自定义顶部提醒视图通知(CustomHeadsUpView)
  • 效果图

    Android|Android 8.0中各种通知写法汇总
    文章图片
  • 示例代码
public void sendCustomHeadsUpViewNotification(Context context, NotificationManager nm) { //创建点击通知时发送的广播 Intent intent = new Intent(context,LaunchActivity.class); PendingIntent pi = PendingIntent.getActivity(context,0,intent,0); //创建自定义顶部提醒视图 Intent answerIntent = new Intent(context,NotificationService.class); answerIntent.setAction(ACTION_CUSTOM_HEADS_UP_VIEW); answerIntent.putExtra(EXTRA_OPTIONS, ACTION_ANSWER); PendingIntent answerPendingIntent = PendingIntent.getService(context,0,answerIntent,PendingIntent.FLAG_UPDATE_CURRENT); Intent rejectIntent = new Intent(context,NotificationService.class); rejectIntent.setAction(ACTION_CUSTOM_HEADS_UP_VIEW); rejectIntent.putExtra(EXTRA_OPTIONS,ACTION_REJECT); PendingIntent rejectPendingIntent = PendingIntent.getService(context,1,rejectIntent,PendingIntent.FLAG_UPDATE_CURRENT); RemoteViews headsUpView = new RemoteViews(context.getPackageName(),R.layout.custom_heads_up_layout); headsUpView.setOnClickPendingIntent(R.id.iv_answer,answerPendingIntent); headsUpView.setOnClickPendingIntent(R.id.iv_reject,rejectPendingIntent); //创建通知 Notification.Builder nb = new Notification.Builder(context,NotificationChannels.CRITICAL) //设置通知左侧的小图标 .setSmallIcon(R.mipmap.ic_notification) //设置通知标题 .setContentTitle("Custom heads up notification") //设置通知内容 .setContentText("Demo for custom heads up notification !") //设置点击通知后自动删除通知 .setAutoCancel(true) //设置显示通知时间 .setShowWhen(true) //设置点击通知时的响应事件 .setContentIntent(pi) //设置全屏响应事件; .setFullScreenIntent(pi,true) //设置自定义顶部提醒视图 .setCustomHeadsUpContentView(headsUpView); //发送通知 nm.notify(NOTIFICATION_CUSTOM_HEADS_UP,nb.build()); }

自定义视图通知(CustomView)
  • 效果图

    Android|Android 8.0中各种通知写法汇总
    文章图片
Android|Android 8.0中各种通知写法汇总
文章图片
  • 示例代码
public void sendCustomViewNotification(Context context, NotificationManager nm, NotificationContentWrapper content, Boolean isLoved, Boolean isPlaying) { //创建点击通知时发送的广播 Intent intent = new Intent(context,LaunchActivity.class); PendingIntent pi = PendingIntent.getActivity(context,0,intent,0); //创建各个按钮的点击响应广播 Intent intentLove = new Intent(context,NotificationService.class); intentLove.setAction(ACTION_CUSTOM_VIEW_OPTIONS_LOVE); PendingIntent piLove = PendingIntent.getService(context,0,intentLove,PendingIntent.FLAG_UPDATE_CURRENT); Intent intentPre = new Intent(context,NotificationService.class); intentPre.setAction(ACTION_CUSTOM_VIEW_OPTIONS_PRE); PendingIntent piPre = PendingIntent.getService(context,0,intentPre,PendingIntent.FLAG_UPDATE_CURRENT); Intent intentPlayOrPause = new Intent(context,NotificationService.class); intentPlayOrPause.setAction(ACTION_CUSTOM_VIEW_OPTIONS_PLAY_OR_PAUSE); PendingIntent piPlayOrPause = PendingIntent.getService(context,0, intentPlayOrPause,PendingIntent.FLAG_UPDATE_CURRENT); Intent intentNext = new Intent(context,NotificationService.class); intentNext.setAction(ACTION_CUSTOM_VIEW_OPTIONS_NEXT); PendingIntent piNext = PendingIntent.getService(context,0,intentNext,PendingIntent.FLAG_UPDATE_CURRENT); Intent intentLyrics = new Intent(context,NotificationService.class); intentLyrics.setAction(ACTION_CUSTOM_VIEW_OPTIONS_LYRICS); PendingIntent piLyrics = PendingIntent.getService(context,0,intentLyrics,PendingIntent.FLAG_UPDATE_CURRENT); Intent intentCancel = new Intent(context,NotificationService.class); intentCancel.setAction(ACTION_CUSTOM_VIEW_OPTIONS_CANCEL); PendingIntent piCancel = PendingIntent.getService(context,0,intentCancel,PendingIntent.FLAG_UPDATE_CURRENT); //创建自定义小视图 RemoteViews customView = new RemoteViews(context.getPackageName(),R.layout.custom_view_layout); customView.setImageViewBitmap(R.id.iv_content,content.bitmap); customView.setTextViewText(R.id.tv_title,content.title); customView.setTextViewText(R.id.tv_summery,content.summery); customView.setImageViewBitmap(R.id.iv_play_or_pause,BitmapFactory.decodeResource(context.getResources(), isPlaying ? R.mipmap.ic_pause : R.mipmap.ic_play)); customView.setOnClickPendingIntent(R.id.iv_play_or_pause,piPlayOrPause); customView.setOnClickPendingIntent(R.id.iv_next,piNext); customView.setOnClickPendingIntent(R.id.iv_lyrics,piLyrics); customView.setOnClickPendingIntent(R.id.iv_cancel,piCancel); //创建自定义大视图 RemoteViews customBigView = new RemoteViews(context.getPackageName(),R.layout.custom_big_view_layout); customBigView.setImageViewBitmap(R.id.iv_content_big,content.bitmap); customBigView.setTextViewText(R.id.tv_title_big,content.title); customBigView.setTextViewText(R.id.tv_summery_big,content.summery); customBigView.setImageViewBitmap(R.id.iv_love_big,BitmapFactory.decodeResource(context.getResources(), isLoved ? R.mipmap.ic_loved : R.mipmap.ic_love)); customBigView.setImageViewBitmap(R.id.iv_play_or_pause_big,BitmapFactory.decodeResource(context.getResources(), isPlaying ? R.mipmap.ic_pause : R.mipmap.ic_play)); customBigView.setOnClickPendingIntent(R.id.iv_love_big,piLove); customBigView.setOnClickPendingIntent(R.id.iv_pre_big,piPre); customBigView.setOnClickPendingIntent(R.id.iv_play_or_pause_big,piPlayOrPause); customBigView.setOnClickPendingIntent(R.id.iv_next_big,piNext); customBigView.setOnClickPendingIntent(R.id.iv_lyrics_big,piLyrics); customBigView.setOnClickPendingIntent(R.id.iv_cancel_big,piCancel); //创建通知 Notification.Builder nb = new Notification.Builder(context,NotificationChannels.MEDIA) //设置通知左侧的小图标 .setSmallIcon(R.mipmap.ic_notification) //设置通知标题 .setContentTitle("Custom notification") //设置通知内容 .setContentText("Demo for custom notification !") //设置通知不可删除 .setOngoing(true) //设置显示通知时间 .setShowWhen(true) //设置点击通知时的响应事件 .setContentIntent(pi) //设置自定义小视图 .setCustomContentView(customView) //设置自定义大视图 .setCustomBigContentView(customBigView); //发送通知 nm.notify(NOTIFICATION_CUSTOM,nb.build()); }

通知相关事件响应 从上面发送通知的示例代码可以看出,所有与点击通知相关的响应事件都是通过PendingIntent来完成的。具体是如何交互的可以参照对应的广播事件处理来学习。
public class NotificationService extends Service { private final static String TAG = "NotificationService"; public final static String ACTION_SEND_PROGRESS_NOTIFICATION = "com.android.peter.notificationdemo.ACTION_SEND_PROGRESS_NOTIFICATION"; private Context mContext; private NotificationManager mNM; private boolean mIsLoved; private boolean mIsPlaying = true; private List mContent = new ArrayList<>(); private int mCurrentPosition = 1; @Override public void onCreate() { super.onCreate(); mContext = this; mNM = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); initNotificationContent(); }@Override public int onStartCommand(Intent intent, int flags, int startId) { if(intent != null && intent.getAction() != null) { Log.i(TAG,"onStartCommand action = " + intent.getAction()); switch (intent.getAction()) { case ACTION_SIMPLE: break; case ACTION_ACTION: break; case ACTION_REMOTE_INPUT: break; case ACTION_BIG_PICTURE_STYLE: break; case ACTION_BIG_TEXT_STYLE: break; case ACTION_INBOX_STYLE: break; case ACTION_MEDIA_STYLE: dealWithActionMediaStyle(intent); break; case ACTION_MESSAGING_STYLE: break; case ACTION_YES: mNM.cancel(NOTIFICATION_ACTION); break; case ACTION_NO: mNM.cancel(NOTIFICATION_ACTION); break; case ACTION_DELETE: break; case ACTION_REPLY: dealWithActionReplay(intent); break; case ACTION_PROGRESS: break; case ACTION_SEND_PROGRESS_NOTIFICATION: dealWithActionSendProgressNotification(); break; case ACTION_CUSTOM_HEADS_UP_VIEW: dealWithActionCustomHeadsUpView(intent); break; case ACTION_CUSTOM_VIEW: break; case ACTION_CUSTOM_VIEW_OPTIONS_LOVE: Notificaitons.getInstance().sendCustomViewNotification(this,mNM,mContent.get(mCurrentPosition),!mIsLoved,mIsPlaying); mIsLoved = !mIsLoved; break; case ACTION_CUSTOM_VIEW_OPTIONS_PRE: --mCurrentPosition; Notificaitons.getInstance().sendCustomViewNotification(this,mNM,getNotificationContent(),mIsLoved,mIsPlaying); break; case ACTION_CUSTOM_VIEW_OPTIONS_PLAY_OR_PAUSE: Notificaitons.getInstance().sendCustomViewNotification(this,mNM,mContent.get(mCurrentPosition),mIsLoved,!mIsPlaying); mIsPlaying = !mIsPlaying; break; case ACTION_CUSTOM_VIEW_OPTIONS_NEXT: ++mCurrentPosition; Notificaitons.getInstance().sendCustomViewNotification(this,mNM,getNotificationContent(),mIsLoved,mIsPlaying); break; case ACTION_CUSTOM_VIEW_OPTIONS_LYRICS: break; case ACTION_CUSTOM_VIEW_OPTIONS_CANCEL: mNM.cancel(NOTIFICATION_CUSTOM); break; default: //do nothing } } return START_STICKY; }@Nullable @Override public IBinder onBind(Intent intent) { return null; }private void initNotificationContent() { mContent.clear(); mContent.add(new NotificationContentWrapper(BitmapFactory.decodeResource(mContext.getResources(),R.mipmap.custom_view_picture_pre),"远走高飞","金志文")); mContent.add(new NotificationContentWrapper(BitmapFactory.decodeResource(mContext.getResources(),R.mipmap.custom_view_picture_current),"最美的期待","周笔畅 - 最美的期待")); mContent.add(new NotificationContentWrapper(BitmapFactory.decodeResource(mContext.getResources(),R.mipmap.custom_view_picture_next),"你打不过我吧","跟风超人")); }private void dealWithActionMediaStyle(Intent intent) { String option = intent.getStringExtra(EXTRA_OPTIONS); Log.i(TAG,"media option = " + option); if(option == null) { return; } switch (option) { case MEDIA_STYLE_ACTION_PAUSE: Notificaitons.getInstance().sendMediaStyleNotification(this,mNM,false); break; case MEDIA_STYLE_ACTION_PLAY: Notificaitons.getInstance().sendMediaStyleNotification(this,mNM,true); break; case MEDIA_STYLE_ACTION_NEXT: break; case MEDIA_STYLE_ACTION_DELETE: mNM.cancel(NOTIFICATION_MEDIA_STYLE); break; default: //do nothing } }private void dealWithActionReplay(Intent intent) { Bundle result = RemoteInput.getResultsFromIntent(intent); if(result != null) { String content = result.getString(REMOTE_INPUT_RESULT_KEY); Log.i(TAG,"content = " + content); mNM.cancel(NOTIFICATION_REMOTE_INPUT); } }private void dealWithActionSendProgressNotification() { new Thread(new Runnable() { @Override public void run() { for(int i=0 ; i<=100 ; i++) { Notificaitons.getInstance().sendProgressViewNotification(mContext,mNM,i); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); }private void dealWithActionCustomHeadsUpView(Intent intent) { String headsUpOption = intent.getStringExtra(EXTRA_OPTIONS); Log.i(TAG,"heads up option = " + headsUpOption); if(headsUpOption == null) { return; } switch (headsUpOption) { case ACTION_ANSWER: mNM.cancel(NOTIFICATION_CUSTOM_HEADS_UP); break; case ACTION_REJECT: mNM.cancel(NOTIFICATION_CUSTOM_HEADS_UP); break; default: //do nothing } }private NotificationContentWrapper getNotificationContent() { switch (mCurrentPosition) { case -1: mCurrentPosition = 2; break; case 3: mCurrentPosition = 0; break; default: // do nothing }return mContent.get(mCurrentPosition); } }

小结 本文给出了在Android 8.0版本中各种通知的写法,各种设置的效果也做了比较详细的注释,可以根据具体需求自行组合,相信可以覆盖绝大部分应用场景,想要了解更多可以参看文末参考文献中给出的链接文章。
  • Demo
参考文献 【Android|Android 8.0中各种通知写法汇总】Google Notification user guide
Android Notification 详解
Android O Preview 之 通知渠道(Notification Channels)
Android notification .addAction deprecated in api 23
Android7.0 通知直接回复
如何使用Notification的相关Style实现不同类型的Notification
一起来学习Android 8.0系统的通知栏适配吧
解决PendingIntent传递参数为空的问题
Android--通知之Notification

    推荐阅读