Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android Notification分析——你可能遇到的各種問題

android Notification分析——你可能遇到的各種問題

編輯:關於Android編程

通知的使用網上有各種總結,csdn上也有很多總結非常到位,在此就不做重復的總結了,需要的同學可以自行搜索或者參考下面給出的鏈接。開始學習的時候認真的讀了一些,現在功能開發完畢,把自己最近遇到的一些問題和心得分享給大家。


一、很難逃避de兼容問題


1、直接new Notification()這種方式已經過時,因此自己也沒有去細究這種方式,直接使用的是new NotificationCompat.Builder(context).build()(這個在support v4包中,下面的內容全是以這種方式來實現的)

2、自定義布局的兼容

使用NotificationCampat來做自定義布局我們可以這樣做:

RemoteViews rvMain = new RemoteViews(context.getPackageName(), R.layout.notification_layout);
//TODO rvMain...
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
				.setContent(rvMain);
// TOOD ...
在4.0以上,這樣是沒問題,但是在2.3的時候,你會發現這樣根本無效,因此我們需要換一種方式:

RemoteViews rvMain = new RemoteViews(context.getPackageName(), R.layout.notification_layout);
//TODO rmMain...
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
				.setContent(rvMain);
// TOOD ...
Notification notification = builder.build();
if(Build.VERSION.SDK_INT <= 10){
	notification.contentView = rvMain;
}

3、通知欄上的操作事件

先說說我們可以處理的通知事件:

setContentIntent():用戶點擊通知時觸發

setFullScreenIntent()://TODO 這個在通知顯示的時候會被調用

setDeleteIntent():用戶清除通知時觸發,可以是點擊清除按鈕,也可以是左右滑動刪除(當然了,前提是高版本)

2.3及以下是無法處理自定義布局中的操作事件的,這樣我們就不要去考慮增加自定義按鈕了。


二、可能會遇到的問題


1、Ticker圖標顯示只有中間一部分

\

<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHByZSBjbGFzcz0="brush:java;">new NotificationCompat.Builder(context).setSmallIcon(R.drawable.ic_notice_small, 0)

我們可以通過這樣的方式來設置Ticker時顯示的圖標。在我們測試的時候小米和sony的機器上出現過,解決辦法是把之前的大圖標(我們最初是72×72)替換成現在的32×32的小圖標,並把它從之前的xxhdpi移到hdpi文件夾中。

2、Ticker不顯示:直接顯示通知的圖標,中間的Ticker過程沒有顯示

這個沒有找到是什麼原因,直接把setFullScreenIntent(mPIFullScreen, false)這行注銷即可

3、點擊通知,通知列表不消失

這個只在華為的一個機器上遇到過,解決辦法是在點擊事件之後發一個關閉的廣播:

sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
參考:http://stackoverflow.com/questions/18261969/clicking-android-notification-actions-does-not-close-notification-drawer

4、出現各種亂

這裡說的混亂是指通知沒有顯示出來、多條通知點擊觸發的事件相同、多條通知的Intent相同等等。這個時候你可能需要去檢查通知的ID和PendingIntent的requestCode。

5、各種機型的適配

這個是相當混亂的,比如大多數是黑底白字,但是部分華為機型是灰底黑字;有些不支持設置自定義布局中的字體顏色;有些會屏蔽自定義布局的背景顏色和透明度,有些甚至你只能自定義通知欄的部分布局(左面的圖標是改不了的):

\

曾經為了追求自定義布局的左側圖標和默認通知的左側圖標寬度相同,大小相仿,做了很多適配,比如各種dimens,但是僅僅是適配,還是不能支持所有機型,遂放棄了。到目前為止沒找到一個完美的解決方案,市面上很多優秀的應用做的也不是非常好,對比下左側圖標寬度你就知道。最近在墨跡天氣中發現這個功能:

\

這算不算對混亂的一種妥協呢?


三、自定義的一些擴展


從開始處理通知中的操作事件,到實現一個比現有通知更高的通知,我們的欲望在不斷的增加。雖然美好的東西總是來得晚一些,但是目前來看,這些想法我們都可以實現了。
4.1中默認的三種big style可以滿足我們很多時候的需求,比如:

\

從左到右依次應該為BigTextStyle、BigPictureStyle、InboxStyle,這個就不多說了,照著demo就能弄出來,值得注意的是,默認展開BigStyle是用兩手指頭平行下滑,折疊是上滑。下面是百度音樂播放器的通知效果,在此簡單實現下,效果如圖:

\ 知道怎麼做了,其實是很容易實現的,但關鍵的是不知道怎麼做。首先看到這個效果,自己去嘗試了各種方法,比如指定視圖的高度,在不同的機器(主要是高版本的)機器上運行,發現都不行,google一下,沒有結果。怎麼辦?反編譯吧,在資源文件中發現了layout-v16文件夾下有個布局,這個布局就是我們上圖的布局,在一大堆java文件中找到這樣一行代碼:

notification.bigContentView = *****;
怎麼樣?明白了吧~~就是關鍵句,查看api,這個屬性需要16及以上才支持,因此我們在實現的時候可以這樣寫:

if(Build.VERSION.SDK_INT >= 16){
	notification.bigContentView = rvMain;
}
將我們自己的RemoteView付給bigContentView。真正實現的時候你可能會發現,這個高度不是我們任意指定的,是的,卻是如此,他的高度是100dp。這樣我們就可以通過自定義RemoteView來實現各種絢麗的通知了。


四、通知NotificationManager的源碼

本想在分析下NotificationManager,但是發現他的代碼很少,只要完成自己的Notification然後調用它的方法就可以。具體的實現就是底層的事情了,又到軟肋的哭

不過簡單浏覽還是發現了一點點——和Toast的關聯,他們都使用了INotificationManager:

    static private INotificationManager getService() {
        if (sService != null) {
            return sService;
        }
        sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));
        return sService;
    }

Toast的show():

    /**
     * Show the view for the specified duration.
     */
    public void show() {
        if (mNextView == null) {
            throw new RuntimeException("setView must have been called");
        }

        INotificationManager service = getService();
        String pkg = mContext.getPackageName();
        TN tn = mTN;
        tn.mNextView = mNextView;

        try {
            service.enqueueToast(pkg, tn, mDuration);
        } catch (RemoteException e) {
            // Empty
        }
    }
NotificatioManager的notify():

    /**
     * Post a notification to be shown in the status bar. If a notification with
     * the same tag and id has already been posted by your application and has not yet been
     * canceled, it will be replaced by the updated information.
     *
     * @param tag A string identifier for this notification.  May be {@code null}.
     * @param id An identifier for this notification.  The pair (tag, id) must be unique
     *        within your application.
     * @param notification A {@link Notification} object describing what to
     *        show the user. Must not be null.
     */
    public void notify(String tag, int id, Notification notification)
    {
        int[] idOut = new int[1];
        INotificationManager service = getService();
        String pkg = mContext.getPackageName();
        if (notification.sound != null) {
            notification.sound = notification.sound.getCanonicalUri();
            if (StrictMode.vmFileUriExposureEnabled()) {
                notification.sound.checkFileUriExposed("Notification.sound");
            }
        }
        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
        try {
            service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
                    notification, idOut, UserHandle.myUserId());
            if (id != idOut[0]) {
                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
            }
        } catch (RemoteException e) {
        }
    }


參考(引用):

http://blog.csdn.net/vipzjyno1/article/details/25248021

http://blog.csdn.net/feng88724/article/details/6259071


demo:下載

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved