美文网首页Android收藏集随笔-生活工作点滴Android
十七、Android 8.0中各种Notification写法汇

十七、Android 8.0中各种Notification写法汇

作者: 清梦星河哈 | 来源:发表于2019-07-22 10:29 被阅读13次

    转载自 peter_RD_nj
    https://www.jianshu.com/p/6aec3656e274

    概述

    通知(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 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;
    
    

    各种样式的通知

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

    简单通知

    • 效果图
    • 示例代码
        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;
    
        @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版本中各种通知的写法,各种设置的效果也做了比较详细的注释,可以根据具体需求自行组合,相信可以覆盖绝大部分应用场景,想要了解更多可以参看文末参考文献中给出的链接文章。

    参考文献

    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中各种Notification写法汇

        本文链接:https://www.haomeiwen.com/subject/iluehctx.html