Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 通知欄Notification的整合 全面學習 (一個DEMO讓你完全了解它)

Android 通知欄Notification的整合 全面學習 (一個DEMO讓你完全了解它)

編輯:關於Android編程

在android的應用層中,涉及到很多應用框架,例如:Service框架,Activity管理機制,Broadcast機制,對話框框架,標題欄框架,狀態欄框架,通知機制,ActionBar框架等等。

下面就來說說經常會使用到通知機制中的通知欄框架(Notificaiton),它適用於交互事件的通知。它是位於頂層可以展開的通知列表。它會時不時的提醒你什麼軟件該更新了,什麼人發你微信消息了等。

(網上看了下,全面介紹的文章不多,所以就萌生了寫這篇的念頭,隨便當作回顧筆記。下面我就通過官方文檔、源代碼、書上的一些資料匯總下這一塊的知識,並通過一個通知欄的匯總DEMO讓大家更好的了解這個類的使用,內容有點多,可以根據需求看目錄學習)。


Notificaiton狀態通知欄:


功能作用


1.顯示接收到短消息、即使消息等信息 (如QQ、微信、新浪、短信)
2.顯示客戶端的推送消息(如有新版本發布,廣告,推薦新聞等)
3.顯示正在進行的事物(例如:後台運行的程序)(如音樂播放器、版本更新時候的下載進度等)


思維導圖結構


思維導圖的大體結構(按照各個節點延伸拓展學習)

Notificaiton -- service -- BroadcastReceiver -- Intent(flag、Action等屬性應用) -- PendingIntent

感慨:

一個Notificaiton通知的拓展使用就要涉及與4大組建的配合,所以學好整體的知識體系。

聯系:

1.由於service 是在後台運行,所以它意圖做什麼我們看不到,可以通過Notificaiton 來顯示提醒(如音樂的後台播放)。

2.service服務和BroadcastReceiver廣播相結合,在加上Notificaiton 顯示(如程序的後台更新)。

3.Intent作為意圖處理,和Notificaiton的點擊時間緊密結合在了一起,並且與BroadcastReceiver和service的聯系也緊密不可以分割。

(service 在後台之後通過BroadcastReceiver來通知Notificaiton 顯示相關東西,在通過Intent完成用戶的意圖操作)

相關文檔:Activity啟動模式 及 Intent Flags 與 棧 的關聯分析


對應的官方鏈接


設計文檔 : 官方:http://developer.android.com/design/patterns/notifications.html
譯文:http://adchs.github.io/patterns/notifications.html 使用教程 :http://developer.android.com/training/notify-user/index.html 開發文檔 :http://developer.android.com/reference/android/app/Notification.html


大體了解


Notification支持文字內容顯示、震動三色燈鈴聲等多種提示形式,在默認情況下,Notification僅顯示消息標題消息內容送達時間這3項內容。以下就是通知的基本布局。

通知的基本布局

\

普通視圖:

高度64dp<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+CrTzytTNvLXEzajWqtTa1bm/qsew0rLP1Mq+zqrG1c2oytPNvDwvcD4KPGltZyBzcmM9"/uploadfile/Collfiles/20140515/2014051509025512.png" alt="\" name="figure3" height="153" title="Android文檔筆記:通知(一)">

元素:

1. 標題 Title/Name

2. 大圖標 Icon/Photo

3. 內容文字

4. 內容信息 MESSAGE

5. 小圖標 Secondary Icon

6. 通知的時間 Timestamp,默認為系統發出通知的時間,也可通過setWhen()來設置



相關分析


狀態通知欄主要涉及到2個類: Notification 和 NotificationManager

Notification為通知信息類,它裡面對應了通知欄的各個屬性

NotificationManager : 是狀態欄通知的管理類,負責發通知、清除通知等操作。

注意:NotificationManager 是一個系統Service,所以必須通過 getSystemService(NOTIFICATION_SERVICE)方法來獲取,方法如下。

NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);


使用步驟:


流程模塊:

第一步:

創建一個通知欄的Builder構造類 (Create a Notification Builder)

第二步:

定義通知欄的Action (Define the Notification's Action)

第三步:

設置通知欄點擊事件 (Set the Notification's Click Behavior)

第四步:

通知 (Issue the Notification)


代碼模塊:


實現系統默認的通知欄效果:

第一步:獲取狀態通知欄管理:

NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);


第二步:實例化通知欄構造器NotificationCompat.Builder:

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);


第三步:對Builder進行配置:

mBuilder.setContentTitle("測試標題")//設置通知欄標題
	.setContentText("測試內容") //設置通知欄顯示內容
	.setContentIntent(getDefalutIntent(Notification.FLAG_AUTO_CANCEL)) //設置通知欄點擊意圖
//	.setNumber(number) //設置通知集合的數量
	.setTicker("測試通知來啦") //通知首次出現在通知欄,帶上升動畫效果的
	.setWhen(System.currentTimeMillis())//通知產生的時間,會在通知信息裡顯示,一般是系統獲取到的時間
	.setPriority(Notification.PRIORITY_DEFAULT) //設置該通知優先級
//	.setAutoCancel(true)//設置這個標志當用戶單擊面板就可以讓通知將自動取消  
	.setOngoing(false)//ture,設置他為一個正在進行的通知。他們通常是用來表示一個後台任務,用戶積極參與(如播放音樂)或以某種方式正在等待,因此占用設備(如一個文件下載,同步操作,主動網絡連接)
	.setDefaults(Notification.DEFAULT_VIBRATE)//向通知添加聲音、閃燈和振動效果的最簡單、最一致的方式是使用當前的用戶默認設置,使用defaults屬性,可以組合
	//Notification.DEFAULT_ALL  Notification.DEFAULT_SOUND 添加聲音 // requires VIBRATE permission
	.setSmallIcon(R.drawable.ic_launcher);//設置通知小ICON


對應的各個方法的屬性(部分方法以上代碼中已經作注釋,就不再介紹):

(1)方法:設置提醒標志符Flags

功能:提醒標志符,向通知添加聲音、閃燈和振動效果等設置達到通知提醒效果,可以組合多個屬性

有2種設置方法:

1.實例化通知欄之後通過給他添加.flags屬性賦值。

		Notification notification = mBuilder.build();
		notification.flags = Notification.FLAG_AUTO_CANCEL;
2.通過setContentIntent(PendingIntent intent)方法中的意圖設置對應的flags

	public PendingIntent getDefalutIntent(int flags){
		PendingIntent pendingIntent= PendingIntent.getActivity(this, 1, new Intent(), flags);
		return pendingIntent;
	}
提醒標志符成員:

Notification.FLAG_SHOW_LIGHTS //三色燈提醒,在使用三色燈提醒時候必須加該標志符

Notification.FLAG_ONGOING_EVENT //發起正在運行事件(活動中)

Notification.FLAG_INSISTENT //讓聲音、振動無限循環,直到用戶響應 (取消或者打開)

Notification.FLAG_ONLY_ALERT_ONCE //發起Notification後,鈴聲和震動均只執行一次

Notification.FLAG_AUTO_CANCEL //用戶單擊通知後自動消失

Notification.FLAG_NO_CLEAR //只有全部清除時,Notification才會清除 ,不清楚該通知(QQ的通知無法清除,就是用的這個)

Notification.FLAG_FOREGROUND_SERVICE //表示正在運行的服務


(2)方法:.setDefaults(int defaults) (NotificationCompat.Builder中的方法,用於提示)


功能:向通知添加聲音、閃燈和振動效果的最簡單、使用默認(defaults)屬性,可以組合多個屬性(和方法1中提示效果一樣的)

對應屬性:

Notification.DEFAULT_VIBRATE //添加默認震動提醒 需要 VIBRATE permission

Notification.DEFAULT_SOUND // 添加默認聲音提醒

Notification.DEFAULT_LIGHTS// 添加默認三色燈提醒

Notification.DEFAULT_ALL// 添加默認以上3種全部提醒


(3)方法:setVibrate(long[] pattern)


功能:設置震動方式。

使用:

.setVibrate(new long[] {0,300,500,700});
實現效果:延遲0ms,然後振動300ms,在延遲500ms,接著在振動700ms。

以上方法的還有種寫法是

mBuilder.build().vibrate = new long[] {0,300,500,700};
以此類推,2種寫法都可以。

如果希望設置默認振動方式,設置了方法(2)中默認為DEFAULT_VIBRATE 即可。


(4)方法:.setLights(intledARGB ,intledOnMS ,intledOffMS )


功能:android支持三色燈提醒,這個方法就是設置不同場景下的不同顏色的燈。

描述:其中ledARGB 表示燈光顏色、 ledOnMS 亮持續時間、ledOffMS 暗的時間。

注意:1)只有在設置了標志符Flags為Notification.FLAG_SHOW_LIGHTS的時候,才支持三色燈提醒。

2)這邊的顏色跟設備有關,不是所有的顏色都可以,要看具體設備。


使用:

.setLights(0xff0000ff, 300, 0)
同理,以下方法也可以設置同樣效果:

		Notification notify = mBuilder.build();
		notify.flags = Notification.FLAG_SHOW_LIGHTS;
		notify.ledARGB = 0xff0000ff;
		notify.ledOnMS = 300;
		notify.ledOffMS = 300;
如果希望使用默認的三色燈提醒,設置了方法(2)中默認為DEFAULT_LIGHTS即可。

(5)方法:.setSound(Uri sound)


功能:設置默認或則自定義的鈴聲,來提醒。

		//獲取默認鈴聲
		.setDefaults(Notification.DEFAULT_SOUND)
		//獲取自定義鈴聲
		.setSound(Uri.parse("file:///sdcard/xx/xx.mp3"))
		//獲取Android多媒體庫內的鈴聲
		.setSound(Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "5"))

同理相同效果的另一種設置方法這邊就不講, 和上面的都是一樣的。


(6)方法:.setPriority(int pri)


功能:設置優先級

對應優先級描述如下圖:

優先級 用戶 MAX 重要而緊急的通知,通知用戶這個事件是時間上緊迫的或者需要立即處理的。 HIGH 高優先級用於重要的通信內容,例如短消息或者聊天,這些都是對用戶來說比較有興趣的。 DEFAULT 默認優先級用於沒有特殊優先級分類的通知。 LOW 低優先級可以通知用戶但又不是很緊急的事件。 MIN 用於後台消息 (例如天氣或者位置信息)。最低優先級通知將只在狀態欄顯示圖標,只有用戶下拉通知抽屜才能看到內容。 \

對應屬性(作用看上圖就可知道):

Notification.PRIORITY_DEFAULT

Notification.PRIORITY_HIGH

Notification.PRIORITY_LOW

Notification.PRIORITY_MAX

Notification.PRIORITY_MIN


(7)方法:setOngoing(boolean ongoing)


功能:設置為ture,表示它為一個正在進行的通知。他們通常是用來表示一個後台任務,用戶積極參與(如播放音樂)或以某種方式正在等待,因此占用設備(如一個文件下載,同步操作,主動網絡連接)


(8)方法:setProgress(int max, int progress,boolean indeterminate)


屬性:max:進度條最大數值 、progress:當前進度、indeterminate:表示進度是否不確定,true為不確定,如下第3幅圖所示 ,false為確定下第1幅圖所示

功能:設置帶進度條的通知,可以在下載中使用

效果圖如下:

\ \

注意:此方法在4.0及以後版本才有用,如果為早期版本:需要自定義通知布局,其中包含ProgressBar視圖

使用:如果為確定的進度條:調用setProgress(max, progress, false)來設置通知,在更新進度的時候在此發起通知更新progress,並且在下載完成後要移除進度條,通過調用setProgress(0, 0, false)既可。

如果為不確定(持續活動)的進度條,這是在處理進度無法准確獲知時顯示活動正在持續,所以調用setProgress(0, 0, true) ,操作結束時,調用setProgress(0, 0, false)並更新通知以移除指示條



第四步:設置通知欄PendingIntent(點擊動作事件等都包含在這裡)

在第三步中,沒有提到一個方法,就是setContentIntent(PendingIntent intent)這個方法,這裡拿到這裡講。



知識點

1)什麼是PendingIntent


PendingIntent和Intent略有不同,它可以設置執行次數,主要用於遠程服務通信、鬧鈴、通知、啟動器、短信中,在一般情況下用的比較少。


2)PendingIntent什麼用


Notification支持多種Intent來響應單擊事件、消除事件、處理緊急狀態的全屏事件等。

這裡就用到了setContentIntent(PendingIntent intent)來處理以上這麼多的事件。


3)相關屬性和方法

屬性:

PendingIntent的位標識符:

FLAG_ONE_SHOT 表示返回的PendingIntent僅能執行一次,執行完後自動取消

FLAG_NO_CREATE 表示如果描述的PendingIntent不存在,並不創建相應的PendingIntent,而是返回NULL

FLAG_CANCEL_CURRENT 表示相應的PendingIntent已經存在,則取消前者,然後創建新的PendingIntent,這個有利於數據保持為最新的,可以用於即時通信的通信場景

FLAG_UPDATE_CURRENT 表示更新的PendingIntent


方法:

\

可以看出,它支持多種相應方式,有Activity、Broadcast、Service,就根據你自身需求去選擇。


在各種情況下情況下它還會根據各種情況出發效果:

contentIntent:在通知窗口區域,Notification被單擊時的響應事件由該intent觸發;

deleteIntent:當用戶點擊全部清除按鈕時,響應該清除事件的Intent;

fullScreenIntent:響應緊急狀態的全屏事件(例如來電事件),也就是說通知來的時候,跳過在通知區域點擊通知這一步,直接執行fullScreenIntent代表的事件。


例如:在執行了點擊通知之後要跳轉到指定的XXX的Activity的時候,可以設置以下方法來相應點擊事件:

Intent intent = new Intent(context,XXX.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
mBuilder.setContentIntent(pendingIntent)


例如:在執行了清空全部的通知操作時候,可以設置以下方法來相應這個事件:

采用setDeleteIntent(PendingIntent intent)方法或按照以下寫法

Intent deleteIntent = new Intent();
deleteIntent.setClass(context, XXXReceiver.class);
deleteIntent.setAction(DELETE_ACTION);
notification.deleteIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);

例如:在響應緊急事件(如來電)時候,可以設置以下方法來相應這個事件:

采用setFullScreenIntent(PendingIntent intent, boolean highPriority)


第五步,最簡單的一部,發送通知請求

mNotificationManager.notify(notifyId, mBuilder.build());



拓展


實現自定義的通知欄效果:

這裡要用到RemoteViews這個類。實現以下2種自定義布局。


注意:

Notification的自定義布局是RemoteViews,和其他RemoteViews一樣,在自定義視圖布局文件中,僅支持FrameLayout、LinearLayout、RelativeLayout三種布局控件和AnalogClock、Chronometer、Button、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView和AdapterViewFlipper這些顯示控件,不支持這些類的子類或Android提供的其他控件。否則會引起ClassNotFoundException異常


步驟如下:

1)創建自定義視圖

2)獲取遠程視圖對象(注:Notification的contentView不能為空)

3)設置PendingIntent(來響應各種事件)

4)發起Notification

大體4步驟這裡就不詳細說了,下面就把DEMO中的列子拿出來說下


樣式:

1.自定義帶按鈕通知欄(如下樣式)

正在進行的

“正在進行的”通知使用戶了解正在運行的後台進程。例如,音樂播放器可以顯示正在播放的音樂。也可以用來顯示需要長時間處理的操作,例如下載或編碼視頻。“正在進行的”通知不能被手動刪除。

\




實現方法如下:
/**
	 * 帶按鈕的通知欄
	 */
	public void showButtonNotify(){
		NotificationCompat.Builder mBuilder = new Builder(this);
		RemoteViews mRemoteViews = new RemoteViews(getPackageName(), R.layout.view_custom_button);
		mRemoteViews.setImageViewResource(R.id.custom_song_icon, R.drawable.sing_icon);
		//API3.0 以上的時候顯示按鈕,否則消失
		mRemoteViews.setTextViewText(R.id.tv_custom_song_singer, "周傑倫");
		mRemoteViews.setTextViewText(R.id.tv_custom_song_name, "七裡香");
		//如果版本號低於(3。0),那麼不顯示按鈕
		if(BaseTools.getSystemVersion() <= 9){
			mRemoteViews.setViewVisibility(R.id.ll_custom_button, View.GONE);
		}else{
			mRemoteViews.setViewVisibility(R.id.ll_custom_button, View.VISIBLE);
		}
		//
		if(isPlay){
			mRemoteViews.setImageViewResource(R.id.btn_custom_play, R.drawable.btn_pause);
		}else{
			mRemoteViews.setImageViewResource(R.id.btn_custom_play, R.drawable.btn_play);
		}
		//點擊的事件處理
		Intent buttonIntent = new Intent(ACTION_BUTTON);
		/* 上一首按鈕 */
		buttonIntent.putExtra(INTENT_BUTTONID_TAG, BUTTON_PREV_ID);
		//這裡加了廣播,所及INTENT的必須用getBroadcast方法
		PendingIntent intent_prev = PendingIntent.getBroadcast(this, 1, buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
		mRemoteViews.setOnClickPendingIntent(R.id.btn_custom_prev, intent_prev);
		/* 播放/暫停  按鈕 */
		buttonIntent.putExtra(INTENT_BUTTONID_TAG, BUTTON_PALY_ID);
		PendingIntent intent_paly = PendingIntent.getBroadcast(this, 2, buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
		mRemoteViews.setOnClickPendingIntent(R.id.btn_custom_play, intent_paly);
		/* 下一首 按鈕  */
		buttonIntent.putExtra(INTENT_BUTTONID_TAG, BUTTON_NEXT_ID);
		PendingIntent intent_next = PendingIntent.getBroadcast(this, 3, buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
		mRemoteViews.setOnClickPendingIntent(R.id.btn_custom_next, intent_next);
		
		mBuilder.setContent(mRemoteViews)
				.setContentIntent(getDefalutIntent(Notification.FLAG_ONGOING_EVENT))
				.setWhen(System.currentTimeMillis())// 通知產生的時間,會在通知信息裡顯示
				.setTicker("正在播放")
				.setPriority(Notification.PRIORITY_DEFAULT)// 設置該通知優先級
				.setOngoing(true)
				.setSmallIcon(R.drawable.sing_icon);
		Notification notify = mBuilder.build();
		notify.flags = Notification.FLAG_ONGOING_EVENT;
		mNotificationManager.notify(notifyId, notify);
	}
注意:帶按鈕的布局相應點擊事件在3.0以下版本沒有用,所以這邊作了系統版本判斷,來顯示消失按鈕。


2.自定義不帶按鈕通知欄


實現方法如下:
		//先設定RemoteViews
		RemoteViews view_custom = new RemoteViews(getPackageName(), R.layout.view_custom);
		//設置對應IMAGEVIEW的ID的資源圖片
		view_custom.setImageViewResource(R.id.custom_icon, R.drawable.icon);
//		view_custom.setInt(R.id.custom_icon,"setBackgroundResource",R.drawable.icon);
		view_custom.setTextViewText(R.id.tv_custom_title, "今日頭條");
		view_custom.setTextViewText(R.id.tv_custom_content, "金州勇士官方宣布球隊已經解雇了主帥馬克-傑克遜,隨後宣布了最後的結果。");


之後調用:
mBuilder.setContent(view_custom)
來設定自定義的這個布局。



實現:大視圖風格通知(注:4.1之前的版本不支持大視圖)


只在通知被展開時顯示

何時展開:通知處在頂端,或者用戶通過收拾展開

收件箱風格的通知:

相比普通視圖,只多出:7. 詳情區域


效果圖如下: \
詳情區域根據用途可有多種風格:

1.NotificationCompat.BigPictureStyle 大圖片風格:詳情區域包含一個256dp高度的位圖

2.NotificationCompat.BigTextStyle 大文字風格:顯示一個大的文字塊

3.NotificationCompat.InboxStyle 收件箱風格:顯示多行文字


各種風格都具有以下常規視圖不具有的內容選項:

1.大標題:在展開視圖時替代普通視圖的標記

2.總結文字:允許你在詳情區域之下增加一行內容


拿收件箱風格為例,實現代碼如下:
		NotificationCompat.BigPictureStyle inboxStyle = new NotificationCompat.InboxStyle();
		String[] events = new String[5];
		// Sets a title for the Inbox style big view
		inboxStyle.setBigContentTitle("大視圖內容:");
		// Moves events into the big view
		for (int i=0; i < events.length; i++) {
		    inboxStyle.addLine(events[i]);
		}
		mBuilder.setContentTitle("測試標題")
				.setContentText("測試內容")
//				.setNumber(number)//顯示數量
				.setStyle(inboxStyle)//設置風格
				.setTicker("測試通知來啦");



開發中碰到的問題

(注:下面所指的低版本是指2.3及2.3以下版本)

1.如何取消掉通知欄上的通知

(1)設置對應的flags,讓用戶點擊既被消除:

notification.flags = FLAG_AUTO_CANCEL;

(2) 通過手動消除某項或則全部通知

mNotificationMgr.cancle(NOTIFICATION_ID);//消除對應ID的通知

mNotificationMgr.cancleAll();//消除創建的所有通知


2.低版本中的部分方法已經被棄用的

(1)Notification.Builder(this).getNotification()

(2)mNotification.setLatestEventInfo(this, "title", "content", null);

這些方法都已經被啟用,雖然還有效果,可是不建議使用。所以開發過程中盡量使用NotificationCompat.Builder(this)的構建方法去創建一個通知類。


3.低版本中會報的錯誤及解決方案:

(1)錯誤代碼:java.lang.IllegalArgumentException: contentIntent required: pkg=com.example.notifications id=100 notification=Notification(vibrate=default,sound=null,defaults=0x2,flags=0x0)

解決方案:如果在高版本不會出錯,而在2.3上面報了這個錯誤,通過開發文檔中的以下知道你可以找打:

For this reason, you should always ensure that UI controls in a notification are also available in an Activity in your app, and you should always start that Activity when users click the notification. To do this, use the setContentIntent() method.

你就應該知道,缺少了setContentIntent() 這個方法,在2.3及更低的版本中,必須給它設置設置contentIntent,如果你點擊沒有意圖,可以在賦值的的Intent中設置為new Intent()既可,切記contentIntent不能為空。

代碼如下:

	public PendingIntent getDefalutIntent(int flags){
		PendingIntent pendingIntent= PendingIntent.getActivity(this, 1, new Intent(), flags);
		return pendingIntent;
	}


(2)錯誤代碼:android.app.RemoteServiceException: Bad notification posted from package com.example.notifications: Couldn't expand RemoteViews for: StatusBarNotification(package=com.example.notifications id=101 tag=null notification=Notification(vibrate=null,sound=null,defaults=0x0,flags=0x2))

解決方法:

在自定義的時候,發現了這個問題,解決:每次更新時都必須把RemoteViews給new出來才行,不能利用已有的notification.contentView直接操作!


4.低版本中,自定義的通知欄中如果帶有按鈕,可能按鈕點擊事件會失靈

解決方法:看其它的應用,好像在低版本都會隱藏掉那些按鈕,就是為了不影響用戶體驗,所以應該就這麼解決,判斷版本號在去決定是否現在按鈕。


5.低版本中,自定義布局中的字體顏色看不清

如右圖:\

解決方案:

由於2.3及之前版本,背景設是白色的那我們定義字體顏色為系統預設的顏色:

?android:attr/textColorPrimary

在資源的src/values目錄中的style.xml文件中設置它標題和內容的樣式為:

  
  
  
      
  
      
  


在2.3之後的版本中(即API >=9的版本中),在資源文件下的src/values-v9目錄中的style.xml文件中設置它標題和內容的樣式為: