最近時不時地有人問我這樣或那樣的通知如何實現(xiàn)吩屹,所以本文將根據(jù)個人經(jīng)驗對Notification做個總結(jié),以供參考肆捕!
什么是通知(Notification)
通知是一個可以在應用程序正常的用戶界面之外顯示給用戶的消息。
通知發(fā)出時,它首先出現(xiàn)在狀態(tài)欄的通知區(qū)域中额衙,用戶打開通知抽屜可查看通知詳情。通知區(qū)域和通知抽屜都是用戶可以隨時查看的系統(tǒng)控制區(qū)域。
作為安卓用戶界面的重要組成部分窍侧,通知有自己的設計指南县踢。在Android 5.0(API level 21)中引入的 Material Design 的變化是特別重要的,更多信息請閱讀 通知設計指南伟件。
如何創(chuàng)建通知
隨著Android系統(tǒng)不斷升級硼啤,Notification的創(chuàng)建方式也隨之變化,主要變化如下:
Android 3.0之前
Android 3.0 (API level 11)之前斧账,使用new Notification()
方式創(chuàng)建通知:
NotificationManager mNotifyMgr =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(
this, 0, new Intent(this, ResultActivity.class), 0);
Notification notification = new Notification(icon, tickerText, when);
notification.setLatestEventInfo(this, title, content, contentIntent);
mNotifyMgr.notify(NOTIFICATIONS_ID, notification);
Android 3.0 (API level 11)及更高版本
Android 3.0開始棄用new Notification()
方式谴返,改用Notification.Builder()
來創(chuàng)建通知:
NotificationManager mNotifyMgr =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(
this, 0, new Intent(this, ResultActivity.class), 0);
Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setContentIntent(contentIntent)
.build();// getNotification()
mNotifyMgr.notify(NOTIFICATIONS_ID, notification);
這里需要注意: "build()" 是Androdi 4.1(API level 16)加入的,用以替代
"getNotification()"咧织。API level 16開始棄用"getNotification()"
兼容Android 3.0之前的版本
為了兼容API level 11
之前的版本嗓袱,v4 Support Library
中提供了
NotificationCompat.Builder()
這個替代方法。它與Notification.Builder()
類似习绢,二者沒有太大區(qū)別渠抹。
NotificationManager mNotifyMgr =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(
this, 0, new Intent(this, ResultActivity.class), 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setContentIntent(contentIntent);
mNotifyMgr.notify(NOTIFICATIONS_ID, mBuilder.build());
注:除特別說明外,本文將根據(jù) NotificationCompat.Builder() 展開解析闪萄,
Notification.Builder()類似梧却。
通知基本用法
通知的必要屬性
一個通知必須包含以下三項屬性:
- 小圖標,對應 setSmallIcon()
- 通知標題败去,對應 setContentTitle()
- 詳細信息放航,對應 setContentText()
其他屬性均為可選項,更多屬性方法請參考NotificationCompat.Builder为迈。
盡管其他都是可選的三椿,但一般都會為通知添加至少一個動作(Action),這個動作可以是跳轉(zhuǎn)到Activity葫辐、啟動一個Service或發(fā)送一個Broadcas等搜锰。 通過以下方式為通知添加動作:
- 使用PendingIntent
- 通過大視圖通知的 Action Button //僅支持Android 4.1 (API level 16)及更高版本,稍后會介紹
創(chuàng)建通知
1耿战、實例化一個NotificationCompat.Builder對象
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!");
NotificationCompat.Builder自動設置的默認值:
- priority: PRIORITY_DEFAULT
- when: System.currentTimeMillis()
- audio stream: STREAM_DEFAULT
2蛋叼、定義并設置一個通知動作(Action)
Intent resultIntent = new Intent(this, ResultActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(
this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
3、生成Notification
對象
Notificatioin notification = mBuilder.build();
4剂陡、使用NotificationManager
發(fā)送通知
// Sets an ID for the notification
int mNotificationId = 001;
// Gets an instance of the NotificationManager service
NotificationManager mNotifyMgr =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Builds the notification and issues it.
mNotifyMgr.notify(mNotificationId, notification);
更新通知
更新通知很簡單狈涮,只需再次發(fā)送相同ID的通知即可,如果之前的通知依然存在則會更新通知屬性鸭栖,如果之前通知不存在則重新創(chuàng)建歌馍。
示例代碼:
NotificationManager mNotifyMgr =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Sets an ID for the notification, so it can be updated
int notifyID = 1;
NotificationCompat.Builder mNotifyBuilder =
new NotificationCompat.Builder(this)
.setContentTitle("New Message")
.setContentText("You've received new messages.")
.setSmallIcon(R.drawable.ic_notify_status);
int numMessages = 0;
...
mNotifyBuilder.setContentText("new content text")
.setNumber(++numMessages);
mNotifyMgr.notify(notifyID, mNotifyBuilder.build());
...
取消通知
取消通知有如下4種方式:
- 點擊通知欄的清除按鈕,會清除所有可清除的通知
- 設置了 setAutoCancel() 或 FLAG_AUTO_CANCEL的通知晕鹊,點擊該通知時會清除它
- 通過 NotificationManager 調(diào)用 cancel() 方法清除指定ID的通知
- 通過 NotificationManager 調(diào)用 cancelAll() 方法清除所有該應用之前發(fā)送的通知
通知類型
大視圖通知
通知有兩種視圖:普通視圖和大視圖松却。
普通視圖:
大視圖:
默認情況下為普通視圖暴浦,可通過NotificationCompat.Builder.setStyle()
設置大視圖。
注: 大視圖(Big Views)由Android 4.1(API level 16)開始引入晓锻,且僅支持Android 4.1及更高版本歌焦。
構(gòu)建大視圖通知
以上圖為例:
1、構(gòu)建Action Button的PendingIntent
Intent dismissIntent = new Intent(this, PingService.class);
dismissIntent.setAction(CommonConstants.ACTION_DISMISS);
PendingIntent piDismiss = PendingIntent.getService(
this, 0, dismissIntent, 0);
Intent snoozeIntent = new Intent(this, PingService.class);
snoozeIntent.setAction(CommonConstants.ACTION_SNOOZE);
PendingIntent piSnooze =
PendingIntent.getService(this, 0, snoozeIntent, 0);
2砚哆、構(gòu)建NotificatonCompat.Builder對象
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_notification)
.setContentTitle(getString(R.string.notification))
.setContentText(getString(R.string.ping))
.setDefaults(Notification.DEFAULT_ALL)
// 該方法在Android 4.1之前會被忽略
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
//添加Action Button
.addAction (R.drawable.ic_stat_dismiss,
getString(R.string.dismiss), piDismiss)
.addAction (R.drawable.ic_stat_snooze,
getString(R.string.snooze), piSnooze);
3独撇、其他步驟與普通視圖相同
進度條通知
-
明確進度的進度條
使用setProgress(max, progress, false)
來更新進度。
max: 最大進度值
progress: 當前進度
false: 是否是不明確的進度條模擬下載過程躁锁,示例如下:
int id = 1; ... mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mBuilder = new NotificationCompat.Builder(this); mBuilder.setContentTitle("Picture Download") .setContentText("Download in progress") .setSmallIcon(R.drawable.ic_notification); // Start a lengthy operation in a background thread new Thread( new Runnable() { @Override public void run() { int incr; for (incr = 0; incr <= 100; incr+=5) { mBuilder.setProgress(100, incr, false); mNotifyManager.notify(id, mBuilder.build()); try { // Sleep for 5 seconds Thread.sleep(5*1000); } catch (InterruptedException e) { Log.d(TAG, "sleep failure"); } } mBuilder.setContentText("Download complete")//下載完成 .setProgress(0,0,false); //移除進度條 mNotifyManager.notify(id, mBuilder.build()); } } ).start();
上圖纷铣,分別為下載過程中進度條通知 和 下載完成移除進度條后的通知。 -
不確定進度的進度條
使用setProgress(0, 0, true)
來表示進度不明確的進度條mBuilder.setProgress(0, 0, true); mNotifyManager.notify(id, mBuilder.build());
浮動通知(Heads-up Notifications)
Android 5.0(API level 21)開始战转,當屏幕未上鎖且亮屏時关炼,通知可以以小窗口形式顯示。用戶可以在不離開當前應用前提下操作該通知匣吊。
如圖:
NotificationCompat.Builder mNotifyBuilder =
new NotificationCompat.Builder(this)
.setContentTitle("New Message")
.setContentText("You've received new messages.")
.setSmallIcon(R.drawable.ic_notify_status)
.setFullScreenIntent(pendingIntent, false);
以下兩種情況會顯示浮動通知:
- setFullScreenIntent()儒拂,如上述示例。
- 通知擁有高優(yōu)先級且使用了鈴聲和振動
鎖屏通知
Android 5.0(API level 21)開始色鸳,通知可以顯示在鎖屏上社痛。用戶可以通過設置選擇是否允許敏感的通知內(nèi)容顯示在安全的鎖屏上。
你的應用可以通過setVisibility()
控制通知的顯示等級:
- VISIBILITY_PRIVATE : 顯示基本信息命雀,如通知的圖標蒜哀,但隱藏通知的全部內(nèi)容
- VISIBILITY_PUBLIC : 顯示通知的全部內(nèi)容
- VISIBILITY_SECRET : 不顯示任何內(nèi)容,包括圖標
自定義通知
Android系統(tǒng)允許使用RemoteViews來自定義通知吏砂。
自定義普通視圖通知高度限制為64dp撵儿,大視圖通知高度限制為256dp。同時狐血,建議自定義通知盡量簡單淀歇,以提高兼容性。
自定義通知需要做如下操作:
1匈织、創(chuàng)建自定義通知布局
2浪默、使用RemoteViews定義通知組件,如圖標缀匕、文字等
3纳决、調(diào)用setContent()
將RemoteViews對象綁定到NotificationCompat.Builder
4、同正常發(fā)送通知流程
注意: 避免為通知設置背景乡小,因為兼容性原因阔加,有些文字可能看不清。
定義通知文本樣式
通知的背景顏色在不同的設備和版本中有所不同满钟,Android2.3開始胜榔,系統(tǒng)定義了一套標準通知文本樣式约急,建議自定義通知使用標準樣式,這樣有助于通知文本可見苗分。
通知文本樣式:
Android 5.0之前可用:
android:style/TextAppearance.StatusBar.EventContent.Title // 通知標題樣式
android:style/TextAppearance.StatusBar.EventContent // 通知內(nèi)容樣式
Android 5.0及更高版本:
android:style/TextAppearance.Material.Notification.Title // 通知標題樣式
android:style/TextAppearance.Material.Notification // 通知內(nèi)容樣式
更多通知的標準樣式和布局,可參考源碼frameworks/base/core/res/res/layout
路徑下的通知模版如:
Android 5.0之前:
notification_template_base.xml
notification_template_big_base.xml
notification_template_big_picture.xml
notification_template_big_text.xml
Android 5.0 及更高版本:
notification_template_material_base.xml
notification_template_material_big_base.xml
notification_template_material_big_picture.xml
notification_template_part_chronometer.xml
notification_template_progressbar.xml
等等牵辣。
保留Activity返回棧
常規(guī)Activity
默認情況下摔癣,從通知啟動一個Activity,按返回鍵會回到主屏幕纬向。但某些時候有按返回鍵仍然留在當前應用的需求择浊,這就要用到TaskStackBuilder
了。
1逾条、在manifest中定義Activity的關(guān)系
Android 4.0.3 及更早版本
<activity
android:name=".ResultActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>
Android 4.1 及更高版本
<activity
android:name=".ResultActivity"
android:parentActivityName=".MainActivity">
</activity>
2琢岩、創(chuàng)建返回棧PendingIntent
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// 添加返回棧
stackBuilder.addParentStack(ResultActivity.class);
// 添加Intent到棧頂
stackBuilder.addNextIntent(resultIntent);
// 創(chuàng)建包含返回棧的pendingIntent
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
上述操作后,從通知啟動ResultActivity师脂,按返回鍵會回到MainActivity担孔,而不是主屏幕。
特殊Activity
默認情況下吃警,從通知啟動的Activity會在近期任務列表里出現(xiàn)糕篇。如果不需要在近期任務里顯示,則需要做以下操作:
1酌心、在manifest中定義Activity
<activity
android:name=".ResultActivity"
android:launchMode="singleTask"
android:taskAffinity=""
android:excludeFromRecents="true">
</activity>
2拌消、構(gòu)建PendingIntent
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
Intent notifyIntent = new Intent(this, ResultActivity.class);
// Sets the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent notifyPendingIntent =
PendingIntent.getActivity(this, 0, notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(notifyPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
上述操作后,從通知啟動ResultActivity安券,此Activity不會出現(xiàn)在近期任務列表中墩崩。
通知常見屬性和常量
通知的提醒方式
1、聲音提醒
- 默認聲音
notification.defaults |= Notification.DEFAULT_SOUND; - 自定義聲音
notification.sound = Uri.parse("file:///sdcard0/notification.ogg");
2侯勉、震動提醒
- 默認振動
notification.defaults |= Notification.DEFAULT_VIBRATE; - 自定義振動
long[] vibrate = {100, 200, 300, 400}; //震動效果
// 表示在100鹦筹、200、300址貌、400這些時間點交替啟動和關(guān)閉震動 notification.vibrate = vibrate;
3盛龄、閃爍提醒
- 默認閃爍
notification.defaults |= Notification.DEFAULT_LIGHTS; - 自定義閃爍
notification.ledARGB = 0xff00ff00; // LED燈的顏色,綠燈
notification.ledOnMS = 300; // LED燈顯示的毫秒數(shù)芳誓,300毫秒
notification.ledOffMS = 1000; // LED燈關(guān)閉的毫秒數(shù)余舶,1000毫秒
notification.flags |= Notification.FLAG_SHOW_LIGHTS; // 必須加上這個標志
常見的Flags
- FLAG_AUTO_CANCEL
當通知被用戶點擊之后會自動被清除(cancel) - FLAG_INSISTENT
在用戶響應之前會一直重復提醒音 - FLAG_ONGOING_EVENT
表示正在運行的事件 - FLAG_NO_CLEAR
通知欄點擊“清除”按鈕時,該通知將不會被清除 - FLAG_FOREGROUND_SERVICE
表示當前服務是前臺服務
更多Notification屬性詳見Notification锹淌。
That's all匿值! 更多通知知識點等待你來發(fā)掘,歡迎補充!
參考資料
Notifications