Android通知Notification詳解

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()

    系統已經提供了幾個樣式給我們使用,有BigPictureStyleBigTextStyleMessagingStyleInboxStyle等。

自定義外觀

我們可以通過RemoteView來對通知欄進行自定義View的設置。有四個相關方法

setContent 設置普通視圖,高度限制為 64 dp
setCustomContentView設置普通視圖,高度限制為 64 dp
setCustomBigContentView() 設置擴展視圖,高度可以擴展到256dp
setCustomHeadsUpContentView() 設置浮動通知視圖

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

推薦閱讀更多精彩內容