Android5.0通知變化淺析


目前在Android中通知的使用還是很常見的,為了做版本兼容,常用兼容包NotificationCompat.Builder和 Notification.Builder。

  • NotificationCompat.Builder位於v4擴展包內(version 4 Support Library)
  • Notification.Builder在Android 3.0 開始引入(API level 11).

最近在Android5.0設備上發現一個問題:通知圖標突然變成了白色的方塊而不是代碼中設置的icon。

問題原因

細讀開發者文檔其實也可以發現一些線索,雖然筆者是直接查的源碼發現的問題原因。http://developer.android.com/design/patterns/notifications.html 一文的Use distinct icons部分介紹了幾點關於通知的建議,其中的有兩點是建議開發者不要做的行為。

Don't
Place any additional alpha (dimming or fading) into your small icons and action icons; they can have anti-aliased edges, but because Android uses these icons as masks (that is, only the alpha channel is used), the image should generally be drawn at full opacity.

Don't
Use color to distinguish your app from others. Notification icons should only be a white-on-transparent background image.

簡單的說就是5.0后Android官方建議不要為通知的圖標添加任何額外的透明度,漸變色,不要企圖用顏色將通知圖標與其他應用,比如系統應用,應用的通知圖標只能是在透明的背景上有白色的圖案。
至於原因,文檔並沒有細說,只是提到5.0系統將會在底層處理圖標,想知怎么處理的可以參考Android SDK API level 21后的Notificaiton源碼,里面寫的較詳細。
Project Structure
Project Structure

結合文檔提供的圖片示例,應該可以理解。
如果不遵循建議那么有很大幾率是會出上文提到問題的,為什么不是別然出問題呢?
這還依賴於代碼編譯的版本,根據嘗試,目前api 21以后編譯會出問題,20及以前的版本編譯不會出問題。所以解決問題比較簡單粗暴的方案是用20及更早的版本編譯代碼。但是要測底解決問題,還是得遵循文檔指導,及從新設計通知的圖標以符合要求。

源碼分析

下面看一下到底21的Android源碼里面做了什么操作會導致通知的圖標統統變白色。
Notification.java

private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) {
	//...
	if (mLargeIcon != null) {
         contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
         processLargeLegacyIcon(mLargeIcon, contentView);
         contentView.setImageViewResource(R.id.right_icon, mSmallIcon);
         contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
         processSmallRightIcon(mSmallIcon, contentView);
     } else { // small icon at left
         contentView.setImageViewResource(R.id.icon, mSmallIcon);
         contentView.setViewVisibility(R.id.icon, View.VISIBLE);
         processSmallIconAsLarge(mSmallIcon, contentView);
    }
    //...
}

        /**
         * Recolor small icons when used in the R.id.right_icon slot.
         */
        private void processSmallRightIcon(int smallIconDrawableId,
                RemoteViews contentView) {
            if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, smallIconDrawableId)) {
                contentView.setDrawableParameters(R.id.right_icon, false, -1,
                        0xFFFFFFFF,
                        PorterDuff.Mode.SRC_ATOP, -1);

                contentView.setInt(R.id.right_icon,
                        "setBackgroundResource",
                        R.drawable.notification_icon_legacy_bg);

                contentView.setDrawableParameters(
                        R.id.right_icon,
                        true,
                        -1,
                        resolveColor(),
                        PorterDuff.Mode.SRC_ATOP,
                        -1);
            }
        }

這里我截取了兩段比較關鍵的代碼,在用NotificationCompat.Builder實例化我們的通知后,最終需要將各種圖標,參數配置,應用到通知視圖上面。可以看到如果我們只設置smallIcon而不設置largeIcon也是可以的,此時直接將small作為大圖標設置給左側的id為R.id.icon的ImageView。要注意的事一般情況下都不可以不設置smallIcon,否則通知無法正常顯示出來。
processSmallIconAsLarge方法里面負責將我們設置的smallIcon二次處理,也就是這里會改變我們最終看到的通知圖標,包括頂部狀態欄和下拉顯示的小圖標。

參考

  1. http://developer.android.com/design/patterns/notifications.html
  2. http://developer.android.com/guide/topics/ui/notifiers/notifications.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM