Android 8.0中各種通知寫法匯總

概述

通知(Notification)是應(yīng)用為用戶顯示重要信息提示的一種工具辜荠。系統(tǒng)為開發(fā)者提供了不同種類的通知樣式模板可以使用,開發(fā)者也可以根據(jù)自己需要自定義通知樣式扶认。
之前寫過類似的通知demo侨拦,時間長代碼找不到了。另外辐宾,Google在Android N版本新增了可以直接回復(fù)的通知樣式狱从,Android O版本新增了通知渠道(NotificationCannel),也是時候更新一下知識庫了叠纹。

代碼結(jié)構(gòu)

與通知相關(guān)的主要邏輯在Notifications季研、NotificationChannels和NotificationService這三個類中。

  • MainActivity.class
    主要是處理按鈕點擊事件誉察,發(fā)送對應(yīng)種類的通知与涡。


  • LaunchActivity.class
    點擊通知后啟動的Activity。

  • Notifications.class
    封裝了一個單實例來發(fā)送通知,里面定義了發(fā)送各種通知的方法驼卖。

  • NotificationChannels.class
    把demo中用到的所有NotificationChannel封裝到一個方法里面氨肌,在應(yīng)用啟動的時候一次性創(chuàng)建。

  • CustomApplication.class
    在應(yīng)用啟動后一次性創(chuàng)建所有需要的NotificationChannel酌畜。

  • NotificationService.class
    后臺服務(wù)怎囚,負責處理與通知相關(guān)的所有響應(yīng)事件。

  • NotificationContentWrapper.class
    封裝的通知數(shù)據(jù)結(jié)構(gòu)體桥胞,通過一個對象傳遞所有相關(guān)數(shù)據(jù)恳守。

通知渠道(NotificationChannel)

通知渠道是Google在Android O中新增加的功能或是增強,新的版本中把振動贩虾、音效和燈效(實際上很多手機已經(jīng)沒有呼吸燈了)等相關(guān)效果放在了通知渠道中控制催烘,這樣用戶就可以有選擇的控制應(yīng)用的某一類通知的通知效果,而不像之前版本中應(yīng)用所有通知都受控于一種設(shè)置缎罢。需要注意的是伊群,在Android O版本中,發(fā)送通知的時候必須要為通知設(shè)置通知渠道屁使,否則通知不會被發(fā)送在岂。

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

創(chuàng)建通知渠道的時候如果不額外設(shè)置音效、振動和燈光效果蛮寂,通知在播放的時候會根據(jù)通知渠道中設(shè)置的重要等級(importance)來播放對應(yīng)的通知效果蔽午。當然系統(tǒng)也提供了對應(yīng)的方法來設(shè)置這些效果,實現(xiàn)方法可以參見上面代碼中的meidiaChannel的實現(xiàn)。

各種優(yōu)先級及對應(yīng)效果如下:

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

各種樣式的通知

下面給出各種式樣的通知的效果圖和寫法,可以根據(jù)實際需求選擇合適的方法斤彼,也可以自行組合。

簡單通知

  • 效果圖


  • 示例代碼

    public void sendSimpleNotification(Context context,NotificationManager nm) {
        //創(chuàng)建點擊通知時發(fā)送的廣播
        Intent intent = new Intent(context,NotificationService.class);
        intent.setAction(ACTION_SIMPLE);
        PendingIntent pi = PendingIntent.getService(context,0,intent,0);
        //創(chuàng)建刪除通知時發(fā)送的廣播
        Intent deleteIntent = new Intent(context,NotificationService.class);
        deleteIntent.setAction(ACTION_DELETE);
        PendingIntent deletePendingIntent = PendingIntent.getService(context,0,deleteIntent,0);
        //創(chuàng)建通知
        Notification.Builder nb = new Notification.Builder(context,NotificationChannels.LOW)
                //設(shè)置通知左側(cè)的小圖標
                .setSmallIcon(R.mipmap.ic_notification)
                //設(shè)置通知標題
                .setContentTitle("Simple notification")
                //設(shè)置通知內(nèi)容
                .setContentText("Demo for simple notification !")
                //設(shè)置點擊通知后自動刪除通知
                .setAutoCancel(true)
                //設(shè)置顯示通知時間
                .setShowWhen(true)
                //設(shè)置通知右側(cè)的大圖標
                .setLargeIcon(BitmapFactory.decodeResource(context.getResources(),R.mipmap.ic_notifiation_big))
                //設(shè)置點擊通知時的響應(yīng)事件
                .setContentIntent(pi)
                //設(shè)置刪除通知時的響應(yīng)事件
                .setDeleteIntent(deletePendingIntent);
        //發(fā)送通知
        nm.notify(NOTIFICATION_SAMPLE,nb.build());
    }

帶Action按鈕通知

  • 效果圖


  • 示例代碼
    public void sendActionNotification(Context context,NotificationManager nm) {
        //創(chuàng)建點擊通知時發(fā)送的廣播
        Intent intent = new Intent(context,NotificationService.class);
        intent.setAction(ACTION_ACTION);
        PendingIntent pi = PendingIntent.getService(context,0,intent,0);
        //創(chuàng)建通知
        Notification.Builder nb = new Notification.Builder(context,NotificationChannels.DEFAULT)
                //設(shè)置通知左側(cè)的小圖標
                .setSmallIcon(R.mipmap.ic_notification)
                //設(shè)置通知標題
                .setContentTitle("Action notification")
                //設(shè)置通知內(nèi)容
                .setContentText("Demo for action notification !")
                //設(shè)置點擊通知后自動刪除通知
                .setAutoCancel(true)
                //設(shè)置顯示通知時間
                .setShowWhen(true)
                //設(shè)置點擊通知時的響應(yīng)事件
                .setContentIntent(pi);
        //創(chuàng)建點擊通知 YES 按鈕時發(fā)送的廣播
        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();
        //創(chuàng)建點擊通知 NO 按鈕時發(fā)送的廣播
        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);
        //發(fā)送通知
        nm.notify(NOTIFICATION_ACTION,nb.build());
    }

帶快速回復(fù)功能通知

  • 效果圖



  • 示例代碼
    public void sendRemoteInputNotification(Context context,NotificationManager nm) {
        //創(chuàng)建點擊通知時發(fā)送的廣播
        Intent intent = new Intent(context,NotificationService.class);
        intent.setAction(ACTION_REMOTE_INPUT);
        PendingIntent pi = PendingIntent.getService(context,0,intent,0);
        //創(chuàng)建通知
        Notification.Builder nb = new Notification.Builder(context,NotificationChannels.IMPORTANCE)
                //設(shè)置通知左側(cè)的小圖標
                .setSmallIcon(R.mipmap.ic_notification)
                //設(shè)置通知標題
                .setContentTitle("Remote input notification")
                //設(shè)置通知內(nèi)容
                .setContentText("Demo for remote input notification !")
                //設(shè)置點擊通知后自動刪除通知
                .setAutoCancel(true)
                //設(shè)置顯示通知時間
                .setShowWhen(true)
                //設(shè)置點擊通知時的響應(yīng)事件
                .setContentIntent(pi);
        //創(chuàng)建帶輸入框的按鈕
        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);
        //發(fā)送通知
        nm.notify(NOTIFICATION_REMOTE_INPUT,nb.build());
    }

大圖效果通知(BigPictureStyle)

  • 效果圖


  • 示例代碼
    public void sendBigPictureStyleNotification(Context context,NotificationManager nm) {
        //創(chuàng)建點擊通知時發(fā)送的廣播
        Intent intent = new Intent(context,NotificationService.class);
        intent.setAction(ACTION_BIG_PICTURE_STYLE);
        PendingIntent pi = PendingIntent.getService(context,0,intent,0);
        //創(chuàng)建大視圖樣式
        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));
        //創(chuàng)建通知
        Notification.Builder nb = new Notification.Builder(context,NotificationChannels.DEFAULT)
                //設(shè)置通知左側(cè)的小圖標
                .setSmallIcon(R.mipmap.ic_notification)
                //設(shè)置通知標題
                .setContentTitle("Big picture style notification")
                //設(shè)置通知內(nèi)容
                .setContentText("Demo for big picture style notification !")
                //設(shè)置點擊通知后自動刪除通知
                .setAutoCancel(true)
                //設(shè)置顯示通知時間
                .setShowWhen(true)
                //設(shè)置點擊通知時的響應(yīng)事件
                .setContentIntent(pi)
                //設(shè)置大視圖樣式通知
                .setStyle(bigPictureStyle);
        //發(fā)送通知
        nm.notify(NOTIFICATION_BIG_PICTURE_STYLE,nb.build());
    }

多文字效果通知(BigTextStyle)

  • 示例代碼
    public void sendBigTextStyleNotification(Context context,NotificationManager nm) {
        //創(chuàng)建點擊通知時發(fā)送的廣播
        Intent intent = new Intent(context,NotificationService.class);
        intent.setAction(ACTION_BIG_TEXT_STYLE);
        PendingIntent pi = PendingIntent.getService(context,0,intent,0);
        //創(chuàng)建大文字樣式
        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");
        //創(chuàng)建通知
        Notification.Builder nb = new Notification.Builder(context,NotificationChannels.DEFAULT)
                //設(shè)置通知左側(cè)的小圖標
                .setSmallIcon(R.mipmap.ic_notification)
                //設(shè)置通知標題
                .setContentTitle("Big text style notification")
                //設(shè)置通知內(nèi)容
                .setContentText("Demo for big text style notification !")
                //設(shè)置點擊通知后自動刪除通知
                .setAutoCancel(true)
                //設(shè)置顯示通知時間
                .setShowWhen(true)
                //設(shè)置點擊通知時的響應(yīng)事件
                .setContentIntent(pi)
                //設(shè)置大文字樣式通知
                .setStyle(bigTextStyle);
        //發(fā)送通知
        nm.notify(NOTIFICATION_BIG_TEXT_STYLE,nb.build());
    }

信箱效果通知(InboxStyle)

  • 效果圖


  • 示例代碼
    public void sendInboxStyleNotification(Context context, NotificationManager nm) {
        //創(chuàng)建點擊通知時發(fā)送的廣播
        Intent intent = new Intent(context,NotificationService.class);
        intent.setAction(ACTION_INBOX_STYLE);
        PendingIntent pi = PendingIntent.getService(context,0,intent,0);
        //創(chuàng)建信箱樣式
        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.");
        //創(chuàng)建通知
        Notification.Builder nb = new Notification.Builder(context,NotificationChannels.DEFAULT)
                //設(shè)置通知左側(cè)的小圖標
                .setSmallIcon(R.mipmap.ic_notification)
                //設(shè)置通知標題
                .setContentTitle("Inbox style notification")
                //設(shè)置通知內(nèi)容
                .setContentText("Demo for inbox style notification !")
                //設(shè)置點擊通知后自動刪除通知
                .setAutoCancel(true)
                //設(shè)置顯示通知時間
                .setShowWhen(true)
                //設(shè)置點擊通知時的響應(yīng)事件
                .setContentIntent(pi)
                //設(shè)置信箱樣式通知
                .setStyle(inboxStyle);
        //發(fā)送通知
        nm.notify(NOTIFICATION_INBOX_STYLE,nb.build());
    }

媒體效果通知(MediaStyle)

  • 效果圖


  • 示例代碼
    public void sendMediaStyleNotification(Context context, NotificationManager nm, boolean isPlaying) {
        //創(chuàng)建點擊通知時發(fā)送的廣播
        Intent intent = new Intent(context,NotificationService.class);
        intent.setAction(ACTION_MEDIA_STYLE);
        PendingIntent pi = PendingIntent.getService(context,0,intent,0);
        //創(chuàng)建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();
        //創(chuàng)建媒體樣式
        Notification.MediaStyle mediaStyle = new Notification.MediaStyle()
                //最多三個Action
                .setShowActionsInCompactView(0,1,2);
        //創(chuàng)建通知
        Notification.Builder nb = new Notification.Builder(context,NotificationChannels.MEDIA)
                //設(shè)置通知左側(cè)的小圖標
                .setSmallIcon(R.mipmap.ic_notification)
                //設(shè)置通知標題
                .setContentTitle("Media style notification")
                //設(shè)置通知內(nèi)容
                .setContentText("Demo for media style notification !")
                //設(shè)置通知不可刪除
                .setOngoing(true)
                //設(shè)置顯示通知時間
                .setShowWhen(true)
                //設(shè)置點擊通知時的響應(yīng)事件
                .setContentIntent(pi)
                //設(shè)置Action按鈕
                .setActions(playOrPauseAction,nextAction,deleteAction)
                //設(shè)置信箱樣式通知
                .setStyle(mediaStyle);

        //發(fā)送通知
        nm.notify(NOTIFICATION_MEDIA_STYLE,nb.build());
    }

信息效果通知(MessagingStyle)

  • 效果圖


  • 示例代碼
    public void sendMessagingStyleNotification(Context context, NotificationManager nm) {
        //創(chuàng)建點擊通知時發(fā)送的廣播
        Intent intent = new Intent(context,NotificationService.class);
        intent.setAction(ACTION_MESSAGING_STYLE);
        PendingIntent pi = PendingIntent.getService(context,0,intent,0);
        //創(chuàng)建信息樣式
        Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("peter")
                .setConversationTitle("Messaging style notification")
                .addMessage("This is a message for you", System.currentTimeMillis(),"peter");
        //創(chuàng)建通知
        Notification.Builder nb = new Notification.Builder(context,NotificationChannels.DEFAULT)
                //設(shè)置通知左側(cè)的小圖標
                .setSmallIcon(R.mipmap.ic_notification)
                //設(shè)置通知標題
                .setContentTitle("Messaging style notification")
                //設(shè)置通知內(nèi)容
                .setContentText("Demo for messaging style notification !")
                //設(shè)置點擊通知后自動刪除通知
                .setAutoCancel(true)
                //設(shè)置顯示通知時間
                .setShowWhen(true)
                //設(shè)置點擊通知時的響應(yīng)事件
                .setContentIntent(pi)
                //設(shè)置信箱樣式通知
                .setStyle(messagingStyle);
        //發(fā)送通知
        nm.notify(NOTIFICATION_MESSAGING_STYLE,nb.build());
    }

帶進度條通知

  • 效果圖


  • 示例代碼
    public void sendProgressViewNotification(Context context,NotificationManager nm, int progress) {
        //創(chuàng)建點擊通知時發(fā)送的廣播
        Intent intent = new Intent(context,NotificationService.class);
        intent.setAction(ACTION_PROGRESS);
        PendingIntent pi = PendingIntent.getService(context,0,intent,0);
        //創(chuàng)建通知
        Notification.Builder nb = new Notification.Builder(context,NotificationChannels.LOW)
                //設(shè)置通知左側(cè)的小圖標
                .setSmallIcon(R.mipmap.ic_notification)
                //設(shè)置通知標題
                .setContentTitle("Downloading...")
                //設(shè)置通知內(nèi)容
                .setContentText(String.valueOf(progress) + "%")
                //設(shè)置通知不可刪除
                .setOngoing(true)
                //設(shè)置顯示通知時間
                .setShowWhen(true)
                //設(shè)置點擊通知時的響應(yīng)事件
                .setContentIntent(pi)
                .setProgress(100,progress,false);
        //發(fā)送通知
        nm.notify(NOTIFICATION_PROGRESS,nb.build());
    }

自定義頂部提醒視圖通知(CustomHeadsUpView)

  • 效果圖


  • 示例代碼
    public void sendCustomHeadsUpViewNotification(Context context, NotificationManager nm) {
        //創(chuàng)建點擊通知時發(fā)送的廣播
        Intent intent = new Intent(context,LaunchActivity.class);
        PendingIntent pi = PendingIntent.getActivity(context,0,intent,0);
        //創(chuàng)建自定義頂部提醒視圖
        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);
        //創(chuàng)建通知
        Notification.Builder nb = new Notification.Builder(context,NotificationChannels.CRITICAL)
                //設(shè)置通知左側(cè)的小圖標
                .setSmallIcon(R.mipmap.ic_notification)
                //設(shè)置通知標題
                .setContentTitle("Custom heads up notification")
                //設(shè)置通知內(nèi)容
                .setContentText("Demo for custom heads up notification !")
                //設(shè)置點擊通知后自動刪除通知
                .setAutoCancel(true)
                //設(shè)置顯示通知時間
                .setShowWhen(true)
                //設(shè)置點擊通知時的響應(yīng)事件
                .setContentIntent(pi)
                //設(shè)置全屏響應(yīng)事件;
                .setFullScreenIntent(pi,true)
                //設(shè)置自定義頂部提醒視圖
                .setCustomHeadsUpContentView(headsUpView);
        //發(fā)送通知
        nm.notify(NOTIFICATION_CUSTOM_HEADS_UP,nb.build());
    }

自定義視圖通知(CustomView)

  • 效果圖


  • 示例代碼
    public void sendCustomViewNotification(Context context, NotificationManager nm, NotificationContentWrapper content, Boolean isLoved, Boolean isPlaying) {
        //創(chuàng)建點擊通知時發(fā)送的廣播
        Intent intent = new Intent(context,LaunchActivity.class);
        PendingIntent pi = PendingIntent.getActivity(context,0,intent,0);
        //創(chuàng)建各個按鈕的點擊響應(yīng)廣播
        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);
        //創(chuàng)建自定義小視圖
        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);
        //創(chuàng)建自定義大視圖
        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);
        //創(chuàng)建通知
        Notification.Builder nb = new Notification.Builder(context,NotificationChannels.MEDIA)
                //設(shè)置通知左側(cè)的小圖標
                .setSmallIcon(R.mipmap.ic_notification)
                //設(shè)置通知標題
                .setContentTitle("Custom notification")
                //設(shè)置通知內(nèi)容
                .setContentText("Demo for custom notification !")
                //設(shè)置通知不可刪除
                .setOngoing(true)
                //設(shè)置顯示通知時間
                .setShowWhen(true)
                //設(shè)置點擊通知時的響應(yīng)事件
                .setContentIntent(pi)
                //設(shè)置自定義小視圖
                .setCustomContentView(customView)
                //設(shè)置自定義大視圖
                .setCustomBigContentView(customBigView);
        //發(fā)送通知
        nm.notify(NOTIFICATION_CUSTOM,nb.build());
    }

通知相關(guān)事件響應(yīng)

從上面發(fā)送通知的示例代碼可以看出骄恶,所有與點擊通知相關(guān)的響應(yīng)事件都是通過PendingIntent來完成的。具體是如何交互的可以參照對應(yīng)的廣播事件處理來學(xué)習(xí)匕垫。

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

小結(jié)

本文給出了在Android 8.0版本中各種通知的寫法僧鲁,各種設(shè)置的效果也做了比較詳細的注釋,可以根據(jù)具體需求自行組合象泵,相信可以覆蓋絕大部分應(yīng)用場景寞秃,想要了解更多可以參看文末參考文獻中給出的鏈接文章。

參考文獻

Google Notification user guide
Android Notification 詳解
Android O Preview 之 通知渠道(Notification Channels)
Android notification .addAction deprecated in api 23
Android7.0 通知直接回復(fù)
如何使用Notification的相關(guān)Style實現(xiàn)不同類型的Notification
一起來學(xué)習(xí)Android 8.0系統(tǒng)的通知欄適配吧
解決PendingIntent傳遞參數(shù)為空的問題
Android--通知之Notification

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末偶惠,一起剝皮案震驚了整個濱河市春寿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌忽孽,老刑警劉巖绑改,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谢床,死亡現(xiàn)場離奇詭異,居然都是意外死亡厘线,警方通過查閱死者的電腦和手機识腿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來皆的,“玉大人覆履,你說我怎么就攤上這事》驯。” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵栖雾,是天一觀的道長楞抡。 經(jīng)常有香客問我,道長析藕,這世上最難降的妖魔是什么召廷? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮账胧,結(jié)果婚禮上竞慢,老公的妹妹穿的比我還像新娘。我一直安慰自己治泥,他們只是感情好筹煮,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著居夹,像睡著了一般败潦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上准脂,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天劫扒,我揣著相機與錄音,去河邊找鬼狸膏。 笑死沟饥,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的湾戳。 我是一名探鬼主播贤旷,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼院塞!你這毒婦竟也來了遮晚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤拦止,失蹤者是張志新(化名)和其女友劉穎县遣,沒想到半個月后糜颠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡萧求,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年其兴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夸政。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡元旬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出守问,到底是詐尸還是另有隱情匀归,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布耗帕,位于F島的核電站穆端,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏仿便。R本人自食惡果不足惜体啰,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嗽仪。 院中可真熱鬧荒勇,春花似錦、人聲如沸闻坚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鲤氢。三九已至搀擂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卷玉,已是汗流浹背哨颂。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留相种,地道東北人威恼。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像寝并,于是被迫代替她去往敵國和親箫措。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354