Notification簡介
通知是在常規UI界面之外向用戶展示消息的工具,當系統發出通知時,它會以圖表的形式顯示在狀態欄中。此時打開通知欄,就可以看到通知的詳細信息了。創建通知由Notification.Builder類來控制(API 11添加)。另外,v4的支持庫也提供了創建通知的類 NotificationCompat.Builder
。在API 11 之前,通知的創建由new Notification()
直接創建,現在不建議使用了。
創建Notification
創建通知通過NotificationCompat.Builder
,創建完成之后,調用NotificationCompat.Builder.build()
方法獲取Notification對象,此時通知已經創建好了,下一步發出通知使用NotificationManager.notify()
就可以將通知發送出去了。
創建通知的時候可以在Builder中對通知進行設置,包括圖標,標題,點擊響應等等。有三個基本參數是必須要包含的:
小圖標,由
setSmallIcon()
設置
標題,由setContentTitle()
設置
詳細文本,由setContentText()
設置
下面是一個通知的例子,基本上包含了常用的各項設置:
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_action_new) //設置小圖標,用于狀態欄左上角顯示
.setContentTitle("Notification Title") //設置標題
.setContentText("Notification content text.")
.setContentInfo("Content info")
.setSubText("sub text")
.setTicker("ticker...") //通知到來時狀態欄閃過的信息,API21以后不再顯示
.setDefaults(NotificationCompat.DEFAULT_ALL)//設置默認的燈光,提示音和振動,可選值:DEFAULT_ALL,DEFAULT_SOUND,DEFAULT_VIBRATE,DEFAULT_LIGHTS
// .setLights()
// .setSound()
// .setVibrate()
.setNumber(10) //已經被 setSubText取代,顯示在時間下方的內容
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)//5.0以后添加
.setWhen(System.currentTimeMillis()) //設置通知上顯示的時間
.setShowWhen(true) //通知是否顯示時間
.setUsesChronometer // 設置是否顯示時鐘表示時間
.setChronometerCountDown(false); // 設置時鐘是否為倒計時
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.largeicon)) //設置大圖標
.setPriority(NotificationCompat.PRIORITY_MAX) //設置等級,可選值有PRIORITY_MIN(-2),PRIORITY_LOW(-1),PRIORITY_DEFAULT(0),PRIORITY_HIGH(1),PRIORITY_MAX(2),默認為0
.setOngoing(false) //設置是否為正在進行的通知。設置為true表示有相關動作正在執行,比如播放音樂。ongoing狀態的通知是不會自動消失,也不能手動清除的。除非調用Manager的cancel方法
.setAutoCancel(true) //是否自動消失,true表示響應點擊之后自動消失。
.build(); //API16添加,API11使用getNotification()
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(1, notification);
setVisibility
方法有以下可選值:
-
VISIBILITY_PUBLIC
任何情況下都顯示通知的完整內容。 -
VISIBILITY_SECRET
不會在鎖定屏幕上顯示此通知的任何部分。 -
VISIBILITY_PRIVATE
顯示通知圖標和內容標題等基本信息,但是隱藏通知的完整內容。
設置 VISIBILITY_PRIVATE 后,還可以通過 setPublicVersion() 提供其中隱藏了某些詳細信息的替換版本通知內容。
PendingIntent
為通知設定點擊事件,需要使用PendingIntent實現。與Intent相比,PendingIntent表示一種特定的處于等待狀態,即將發生的一種狀態,而Intent則是馬上發生的。PendingIntent可以表示三種意圖:
- getActivity(Context context, int requestCode, Intent intent, int flags)
- getService(Context context, int requestCode, Intent intent, int flags)
- getBroadcast(Context context, int requestCode, Intent intent, int flags)
requestCode
表示PendingIntent發送方的請求碼,它會對PendingIntent的匹配產生影響,當PendingIntent包含的Intent相同,而且requestCode也相同,系統就為認為這是同樣的PendingIntent(Extras不影響)。
flags
常用的值有四個:
-
FLAG_ONE_SHOT
表示該PendingIntent只能被使用一次,使用完之后就自動cancel。 -
FLAG_NO_CREATE
不會主動創建PendingIntent,如果之前不存在該PendingIntent,get方法返回null,調用失敗。 -
FLAG_CANCEL_CURRENT
當前PendingIntent如果已經存在了,那么cancel掉存在的,然后重新創建一個。 -
FLAG_UPDATE_CURRENT
當前PendingIntent如果已經存在了,它們都會被更新,替換成新的Extras。
我們使用notify發送通知的時候,如果id相同,會被認為是同一個通知,更新通知的狀態。如果發送一系列id不同,內容相同的通知(包括同樣的PendingIntent),這時候點擊事件就會根據不同的flag做出不同的判斷了。
系統會認為這一系列通知的PendingIntent是同樣的,所以如果flag是FLAG_ONE_SHOT,第一個點擊的通知會響應事件,剩余的通知在點擊的時候就不會有動作了,因為PendingIntent已經被cancel。如果flag是FLAG_CANCEL_CURRENT,那么,每次發送一個通知,系統就會發現PendingIntent已經存在了,于是cancel掉存在的PendingIntent,再生成一個新的,只能給自己用,所以只有最后一個會被響應。如果是FLAG_UPDATE_CURRENT,每發送一條,它都會更新當前存在的所有PendingIntent,并替換為最新的Extras,所以,每個通知都會正常響應。
為通知設置事件,通常情況下這兩個參數都設置為0就可以了:
Intent intent = new Intent(this, SplashActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0 , intent, 0);
builder.setContentIntent(pi)
設置PendingIntent有三個方法:
-
setContentIntent
點擊通知內容 -
setDeleteIntent()
通知被清除時 -
setFullScreenIntent()
全屏事件的Intent,比如在通話時。設置了該項,通知會以浮動的形式閃出
浮動通知是5.0新加的功能,如果通知的優先級設置較高,或者設置了setFullScreenIntent
,通知到來的時候手機處于活動狀態(點亮屏幕且未鎖屏),這是通知會從頂部自動閃出,并且可以響應點擊。
事件進階-TaskStackBuilder
Android中使用任務棧來管理Activity,這個應該都很清楚了,現在考慮這么一種情況:通過點擊通知欄打開一個Activity,這時候,通過Back返回,就會銷毀當前Activity,直接返回桌面了,如果我們想返回該應用的首頁,而不是退出,就要用到TaskStackBuilder。
我們先看一下TaskStackBuilder的使用方法:
Intent intent = new Intent(this, SplashActivity.class);// 構建一個指向SplashActivity.class的Intent
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);//獲取TaskStackBuilder
stackBuilder.addParentStack(SplashActivity.class)
stackBuilder.addNextIntent(intent);
PendingIntent pi2 = stackBuilder.getPendingIntent(0,0);
首先通過TaskStackBuilder.create(this)
創建一個任務棧,下一步方法是addParentStack
,這個方法比較奇葩,我們這里指定的是SplashActivity.class
,實際上它添加的并不是SplashActivity
。它需要與Manifest中的對應Activity的parentActivityName
屬性結合使用。
<activity
android:name=".SplashActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:parentActivityName=".DrawableActivity"
>
SplashActivity
指定了它的父Activity為DrawableActivity
,所以我們調用addParentStack(SplashActivity.class)
之后,此時返回棧中只是添加了DrawableActivity
addNextIntent
用來繼續向返回棧添加Activity,這里才將SplashActivity
添加進來。當然我們也可以繼續創建指向其他Activity的Intent,使用addNextIntent
向返回棧中添加新的Activity,最后添加的Activity處于最頂層,依次向下。(實際上addParentStack
并不是必須的,系統使用addNextIntent
添加Activity進棧時,仍然會讀取它的android:parentActivityName
并添加對應的父Activity。另外,請不要對被設為parentActivity的Activity再設置android:parentActivityName
,會導致ANR)
使用TaskStackBuilder之后,不能根據intent來創建PendingIntent了,需要使用getPendingIntent
方法,獲取到之后設置給Notification,這樣就實現了指定返回Activity的功能。
為Activity指定任務棧
上面介紹了創建任務棧并管理其中的Activity,從而實現返回指定Activity的功能。但是,有時候我們需要的功能很簡單,點擊通知打開Activity,按下Back鍵返回桌面。此時,如果Activity所在的應用處于開啟狀態,新開啟的Activity會直接添加到當前應用的棧中,所以按下Back之后返回的是應用而不是桌面。
要實現這種功能很簡單,為新建的Activity創建新的任務棧就可以了。
首先設置要啟動的Activity屬性:
<activity>
......
android:taskAffinity="" //指定任務棧的Affinity,與Intent的NEW_TASK相結合,在新的任務棧啟動
android:excludeFromRecents="true">//不顯示在最近任務列表
</activity>
然后:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
再設置PendingIntent給通知就可以了。FLAG_ACTIVITY_CLEAR_TASK
表示清空要啟動的Activity所處的任務棧,確保android:taskAffinity
指定的值唯一的情況下可以不設置。
其他常用設置
進度條通知
使用setProgress(max, progress, false)
來設置及進度條通知,并更新進度。第三個參數設置為true表示循環滾動不顯示準確進度的進度條。注意進度條與subContent不能同時設置,否則進度條不能顯示。-
設置樣式
setStyle()
系統已經提供了幾個樣式給我們使用,有
BigPictureStyle
,BigTextStyle
,MessagingStyle
,InboxStyle
等。
自定義外觀
我們可以通過RemoteView來對通知欄進行自定義View的設置。有四個相關方法
setContent
設置普通視圖,高度限制為 64 dp
setCustomContentView
設置普通視圖,高度限制為 64 dp
setCustomBigContentView()
設置擴展視圖,高度可以擴展到256dp
setCustomHeadsUpContentView()
設置浮動通知視圖