概述

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

代码结构

与通知相关的主要逻辑在Notifications、NotificationChannels和NotificationService这三个类中。

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

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

创建通知渠道的时候如果不额外设置音效、振动和灯光效果,通知在播放的时候会根据通知渠道中设置的重要等级(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;

各种样式的通知

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

简单通知

  • 效果图

  • 示例代码

    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按钮通知

  • 效果图

  • 示例代码
    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());}

带快速回复功能通知

  • 效果图

  • 示例代码
    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)

  • 效果图

  • 示例代码
    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)

  • 示例代码
    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)

  • 效果图

  • 示例代码
    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)

  • 效果图

  • 示例代码
    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)

  • 效果图

  • 示例代码
    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());}

带进度条通知

  • 效果图

  • 示例代码
    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)

  • 效果图

  • 示例代码
    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)

  • 效果图

  • 示例代码
    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<NotificationContentWrapper> mContent = new ArrayList<>();private int mCurrentPosition = 1;@Overridepublic void onCreate() {super.onCreate();mContext = this;mNM = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);initNotificationContent();}@Overridepublic 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@Overridepublic 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() {@Overridepublic 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

参考文献

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

Android 8.0中各种通知写法汇总相关推荐

  1. Android 8.0 创建管理通知渠道Notification

    从Android8.0(API26)开始,所有的通知必须分配一个渠道.每一个渠道,你都可以设置渠道中所有通知的视觉和听觉行为.然后,用户能够随意修改这些设置来决定通知的行为. 在用户界面渠道显示为 & ...

  2. Android 7.0中的多窗口-分屏-实现解析

    禁用APK分屏-AndroidManifest.xml添加属性:android:resizeableActivity="false" Android 7.0中的多窗口实现解析 标签 ...

  3. Android 5.0中的FDE功能实现

    标 题:  [分享]Android 5.0中的FDE功能实现 作 者: netsniffer 时 间: 2015-01-27,21:15:06 链 接: http://bbs.pediy.com/sh ...

  4. android辅助功能实现群发,Android 8.0实现发送通知的方法

    Android 8.0实现发送通知的方法 发布时间:2020-07-30 09:34:40 来源:亿速云 阅读:111 作者:小猪 这篇文章主要讲解了Android 8.0实现发送通知的方法,内容清晰 ...

  5. Android 8.0学习(31)---Android 8.0 中的 ART 功能改进

    Android 8.0 中的 ART 功能改进 在 Android 8.0 版本中,Android Runtime (ART) 有了极大改进.下面的列表总结了设备制造商可以在 ART 中获得的增强功能 ...

  6. linux 电源管理 唤醒,Android 4.0 中的PowerManager(电源管理--休眠唤醒) [转]

    转发请注明出处: 最近,在学习让系统进入休眠的过程中,学习了电源管理的相关知识.为了备忘和理清思路现整理成文,以便日后查阅. 移动设备由于自身的限制有一个硬伤就是电量的消耗问题.由于电池的电量有限,所 ...

  7. as3 android白屏,Android 8.0中一些坑以及对应的解决方法

    前言 虽然 Android 9.0 都已经面世了,本篇文章写的有点迟了. 但是迟到好过不到,因此基于此这边还是记录一下项目中遇到的 Android 8.0 的坑及对应解决方法. 每次系统升级,虽然系统 ...

  8. Android Studio3.0中dependencies依赖由compile变为implementation的区别

    前言 Android Studio版本更新至3.0了,更新后,连带着com.android.tools.build:gradle 工具也升级到了3.0.0,在3.0.0中使用了最新的Gralde 4. ...

  9. Android — 在服务中发送通知Notification

    1.在服务中,发送通知的方法 private void sendNotification(String title,String content,StateBean stateBean){Contex ...

  10. Android 8.0 中如何读取内部和外部存储以及外置SDcard

    最近碰到询问我这个读取SDcard的问题, 很久没有看这部分了,所以大致看了一下, 顺便记录一下.在Android 8.0上做了测试. 一般的Android App能读取的存储空间主要有三种: app ...

最新文章

  1. Spring3的表达式语言
  2. 02_Jquery_02_元素选择器
  3. java空心三角形_java经典算法_019打印三角形(空心,实心)
  4. 手机uc怎么放大页面_手机网站怎样做可以提高用户体验度?——竹晨网络
  5. 固态硬盘上安装centos_自己动手丰衣足食 手把手教你安装M.2固态硬盘
  6. Hibernate常用的Java数据类型映射到mysql和Oracle
  7. vs2015开发人员命令提示工具 查看C++类对象模型
  8. ACM学习历程—HDU 2112 HDU Today(map spfa 优先队列)
  9. Atlas客户端类库、控件介绍(2)
  10. python一些常用方法_收藏整理的一些Python常用方法和技巧
  11. 磁盘在linux是什么文件,鸟哥的 Linux 私房菜 -- Linux 磁盘与文件系统管理
  12. 凸优化第四章凸优化问题 4.1 优化问题
  13. Unity 之圆环算法
  14. “百度百科六度分隔理论”(简单版)
  15. mysql upgrade 是什么意思_Upgrade是什么意思?
  16. MFC窗口透明化以及透明穿透
  17. 【HTML基础-1】HTML标签简介及常用标签
  18. 金仓数据库KingbaseES ksql工具用户指南及参考--2. Ksql快速启动
  19. 2019 华为手机录屏adb命令不识别
  20. 数字图像处理学习之路:图像变换(一)

热门文章

  1. java 调用百度语音
  2. Hash散列算法详细解析(五)
  3. 关于Excel被保护的工作表忘记密码的强制解除办法
  4. unity的立方贴图
  5. 2019携程校招笔试题选讲
  6. QQ空间说说批量删除
  7. 百度导航SDK升级适配 Anroid 11骑步导航闪退
  8. 下载编译chromium
  9. 建模实训报告总结_实验报告总结(15篇)
  10. 面试题之10亿正整数问题