概述
通知(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