在Android系統中,Notification是一種具有全局效果的通知,在App開發中也很常用,今天就記錄一下學習Notification的過程。
老規矩,先來一個搞笑段子:
經常熬夜有三大害處:第一,記憶力越來越差;第二,數學水平下降;第四,記憶力越來越差。
這篇文章Copy自xxbs2003的博文。因爲他寫的太好了,並且我不想寫。
Notification
Notification,俗稱通知,是一種具有全局效果的通知,它展示在屏幕的頂端,首先會表現爲一個圖標的形式,當用戶向下滑動的時候,展示出通知具體的內容。
因爲Android的快速發展,而Android的版本也快速的升級導致了一些兼容性的問題。對於Notification而言,Android3.0是一個分水嶺,在其之前構建Notification推薦使用NotificationCompate.Builder,它位於android.support.v4.app.NotificationCompat.Builder,是一個Android向下版本的兼容包,而在Android3.0之後,一般推薦使用Notification.Builder構建。本博客主要介紹的是Android4.x的開發,所以在這裏使用Notification.Builder進行講解演示。
通知一般通過NotificationManager服務發送一個Notification對象來完成通知,NotificationManager是一個重要的系統級服務,該對象位於應用程序的框架層中,應用程序可以通過它向系統發送全局的通知。使用通知的時候,需要創建一個Notification對象用來承載通知的內容,但是一般不會直接通過Notification的構造方法來得到對象,而是使用它的內部類Notification.Builder來實例化一個Builder對象,並設置通知的各項屬性,最後通過Notification.Builder.builder()方法得到一個Notification對象,當獲得這個Notification對象之後,就可以使用NotificationManager.notify()方法發送通知。
NotificationManager類是一個通知管理器類,這個對象是由系統維護的服務,是以單例模式的方式獲得,所以一般並不直接實例化這個對象。在Activity中,可以使用Activity.getSystemService(String)方法獲取NotificationManager對象,Activity.getSystemService(String)方法可以通過Android系統級服務的句柄,返回對應的對象。在這裏需要返回NotificationManager,所以直接傳遞Context.NOTIFICATION_SERVICE即可。
雖然通知中提供了各種屬性的設置,但是一個通知對象,有幾個屬性是必須要設置的,其他的屬性均是可選的,必須設置的屬性如下:
- 小圖標,使用setSamllIcon()方法設置。
- 標題,使用setContentTitle()方法設置。
- 文本內容,使用setContentText()方法設置。
更新與移除通知
在使用NotificationManager.notify()發送通知的時候,需要傳遞一個標識符,用於唯一標識這個通知。對於有些場景,並不是無限的添加新的通知,有時候需要更新原有通知的信息,這個時候可以重寫構建Notification,而使用與之前通知相同標識符來發送通知,這個時候舊的通知就被被新的通知所取代,起到更新通知的效果。
對於一個通知,當展示在狀態欄之後,但是使用過後,如何取消呢?Android爲我們提供兩種方式移除通知,一種是Notification自己維護,使用setAutoCancel()方法設置是否維護,傳遞一個boolean類型的數據。另外一種方式使用NotificationManager通知管理器對象來維護,它通過notify()發送通知的時候,指定的通知標識Id來操作通知,可以使用cancel(int)來移除一個指定的通知,也可以使用cancelAll()移除所有的通知。
使用NotificationManager移除指定通知示例:
1 NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
2 mNotificationManager.cancel(0);
PendingIntent
對於一個通知而言,它顯示的消息是有限的,一般僅用於提示一些概要信息。但是一般簡短的消息,並不能表達需要告訴用戶的全部內容,所以需要綁定一個意圖,當用戶點擊通知的時候,調用一個意圖展示出一個Activity用來顯示詳細的內容。而Notification中,並不使用常規的Intent去傳遞一個意圖,而是使用PendingIntent。
先來說說Intent和PendingIntent的區別,PendingIntent可以看做是對Intent的包裝,通過名稱可以看出PendingIntent用於處理即將發生的意圖,而Intent用來用來處理馬上發生的意圖。而對於通知來說,它是一系統級的全局通知,並不確定這個意圖被執行的時間。當在應用外部執行PendingIntent時,因爲它保存了觸發應用的Context,使得外部應用可以如在當前應用中一樣,執行PendingIntent裏的Intent,就算執行的時候響應通知的應用已經被銷燬了,也可以通過存在PendingIntent裏的Context照常執行它,並且還可以處理Intent說帶來的額外信息。
PendingIntent提供了多個靜態的getXxx()方法,用於獲得適用於不同場景的PendingIntent對象。一般需要傳遞的幾個參數都很常規,只介紹一個flag參數,用於標識PendingIntent的構造選擇:
- FLAG_CANCEL_CURRENT:如果構建的PendingIntent已經存在,則取消前一個,重新構建一個。
- FLAG_NO_CREATE:如果前一個PendingIntent已經不存在了,將不再構建它。
- FLAG_ONE_SHOT:表明這裏構建的PendingIntent只能使用一次。
- FLAG_UPDATE_CURRENT:如果構建的PendingIntent已經存在,則替換它,常用。
Notification視覺風格
Notification有兩種視覺風格,一種是標準視圖(Normal view)、一種是大視圖(Big view)。標準視圖在Android中各版本是通用的,但是對於大視圖而言,僅支持Android4.1+的版本。
從官方文檔瞭解到,一個標準視圖顯示的大小要保持在64dp高,寬度爲屏幕標準。標準視圖的通知主體內容有一下幾個:
- 通知標題。
- 大圖標。
- 通知內容。
- 通知消息。
- 小圖標。
- 通知的時間,一般爲系統時間,也可以使用setWhen()設置。
下面通過一個示例,模仿上面效果的通知。
1 btnNotification.setOnClickListener(new View.OnClickListener() {
2
3 @Override
4 public void onClick(View v) {
5 Bitmap btm = BitmapFactory.decodeResource(getResources(),
6 R.drawable.msg);
7 NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
8 MainActivity.this).setSmallIcon(R.drawable.msg)
9 .setContentTitle("5 new message")
10 .setContentText("[email protected]");
11 mBuilder.setTicker("New message");//第一次提示消息的時候顯示在通知欄上
12 mBuilder.setNumber(12);
13 mBuilder.setLargeIcon(btm);
14 mBuilder.setAutoCancel(true);//自己維護通知的消失
15
16 //構建一個Intent
17 Intent resultIntent = new Intent(MainActivity.this,
18 ResultActivity.class);
19 //封裝一個Intent
20 PendingIntent resultPendingIntent = PendingIntent.getActivity(
21 MainActivity.this, 0, resultIntent,
22 PendingIntent.FLAG_UPDATE_CURRENT);
23 // 設置通知主題的意圖
24 mBuilder.setContentIntent(resultPendingIntent);
25 //獲取通知管理器對象
26 NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
27 mNotificationManager.notify(0, mBuilder.build());
28 }
29 });
顯示效果:
而對於大視圖(Big View)而言,它的細節區域只能顯示256dp高度的內容,並且只對Android4.1+之後的設備才支持,它比標準視圖不一樣的地方,均需要使用setStyle()方法設定,它大致的效果如下:
setStyle()傳遞一個NotificationCompat.Style對象,它是一個抽象類,Android爲我們提供了三個實現類,用於顯示不同的場景。分別是:
- NotificationCompat.BigPictureStyle, 在細節部分顯示一個256dp高度的位圖。
- NotificationCompat.BigTextStyle,在細節部分顯示一個大的文本塊。
- NotificationCompat.InboxStyle,在細節部分顯示一段行文本。
如果僅僅顯示一個圖片,使用BigPictureStyle是最方便的;如果需要顯示一個富文本信息,則可以使用BigTextStyle;如果僅僅用於顯示一個文本的信息,那麼使用InboxStyle即可。後面會以一個示例來展示InboxStyle的使用,模仿上面圖片的顯示。
實現代碼:
1 btnBigViewNotification.setOnClickListener(new View.OnClickListener() {
2
3 @Override
4 public void onClick(View v) {
5
6 Bitmap btm = BitmapFactory.decodeResource(getResources(),
7 R.drawable.msg);
8 Intent intent = new Intent(MainActivity.this,
9 ResultActivity.class);
10
11 PendingIntent pendingIntent = PendingIntent.getActivity(
12 MainActivity.this, 0, intent,
13 PendingIntent.FLAG_CANCEL_CURRENT);
14
15 Notification noti = new NotificationCompat.Builder(
16 MainActivity.this)
17 .setSmallIcon(R.drawable.msg)
18 .setLargeIcon(btm)
19 .setNumber(13)
20 .setContentIntent(pendingIntent)
21 .setStyle(
22 new NotificationCompat.InboxStyle()
23 .addLine(
24 "M.Twain (Google+) Haiku is more than a cert...")
25 .addLine("M.Twain Reminder")
26 .addLine("M.Twain Lunch?")
27 .addLine("M.Twain Revised Specs")
28 .addLine("M.Twain ")
29 .addLine(
30 "Google Play Celebrate 25 billion apps with Goo..")
31 .addLine(
32 "Stack Exchange StackOverflow weekly Newsl...")
33 .setBigContentTitle("6 new message")
34 .setSummaryText("[email protected]"))
35 .build();
36
37 NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
38 mNotificationManager.notify(0, noti);
39 }
40 });
展示效果: