在android的應用層中,涉及到很是多應用框架。好比:Service框架,Activity管理機制,Broadcast機制,對話框框架,標題欄框架,狀態欄框架。通知機制,ActionBar框架等等。html
如下就來講說經常會使用到通知機制中的通知欄框架(Notificaiton)。它適用於交互事件的通知。它是位於頂層可以展開的通知列表。它會時不時的提醒你什麼軟件該更新了,什麼人發你微信消息了等。java
(網上看了下,全面介紹的文章很少,因此就萌生了寫這篇的念頭,隨便看成回想筆記。如下我就經過官方文檔、源碼、書上的一些資料彙總下這一塊的知識。並經過一個通知欄的彙總DEMO讓你們更好的瞭解這個類的使用,內容有點多,可以依據需求看文件夾學習)。android
Notificaiton狀態通知欄:git
1.顯示接收到短消息、即便消息等信息 (如QQ、微信、新浪、短信)
2.顯示client的推送消息(若有新版本號公佈。廣告,推薦新聞等)
3.顯示正在進行的事物(好比:後臺執行的程序)(如音樂播放器、版本號更新時候的下載進度等)github
思惟導圖的大致結構(依照各個節點延伸拓展學習)微信
Notificaiton -- service -- BroadcastReceiver -- Intent(flag、Action等屬性應用) -- PendingIntent
網絡
感慨:app
一個Notificaiton通知的拓展使用就要涉及與4大組建的配合,因此學好整體的知識體系。框架
聯繫:ide
1.由於service 是在後臺執行,因此它意圖作什麼咱們看不到,可以經過Notificaiton 來顯示提醒(如音樂的後臺播放)。
2.service服務和BroadcastReceiver廣播相結合,在加上Notificaiton 顯示(如程序的後臺更新)。
3.Intent做爲意圖處理。和Notificaiton的點擊時間緊密結合在了一塊兒,並且與BroadcastReceiver和service的聯繫也緊密不可以切割。
(service 在後臺以後經過BroadcastReceiver來通知Notificaiton 顯示相關東西,在經過Intent完畢用戶的意圖操做)
相關文檔:Activity啓動模式 及 Intent Flags 與 棧 的關聯分析
Notification支持文字內容顯示、震動、三色燈、鈴聲等多種提示形式,在默認狀況下,Notification僅顯示消息標題、消息內容、送達時間這3項內容。下面就是通知的基本佈局。
通知的基本佈局:
普通視圖:
高度64dp
大試圖的通知在展開前也顯示爲普通視圖
元素:
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
功能:提醒標誌符。向通知加入聲音、閃燈和振動效果等設置達到通知提醒效果,可以組合多個屬性
有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 //表示正在執行的服務
功能:向通知加入聲音、閃燈和振動效果的最簡單、使用默認(defaults)屬性。可以組合多個屬性(和方法1中提示效果同樣的)
相應屬性:
Notification.DEFAULT_VIBRATE //加入默認震動提醒 需要 VIBRATE permissionNotification.DEFAULT_SOUND // 加入默認聲音提醒
Notification.DEFAULT_LIGHTS// 加入默認三色燈提醒Notification.DEFAULT_ALL// 加入默認以上3種全部提醒
功能:設置震動方式。
使用:
.setVibrate(new long[] {0,300,500,700});實現效果:延遲0ms,而後振動300ms。在延遲500ms,接着在振動700ms。
以上方法的還有種寫法是
mBuilder.build().vibrate = new long[] {0,300,500,700};以此類推,2種寫法都可以。
假設但願設置默認振動方式,設置了方法(2)中默以爲DEFAULT_VIBRATE 就能夠。
功能: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就能夠。
功能:設置默認或則本身定義的鈴聲,來提醒。
//獲取默認鈴聲 .setDefaults(Notification.DEFAULT_SOUND) //獲取本身定義鈴聲 .setSound(Uri.parse("file:///sdcard/xx/xx.mp3")) //獲取Android多媒體庫內的鈴聲 .setSound(Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "5"))
同理一樣效果的還有一種設置方法這邊就不講, 和上面的都是同樣的。
功能:設置優先級
相應優先級描寫敘述例如如下圖:
優先級 | 用戶 |
---|---|
MAX | 重要而緊急的通知,通知用戶這個事件是時間上緊迫的或者需要立刻處理的。 |
HIGH | 高優先級用於重要的通訊內容,好比短消息或者聊天,這些都是對用戶來講比較有興趣的。 |
DEFAULT | 默認優先級用於沒有特殊優先級分類的通知。 |
LOW | 低優先級可以通知用戶但又不是很是緊急的事件。 |
MIN | 用於後臺消息 (好比天氣或者位置信息)。最低優先級通知將僅僅在狀態欄顯示圖標,僅僅實用戶下拉通知抽屜才幹看到內容。 |
相應屬性(做用看上圖就可知道):
Notification.PRIORITY_DEFAULT
Notification.PRIORITY_HIGH
Notification.PRIORITY_LOWNotification.PRIORITY_MAX
Notification.PRIORITY_MIN
功能:設置爲ture,表示它爲一個正在進行的通知。
他們通常是用來表示一個後臺任務,用戶積極參與(如播放音樂)或以某種方式正在等待,所以佔用設備(如一個文件下載,同步操做,主動網絡鏈接)
屬性: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)這種方法,這裏拿到這裏講。
PendingIntent和Intent略有不一樣,它可以設置運行次數,主要用於遠程服務通訊、鬧鈴、通知、啓動器、短信中。在普通狀況下用的比較少。
Notification支持多種Intent來響應單擊事件、消除事件、處理緊急狀態的全屏事件等。
這裏就用到了setContentIntent(PendingIntent intent)來處理以上這麼多的事件。
屬性:
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:當用戶點擊全部清除button時。響應該清除事件的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.本身定義帶button通知欄(例如如下樣式)
正在進行的
「正在進行的」通知使用戶瞭解正在執行的後臺進程。
好比,音樂播放器可以顯示正在播放的音樂。也可以用來顯示需要長時間處理的操做,比例如如下載或編碼視頻。
「正在進行的」通知不能被手動刪除。
/** * 帶按鈕的通知欄 */ 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下面版本號沒實用。因此這邊做了系統版本號推斷。來顯示消失按鈕。
//先設定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)
僅僅在通知被展開時顯示
什麼時候展開:通知處在頂端,或者用戶經過收拾展開
收件箱風格的通知:
相比普通視圖。僅僅多出: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)設置相應的flags,讓用戶點擊既被消除:
notification.flags = FLAG_AUTO_CANCEL;
(2) 經過手動消除某項或則全部通知
mNotificationMgr.cancle(NOTIFICATION_ID);//消除相應ID的通知
mNotificationMgr.cancleAll();//消除建立的所有通知
(1)Notification.Builder(this).getNotification()
(2)mNotification.setLatestEventInfo(this, "title", "content", null);
這些方法都已經被啓用,儘管還有效果。可是不建議使用。
因此開發過程當中儘可能使用NotificationCompat.Builder(this)的構建方法去建立一個通知類。
(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直接操做!
解決方法:看其餘的應用,好像在低版本號都會隱藏掉那些button。就是爲了避免影響用戶體驗,因此應該就這麼解決,推斷版本號號在去決定是否現在button。
如右圖:
解決方式:
由於2.3及以前版本號,背景設是白色的那咱們定義字體顏色爲系統預設的顏色:
?android:attr/textColorPrimary
在資源的src/values文件夾中的style.xml文件裏設置它標題和內容的樣式爲:
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="NotificationContent"> <item name="android:textColor">?android:attr/textColorPrimary</item> </style> <style name="NotificationTitle"> <item name="android:textColor">?
android:attr/textColorPrimary</item> <item name="android:textStyle">bold</item> </style> </resources>
在2.3以後的版本號中(即API >=9的版本號中),在資源文件下的src/values-v9文件夾中的style.xml文件裏設置它標題和內容的樣式爲:
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="NotificationContent" parent="android:TextAppearance.StatusBar.EventContent" /> <style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" /> </resources>
最後賦給本身定義佈局中的相應標題和內容相應的style就能夠。
相應解決網址:
1.http://stackoverflow.com/questions/6250356/how-to-use-default-notification-style
2.http://stackoverflow.com/questions/4867338/custom-notification-layouts-and-text-colors/7320604#7320604
3.http://developer.android.com/guide/topics/ui/notifiers/notifications.html#CustomExpandedView (官方文檔)
http://developer.android.com/about/versions/android-2.2-highlights.html
解決方法:此方法在4.0及之後版本號才實用,假設爲早期版本號:需要本身定義通知佈局。當中包括ProgressBar視圖
2.3及2.3以前:
經過
Notification notify = mBuilder.build(); notify.contentView = view_custom; mNotificationManager.notify(notifyId, notify)方法賦予VIEW。
2.3以後:
經過Builder下面方法賦於本身定義佈局。
mBuilder.setContent(view_custom)
這裏就不貼DEMO中的代碼了,你們可以下個DEMO本身看,裏面也都有凝視的,可能有的地方會有錯誤,忘你們指出,以便及時改動,謝謝。
一個DEMO讓你更懂Notification