此文已由做者黎星受權網易雲社區發佈。html
歡迎訪問網易雲社區,瞭解更多網易技術產品運營經驗。android
因爲歷史緣由,Android在發佈之初對通知欄Notification的設計至關簡單,而現在面對各式各樣的通知欄玩法,谷歌也不得不對其進行更新迭代調整,增長新功能的同時,也在不斷地改變樣式,試圖迎合更多人的口味。本文總結了Android通知欄的版本迭代過程,在通知欄開發過程當中所遇到的各類各樣的坑,以及一些解決技巧,特別的,對於大衆期盼的Android 7.0的到來,通知欄又會發生怎樣的改變呢?接下來一一進行介紹。安全
Android通知欄發展歷史
首先來看一張各個Android版本通知欄消息的全家福。服務器
點擊查看大圖app
Android通知欄從最初的Android1.1系統一直到現在的7.X版本,發生了翻天覆地的變化。從圖中能夠看出,1.X-2.2版本的通知欄採用了白色背景和黑色字體;2.3-4.X版本,默認背景變成了黑色,而主標題採用白色字體,內容爲灰色字體。從Android5.0開始,又更改成白色背景和黑色字體。固然,這只是原生的Android系統通知欄默認顏色,許多廠商對每一個Android的版本都嘗試了各式各樣的修改,在此不一一介紹。ide
下面分別介紹每一個版本的更新和修改記錄。佈局
Android 1.X 修改記錄^1
Android 1.X版本也就是第一個Android誕生的版本。從Android1.1版本開始,提供基本的通知欄消息功能,包含小圖標、主標題、副標題和時間這四個元素。右上角有一個清除通知欄消息的按鈕。須要說明的是,Android從一開始就提供了清除通知欄消息的功能而且保留至今,而iOS到如今都沒有提供清除按鈕。學習
Android 2.X 修改記錄^2
Android 2.X版本的通知欄消息功能上並未發生變化,右上角的「clear notifications」縮減爲了「clear」。2.2版本之前沿用了1.5的通知欄樣式,從2.3版本開始從新設計,改爲了暗色背景。測試
Android 3.X 修改記錄^3
Android 3.X版本是專爲Pad而設計的系統。通知欄消息帶來了一些新的功能。字體
-
非永久的通知欄消息的右邊增長了「X」按鈕,點擊後該條通知能夠當即清除。
-
增長了RemoteControlClient,即遠程控制媒體應用的功能。
-
增長了LargeIcon,可使用大圖展現通知欄消息。
Android 4.1 修改記錄^4
Android 4.1版本的通知欄在3.X版本的基礎上進行了大量修改。增長了很多新功能。
-
增長了Style
-
增長了通知欄按鈕
-
支持通知欄展現的優先級配置
-
通知欄背景改成黑色透明
通知欄樣式
Android 4.1通知欄最大的變化就是增長了豐富多樣的Style樣式。經過設置樣式,能夠展現更大區域的通知消息,如展現大圖和多行文字,也能夠展現相似郵箱收發信的樣式,同時支持自定義按鈕並增長點擊事件。但須要注意的是,只有最頂部的那條通知欄消息能夠默認展現Style樣式,其餘消息默認是以普通樣式展現。Style能夠經過Notification.Builder.setStyle(Style)進行設置。具體支持的樣式有:
Notification.BigPictureStyle
大圖樣式,即除了普通的通知欄消息內容外,能夠在通知欄消息下方展現一張大圖,最大高度支持256dp。
Notification.BigTextStyle
多行文字樣式,能夠支持多行文字的展現。經測試,在不一樣手機上可以支持的行數不同,測試過的機子,最大支持12行。
Notification.InboxStyle
收件箱樣式。支持展現具備一串消息內容的會話樣式,適用於短信、郵件、IM等。
通知欄按鈕
通知欄消息無論是普通樣式仍是Style樣式,都支持兩個按鈕同時出如今一條通知欄消息的底部,經過這兩個按鈕,能夠自定義一系列動做,包括回覆信息和郵件,點贊等。經過Notification.Builder.addAction(Action)添加按鈕。
通知欄優先級
Android 4.1通知欄增長了優先級的配置,優先級高的消息能夠展現在最上方。谷歌設計優先級的初衷是根據不一樣的優先級來防止用戶成天被各類莫名其妙的通知欄消息騷擾,重要的通知則應該適當提升優先級,使得用戶能夠快速地看到並回應,不重要的通知則下降優先級,防止用戶被打擾。優先級一共有5個級別,分別是:
// 默認優先級 public static final int PRIORITY_DEFAULT = 0; // 低優先級 public static final int PRIORITY_LOW = -1; // 最低優先級 public static final int PRIORITY_MIN = -2; // 高優先級 public static final int PRIORITY_HIGH = 1; // 最高優先級 public static final int PRIORITY_MAX = 2;
Android 4.3 修改記錄^6
Android 4.3通知欄沒有發生大的變化。主要增長了兩個小功能。
-
增長了Notification AccessApi,容許可穿戴設備遠程控制通知欄消息。
-
增長了NotificationListenerService,容許接收到系統通知欄列表的變化
Android 5.X 修改記錄^7
Android 5.X系統相較於之前的版本,能夠說是一個真正能夠和iOS抗衡的系統。材料設計給Android系統注入了新的活力,相應的通知欄消息也相較於上一個版本進行了改版。所發生的變化有:
-
通知欄修改成白色背景,暗色字體,以適應材料設計風格。
-
系統會忽略全部non-alpha通道的圖標,包括按鈕圖標和主圖標。
-
能夠經過setColor()方法在圖標後設置一個背景色。
-
通知消息的聲音將經過STREAM_RING或者STREAM_NOTIFICATION控制,之前是經過STREAM_MUSIC控制。
-
鎖屏狀態下,能夠控制通知欄消息的隱私程度。
-
移除了RemoteControlClient,更改成NotificationCompat.MediaStyle實現。
-
增長了Heads-up通知,即經過狀態欄浮動窗口展現通知消息。
Android 6.X 修改記錄^8
-
移除了Notification.setLatestEventInfo()方法,經過持有Notification.Builder,而後使用build()方法能夠更新同一個通知欄實例。
-
容許用戶控制應用通知的優先級。
-
加入了免打擾模式(Do Not Disturb)。
-
增長了getActiveNotifications()方法獲取當前展現的通知消息。
Android 7.X 修改記錄
-
通知欄樣式全面改版,小圖標在左上角,大圖標在右邊,小圖標、App應用名、副標題、數量和時間在第一行,第二行是主標題,第三行是內容。
-
增長了Notification.DecoratedCustomViewStyle()和Notification.DecoratedMediaCustomViewStyle(),幫助更好的裝飾帶有RemoteViews的通知欄消息。
-
須要動態設置Builder.setShowWhen(true)纔會顯示時間。
-
支持Action的直接回復,經過RemoteInput實現,且回覆的消息內容支持當即添加到通知欄。
-
支持通知消息組,類似的消息在達到必定數量後會按照消息組來顯示。
-
增長了NotificationManager.areNotificationsEnabled告知應用是否開啓了通知權限。
Android通知欄踩坑與填坑指南
魅族5.X手機,大圖顯示問題
問題詳情
Flyme系統對原生Android源碼作了修改,採用BigPictureStyle方式顯示大圖通知欄的時候,消息與大圖重合了,以下圖。
解決方案
首先說一下爲何會有解決方案。展現大圖這個功能開發完成後,拿去給產品演示。碰巧產品的機型就是一魅族手機T_T,結果固然是不能接受的,而後又一個巧合的事情出現了,那就是產品的手機裏,京東App推了一條帶大圖的廣告,他們竟然可以解決這個問題!因而,我開始研究解決方案。
首先,經過BigPictureStyle來實現大圖功能確定是走不通的,由於事實就擺着行不通的嘛。京東的App確定是經過RemoteViews來實現的。因而,開始走彎路,嘗試經過RemoteViews來展現大圖。可是谷歌規定,自定義佈局展現的通知欄消息最大高度是64dp。那麼,京東的App是怎麼實現的?在嘗試了各類方法之後,最後又是經過投機取巧的方式解決了問題:
private void showBigPictureNotificationWithMZ(Context context) { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); Notification.Builder builder = new Notification.Builder(context); Notification notification = generateNotification(builder); notification.bigContentView = mRemoteViews; notificationManager.notify(notifyId, notification); }
須要先生成Notification的實例,而後手動給notification.bigContentView賦值,再notify,就能夠了
頂部狀態欄(StatusBar)小圖標顯示異常
問題詳情
當通知來的時候,若是不在通知欄瀏覽,會在頂部狀態欄出現一個向上翻滾動畫的通知消息,這條通知消息左邊是一個小圖標。部分系統這個小圖標顯示異常,是一個純灰色的正方形,以下圖。
解決方案
首先產生灰色圖標的緣由就是5.0系統引入了材料設計,谷歌強制使用帶有alpha通道的圖標,而且RGB的alpha值必須是0(實測不爲0也是能夠的,但系統會忽略全部RGB值)。所以,使用JPG的圖片是不行的,最好的代替方案就是一張背景透明的PNG圖片。
Android 7.X機型,通知欄小圖標顯示成灰色
問題詳情
這個問題跟第二個有點相似,在7.0系統及以上,有部分應用的小圖標是灰色的,大圖能夠正常顯示。碰巧的是,顯示異常的小圖標,顏色都是灰色的。
解決方案
與小圖標顯示異常解決方案相似,將小圖標替換爲透明背景的PNG圖片。
RemoteViews顯示異常
問題詳情
因爲系統提供的通知欄消息類型有時候不能知足要求,部分通知欄消息採用自定義RemoteViews來實現。採用RemoteViews,特別是手動生成Bitmap而後直接傳給一個自定義Layout,再經過setContentView方式設置通知欄消息時,會存在各類各樣的坑。
Android通知欄的背景色有幾種狀況,白色、暗色、暗色透明和黑色。若是生成的Bitmap帶背景色,這個背景色就很難選擇。若是選擇黑色背景,那麼在白色通知欄的機型上就很難看。所以不能徹底在各個系統上面完美展現出來。若是不帶背景色,那麼字體顏色也面臨一樣的困惑。試想,若是在白色的背景上顯示白色的文字,用戶看到白茫茫一片,是什麼感覺?
另外一方面,大部分廠商對原生的Android系統都會有各類各樣的改造,通知欄的樣式也不例外。若是按照原生的樣式來設計,那麼在大部分國內廠商的機子上顯示都和正常的普統統知欄消息不同。例如華爲6.0系統的機子,原生系統的時間線在右上角,華爲的在左邊,這樣會給用戶帶來錯覺。
解決方案
詳見RemoteViews適配一節。
大尺寸小圖標在部分機型上顯示不正確
問題詳情
這個問題主要在部分機型的4.X系統上碰見,小圖標大小沒有按照24dp裁剪,而是採用了桌面圖標同樣的大小96dp。具體適配不正常的機型有HTC Desire 820、Lenovo A320T。
解決方案
按照標準來,小圖標大小爲24dp,大圖標爲桌面icon圖標大小96dp。具體可參考這裏^14
部分機型不支持Style
具體機型見下圖以及後面統計的表格。順便提下,小米是其中之一,不知道他們爲何不支持額外的這些Style。
通知欄更新頻率
問題詳情
每一個應用基本都有自更新的邏輯,App開機的時候提示用戶升級,點擊升級按鈕後在Notification出現一個下載帶進度條的通知。應用通常是在開啓一個工做線程在後臺下載,而後在下載的過程當中經過回調更新通知欄中的進度條。咱們知道,下載進度的快慢是不可控的,若是每次下載中的回調都去更新通知欄,那麼可能幾百毫秒、幾十毫秒、甚至幾毫秒就更新一次通知欄,應用可能就會ANR,甚至崩潰。
解決方案
控制通知欄更新頻率,通常控制在0.5s或者1s就能夠了。在某一個更新時間間隔內下載的進度回調直接丟棄,須要注意的是下載完成的回調,須要實時回調通知欄消息顯示下載完成。
噁心的後臺通知和「守護」通知
問題詳情
這個坑我不肯多介紹,只說結果。但凡存在後臺通知或者「守護」通知的應用,在7.0系統之後都會原形畢露。尚未適配7.0的應用,可長點心兒吧~
解決方案
請棄坑。
小米推送SDK接入問題
問題詳情
爲了提高推送到達,考拉接入了小米推送的SDK。小米推送分爲通知欄消息和透傳消息,通知欄消息屬於系統級推送,在MIUI的機子上能夠在進程被殺死的狀況下也能收到應用推送。然而有個問題,小米認爲應用在前臺時,不會回調任何方法;小米認爲應用在後臺的時候,收到通知欄消息的同時,會回調onNotificationMessageArrived方法。這時候就要當心翼翼地處理這條消息了。由於若是你的應用先後臺判斷邏輯和小米的不同,那麼就有可能小米幫你發了一條通知欄消息,你本身又發了一遍,形成通知欄消息的重複發送(這個坑考拉踩過T_T)。另外一方面,在7.0系統的機子上,主標題和小圖標的顏色是能夠改變的,目前小米推送SDK沒有開放這個接口供調用方定製。
解決方案
目前只能解決第一個問題——先後臺判斷的問題。應用是否在後臺能夠根據如下代碼進行判斷。在Android 5.0以上,能夠經過ActivityManager.RunningAppProcessInfo判斷,Android 5.0及如下版本經過ActivityManager.RunningTaskInfo判斷。經測試,這個方案在Android 4.4以上結果是能夠徹底匹配的。
public static boolean isAppInBackgroundInternal(Context context) { ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { List<ActivityManager.RunningAppProcessInfo> runningProcesses = manager.getRunningAppProcesses(); if (!ListUtils.isEmpty(runningProcesses)) { for (ActivityManager.RunningAppProcessInfo runningProcess : runningProcesses) { if (runningProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { return false; } } } } else { List<ActivityManager.RunningTaskInfo> task = manager.getRunningTasks(1); if (!ListUtils.isEmpty(task)) { ComponentName info = task.get(0).topActivity; if (null != info) { return !isKaolaProcess(info.getPackageName()); } } } return true; }
Android通知欄適配
RemoteViews適配
因爲系統自帶的通知欄消息樣式不能徹底知足產品們腦洞大開的需求,有時候咱們須要自定義佈局樣式展現通知欄消息。Android系統能夠將自定義佈局經過setContent(7.X系統推薦使用setCustomContentView)設置到Notification.Builder中,來實現樣式的更變。setContent方法須要傳入一個RemoteViews對象,它是一個普通的數據類型,不是View,做用是供其餘進程展現視圖。RemoteViews只支持4種基本的佈局^9:
-
FrameLayout
-
LinearLayout
-
RelativeLayout
-
GridLayout
這些佈局下面只支持幾種視圖控件:
-
AnalogClock
-
Button
-
Chronometer
-
ImageButton
-
ImageView
-
ProgressBar
-
TextView
-
ViewFlipper
-
ListView
-
GridView
-
StackView
-
AdapterViewFlipper
只能經過上述組合生成一個RemoteViews。
自定義佈局與視圖
除了上面提到的佈局與控件,有沒有辦法自定義佈局與視圖呢?咱們知道,任何一個View,均可以生成一個Bitmap對象,支持的視圖控件裏有ImageView,能夠經過ImageView.setBitmapResource()將自定義視圖設置到一個ImageView中,而後再隨便放到一個佈局上,就能夠實現通知欄消息的任意佈局。理想是美好的,但現實是殘酷的。使用這種方式自定義的佈局,會存在與原生的通知欄消息樣式不一致的可能,包括小圖標/大圖標的大小,字體的大小與顏色,時間的顯示方式(不一樣版本的時間顯示位置和樣式都不同)。下面解決一個最關鍵,也最致命的問題——字體顏色。若是字體顏色和背景顏色同樣,那這條通知欄消息就無法看了,如RemoteViews顯示異常一節介紹的同樣。
解決字體顏色和背景顏色同樣的問題有三種解決方案,分別是:
-
背景色固定不透明,字體顏色與背景色造成反差。(360和京東的作法)
-
背景色透明,字體顏色採用系統原生的notification_style。
-
背景色透明,經過特殊方式拿到通知欄字體顏色和字體大小。
其中,第一種方案簡單,可以兼容全部廠商機型。例如京東固定背景色爲黑色,字體爲紅色。這種方式的惟一缺陷是樣式上不能與普統統知欄消息重合,在白色背景的通知欄上極爲顯眼。第二種方式,經過閱讀源碼可知,系統的通知欄標題和內容採用的顏色分別是@android:color/primary_text_dark和@android:color/secondary_text_dark,但踩過坑以後發現並不是全部的機型默認都是這兩個顏色,有可能獲取不到值。所以這種方案只能做爲參考,不能用於實際環境中。最後詳細介紹一下第三種方式。
免費領取驗證碼、內容安全、短信發送、直播點播體驗包及雲服務器等套餐
更多網易技術、產品、運營經驗分享請點擊。
相關文章:
【推薦】 探一探快應用的虛實
【推薦】 從整理看視覺設計(網易雲課堂個人學習中心-微專業視覺優化)