[轉]Android 通知Notification 詳解

weixin_34148340發表於2018-12-31

轉自
作者:登天路
轉載請說明出處:http://www.cnblogs.com/travellife/
GitPages:http://www.littlejie.com/

記錄其他較好的

郭霖---> Android通知欄微技巧,8.0系統中通知欄的適配

Android Notification 詳解

前幾天專案中有用到 Android 通知相關的內容,索性把 Android Notification 相關的知識都看了一遍,稍作梳理,在此做個總結,以備不時之需。

溫故而知新,可以為師矣~

下圖是我對 Notification 做的思維導圖,也是本文的主要邏輯。

[圖片上傳失敗...(image-97fe1c-1546067907378)]

本文主要講述 Notification 的基本操作部分,進階部分的內容還在學習ing~

Notification 概述

Notification,是一種具有全域性效果的通知,可以在系統的通知欄中顯示。當 APP 向系統發出通知時,它將先以圖示的形式顯示在通知欄中。使用者可以下拉通知欄檢視通知的詳細資訊。通知欄和抽屜式通知欄均是由系統控制,使用者可以隨時檢視。下面兩張圖均是來自 Google 官方文件。

[圖片上傳失敗...(image-ba3e3-1546067907378)]
圖 1 .通知欄中的通知

[圖片上傳失敗...(image-4752e1-1546067907378)]
圖 2 .抽屜式通知欄中的通知

通知的目的是告知使用者 App 事件。在平時的使用中,通知主要有以下幾個作用:

  1. 顯示接收到短訊息、及時訊息等資訊(如QQ、微信、新浪、簡訊)
  2. 顯示客戶端的推送訊息,如廣告、優惠、版本更新、推薦新聞等,常用的第三方 SDK 有: JPush個推信鴿網易雲信(偏重 IM )阿里雲推送
  3. 顯示正在進行的事物,例如:後臺執行的程式,如音樂播放進度、下載進度等

其中,前兩點可以歸結為與使用者互動,第三點是實時的任務提醒,但不可否認的是,第三點也會與使用者互動。

Notification 作為 Android 重要的使用者介面組成部分,它有自己的設計指南。在 Android 5.0(Api level 21) 中引入的 Material Design 尤為重要。關於 Notification 的設計指南請參考 Notification Pattern

Notification 的概述就這麼多,接下去就開始講 Notification 的基本使用,中間會穿插 Notification 的基本 UI 、各個版本的區別、常見的通知效果以及自己在學習過程中踩到的坑。

Notification 的基本操作

Notification 的基本操作主要有建立、更新、取消這三種。一個 Notification 的必要屬性有三項,如果不設定則在執行時會丟擲異常:

  1. 小圖示,通過 setSmallIcon() 方法設定
  2. 標題,通過 setContentTitle() 方法設定
  3. 內容,通過 setContentText() 方法設定

除了以上三項,其它均為可選項。雖然如此,但還是應該給 Notification 設定一個 Action ,這樣就可以直接跳轉到 App 的某個 Activity 、啟動一個 Service 或者傳送一個 Broadcast。否則,Notification 僅僅只能起到通知的效果,而不能與使用者互動。

當系統接收到通知時,可以通過震動、響鈴、呼吸燈等多種方式進行提醒。

建立 Notification

Notification 的建立主要涉及到 Notification.BuilderNotificationNotificationManager

  1. Notification.Builer : 使用建造者模式構建 Notification 物件。由於 Notification.Builder 僅支援 Android 4.1及之後的版本,為了解決相容性問題, Google 在 Android Support v4 中加入了 NotificationCompat.Builder 類。對於某些在 Android 4.1 之後才特性,即使 NotificationCompat.Builder 支援該方法,在之前的版本中也不能執行。點我 檢視更多關於 Notification 相容性問題處理。文中使用的都是 NotificationCompat。
  2. Notification : 通知對應類,儲存通知相關的資料。NotificationManager 向系統傳送通知時會用到。
  3. NotificationManager : NotificationManager 是通知管理類,它是一個系統服務。呼叫 NotificationManager 的 notify() 方法可以向系統傳送通知。

獲取 NotificationManager 物件:

NotificationManager mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

前面講到,Notification 有三個必要屬性。下面,我們就來建立一個簡單的 Notification 。主要有以下三步:

  1. 獲取 NotificationManager 例項
  2. 例項化 NotificationCompat.Builder 並設定相關屬性
  3. 通過 builder.build() 方法生成 Notification 物件,併傳送通知
private void sendNotification() {
   //獲取NotificationManager例項
   NotificationManager notifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
   //例項化NotificationCompat.Builde並設定相關屬性
   NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
           //設定小圖示
           .setSmallIcon(R.mipmap.icon_fab_repair)
           //設定通知標題
           .setContentTitle("最簡單的Notification")
           //設定通知內容
           .setContentText("只有小圖示、標題、內容")
           //設定通知時間,預設為系統發出通知的時間,通常不用設定
           //.setWhen(System.currentTimeMillis());
   //通過builder.build()方法生成Notification物件,併傳送通知,id=1
   notifyManager.notify(1, builder.build());
}

補充:

  • Android Support Library包的區別
Android Support v4:這個包是為了照顧1.6及更高版本而設計的,這個包是使用最廣泛的。

Android Support v7:這個包是為了考慮照顧2.1及以上版本而設計的,但不包含更低,故如果不考慮1.6,我們可以採用再加上這個包,另外注意,v7是要依賴v4這個包的,即,兩個得同時被包含。

Android Support v13:這個包的設計是為了android 3.2及更高版本的,一般我們都不常用,平板開發中能用到。
  • Notification 中的元素。在 Android N(24) 中, Google 對 Notification 的 UI 進行了修改。下圖是 Android M 和 Android N 的對比。

    [圖片上傳失敗...(image-cff3b3-1546067907378)]

  • 關於 setSmallIcon() 與 setLargeIcon()。在 NotificationCompat.Builder 中有設定通知的大小圖示的兩個方法。這兩個方法有什麼區別呢?當 setSmallIcon() 與 setLargeIcon() 同時存在時, smallIcon 顯示在通知的右下角, largeIcon 顯示在左側;當只設定 setSmallIcon() 時, smallIcon 顯示在左側。看下圖你就明白了。對於部分 ROM ,可能修改過原始碼,如 MIUI 上通知的大圖示和小圖示是沒有區別的。

[圖片上傳失敗...(image-156153-1546067907378)]

Google 官方是這麼解釋 setSmallIcon() 這個方法的:

Set the small icon resource, which will be used to represent the notification in the status bar. The platform template for the expanded view will draw this icon in the left, unless a large icon has also been specified, in which case the small icon will be moved to the right-hand side.

給 Notification 設定 Action

在前一章節 建立 Notification 中傳送的通知並不具備與使用者互動的能力,這是因為我們並沒有給 Notification 設定 Action 。在這一節,我們就來講講如何給 Notification 設定 Action 。這裡,我們來實現一個點選 Notification 跳轉到 MainActivity 的效果。程式碼如下:

/**
* 傳送一個點選跳轉到MainActivity的訊息
*/
private void sendSimplestNotificationWithAction() {
   //獲取PendingIntent
   Intent mainIntent = new Intent(this, MainActivity.class);
   PendingIntent mainPendingIntent = PendingIntent.getActivity(this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);
   //建立 Notification.Builder 物件
   NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
           .setSmallIcon(R.mipmap.ic_launcher)
           //點選通知後自動清除
           .setAutoCancel(true)
           .setContentTitle("我是帶Action的Notification")
           .setContentText("點我會開啟MainActivity")
           .setContentIntent(mainPendingIntent);
   //傳送通知
   mNotifyManager.notify(3, builder.build());
}

相比傳送最簡單的通知,傳送具有 Action 的通知多了建立 Intent 、 PendingIntent 和 setContentIntent() 這幾步。
不難看出, PendingIntent 才是重點,那麼, PendingIntent 是什麼呢?

PendingIntent

如果您瞭解 PendingIntent ,請直接跳過本節。

PendingIntent 是一種特殊的 Intent ,字面意思可以解釋為延遲的 Intent ,用於在某個事件結束後執行特定的 Action 。從上面帶 Action 的通知也能驗證這一點,當使用者點選通知時,才會執行。
PendingIntent 是 Android 系統管理並持有的用於描述和獲取原始資料的物件的標誌(引用)。也就是說,即便建立該PendingIntent物件的程式被殺死了,這個PendingItent物件在其他程式中還是可用的。
日常使用中的簡訊、鬧鐘等都用到了 PendingIntent。

PendingIntent 主要可以通過以下三種方式獲取:

//獲取一個用於啟動 Activity 的 PendingIntent 物件
public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags);

//獲取一個用於啟動 Service 的 PendingIntent 物件
public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags);

//獲取一個用於向 BroadcastReceiver 廣播的 PendingIntent 物件
public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)

PendingIntent 具有以下幾種 flag:

FLAG_CANCEL_CURRENT:如果當前系統中已經存在一個相同的 PendingIntent 物件,那麼就將先將已有的 PendingIntent 取消,然後重新生成一個 PendingIntent 物件。

FLAG_NO_CREATE:如果當前系統中不存在相同的 PendingIntent 物件,系統將不會建立該 PendingIntent 物件而是直接返回 null 。

FLAG_ONE_SHOT:該 PendingIntent 只作用一次。

FLAG_UPDATE_CURRENT:如果系統中已存在該 PendingIntent 物件,那麼系統將保留該 PendingIntent 物件,但是會使用新的 Intent 來更新之前 PendingIntent 中的 Intent 物件資料,例如更新 Intent 中的 Extras 。

更新 Notification

更新通知很簡單,只需要再次傳送相同 ID 的通知即可,如果之前的通知還未被取消,則會直接更新該通知相關的屬性;如果之前的通知已經被取消,則會重新建立一個新通知。

更新通知跟傳送通知使用相同的方式。詳見上節:建立 Notification

取消 Notification

取消通知有如下 5 種方式:

  1. 點選通知欄的清除按鈕,會清除所有可清除的通知
  2. 設定了 setAutoCancel() 或 FLAG_AUTO_CANCEL 的通知,點選該通知時會清除它
  3. 通過 NotificationManager 呼叫 cancel(int id) 方法清除指定 ID 的通知
  4. 通過 NotificationManager 呼叫 cancel(String tag, int id) 方法清除指定 TAG 和 ID 的通知
  5. 通過 NotificationManager 呼叫 cancelAll() 方法清除所有該應用之前傳送的通知

如果你是通過 NotificationManager.notify(String tag, int id, Notification notify) 方法建立的通知,那麼只能通過 NotificationManager.cancel(String tag, int id) 方法才能清除對應的通知,呼叫NotificationManager.cancel(int id) 無效。

關於 Notification 的基本操作程式碼如下,佈局檔案程式碼這就不貼了。我是 Demo 傳送門

/**
 * 為了方便,大部分通知都沒設定對應的Action,即PendingIntent
 * 除了sendFlagAutoCancelNotification()方法
 */
public class SimpleNotificationActivity extends Activity implements View.OnClickListener {

    //Notification.FLAG_FOREGROUND_SERVICE    //表示正在執行的服務
    public static final String NOTIFICATION_TAG = "littlejie";
    public static final int DEFAULT_NOTIFICATION_ID = 1;

    private NotificationManager mNotificationManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple_notification);

        findViewById(R.id.btn_remove_all_notification).setOnClickListener(this);
        findViewById(R.id.btn_send_notification).setOnClickListener(this);
        findViewById(R.id.btn_remove_notification).setOnClickListener(this);
        findViewById(R.id.btn_send_notification_with_tag).setOnClickListener(this);
        findViewById(R.id.btn_remove_notification_with_tag).setOnClickListener(this);
        findViewById(R.id.btn_send_ten_notification).setOnClickListener(this);
        findViewById(R.id.btn_send_flag_no_clear_notification).setOnClickListener(this);
        findViewById(R.id.btn_send_flag_ongoing_event_notification).setOnClickListener(this);
        findViewById(R.id.btn_send_flag_auto_cancecl_notification).setOnClickListener(this);

        mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_remove_all_notification:
                //移除當前 Context 下所有 Notification,包括 FLAG_NO_CLEAR 和 FLAG_ONGOING_EVENT
                mNotificationManager.cancelAll();
                break;
            case R.id.btn_send_notification:
                //傳送一個 Notification,此處 ID = 1
                sendNotification();
                break;
            case R.id.btn_remove_notification:
                //移除 ID = 1 的 Notification,注意:該方法只針對當前 Context。
                mNotificationManager.cancel(DEFAULT_NOTIFICATION_ID);
                break;
            case R.id.btn_send_notification_with_tag:
                //傳送一個 ID = 1 並且 TAG = littlejie 的 Notification
                //注意:此處傳送的通知與 sendNotification() 傳送的通知並不衝突
                //因為此處的 Notification 帶有 TAG
                sendNotificationWithTag();
                break;
            case R.id.btn_remove_notification_with_tag:
                //移除一個 ID = 1 並且 TAG = littlejie 的 Notification
                //注意:此處移除的通知與 NotificationManager.cancel(int id) 移除通知並不衝突
                //因為此處的 Notification 帶有 TAG
                mNotificationManager.cancel(NOTIFICATION_TAG, DEFAULT_NOTIFICATION_ID);
                break;
            case R.id.btn_send_ten_notification:
                //連續發十條 Notification
                sendTenNotifications();
                break;
            case R.id.btn_send_flag_no_clear_notification:
                //傳送 ID = 1, flag = FLAG_NO_CLEAR 的 Notification
                //下面兩個 Notification 的 ID 都為 1,會發現 ID 相等的 Notification 會被最新的替換掉
                sendFlagNoClearNotification();
                break;
            case R.id.btn_send_flag_auto_cancecl_notification:
                sendFlagOngoingEventNotification();
                break;
            case R.id.btn_send_flag_ongoing_event_notification:
                sendFlagAutoCancelNotification();
                break;
        }
    }

    /**
     * 傳送最簡單的通知,該通知的ID = 1
     */
    private void sendNotification() {
        //這裡使用 NotificationCompat 而不是 Notification ,因為 Notification 需要 API 16 才能使用
        //NotificationCompat 存在於 V4 Support Library
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Send Notification")
                .setContentText("Hi,My id is 1");
        mNotificationManager.notify(DEFAULT_NOTIFICATION_ID, builder.build());
    }

    /**
     * 使用notify(String tag, int id, Notification notification)方法傳送通知
     * 移除對應通知需使用 cancel(String tag, int id)
     */
    private void sendNotificationWithTag() {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Send Notification With Tag")
                .setContentText("Hi,My id is 1,tag is " + NOTIFICATION_TAG);
        mNotificationManager.notify(NOTIFICATION_TAG, DEFAULT_NOTIFICATION_ID, builder.build());
    }

    /**
     * 迴圈傳送十個通知
     */
    private void sendTenNotifications() {
        for (int i = 0; i < 10; i++) {
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentTitle("Send Notification Batch")
                    .setContentText("Hi,My id is " + i);
            mNotificationManager.notify(i, builder.build());
        }
    }

    /**
     * 設定FLAG_NO_CLEAR
     * 該 flag 表示該通知不能被狀態列的清除按鈕給清除掉,也不能被手動清除,但能通過 cancel() 方法清除
     * Notification.flags屬性可以通過 |= 運算疊加效果
     */
    private void sendFlagNoClearNotification() {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Send Notification Use FLAG_NO_CLEAR")
                .setContentText("Hi,My id is 1,i can't be clear.");
        Notification notification = builder.build();
        //設定 Notification 的 flags = FLAG_NO_CLEAR
        //FLAG_NO_CLEAR 表示該通知不能被狀態列的清除按鈕給清除掉,也不能被手動清除,但能通過 cancel() 方法清除
        //flags 可以通過 |= 運算疊加效果
        notification.flags |= Notification.FLAG_NO_CLEAR;
        mNotificationManager.notify(DEFAULT_NOTIFICATION_ID, notification);
    }

    /**
     * 設定FLAG_AUTO_CANCEL
     * 該 flag 表示使用者單擊通知後自動消失
     */
    private void sendFlagAutoCancelNotification() {
        //設定一個Intent,不然點選通知不會自動消失
        Intent resultIntent = new Intent(this, MainActivity.class);
        PendingIntent resultPendingIntent = PendingIntent.getActivity(
                this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Send Notification Use FLAG_AUTO_CLEAR")
                .setContentText("Hi,My id is 1,i can be clear.")
                .setContentIntent(resultPendingIntent);
        Notification notification = builder.build();
        //設定 Notification 的 flags = FLAG_NO_CLEAR
        //FLAG_AUTO_CANCEL 表示該通知能被狀態列的清除按鈕給清除掉
        //等價於 builder.setAutoCancel(true);
        notification.flags |= Notification.FLAG_AUTO_CANCEL;
        mNotificationManager.notify(DEFAULT_NOTIFICATION_ID, notification);
    }

    /**
     * 設定FLAG_ONGOING_EVENT
     * 該 flag 表示發起正在執行事件(活動中)
     */
    private void sendFlagOngoingEventNotification() {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Send Notification Use FLAG_ONGOING_EVENT")
                .setContentText("Hi,My id is 1,i can't be clear.");
        Notification notification = builder.build();
        //設定 Notification 的 flags = FLAG_NO_CLEAR
        //FLAG_ONGOING_EVENT 表示該通知通知放置在正在執行,不能被手動清除,但能通過 cancel() 方法清除
        //等價於 builder.setOngoing(true);
        notification.flags |= Notification.FLAG_ONGOING_EVENT;
        mNotificationManager.notify(DEFAULT_NOTIFICATION_ID, notification);
    }    
}

設定 Notification 的通知效果

前面講了 Notification 的建立、更新和取消,以及給 Notification 設定 Action 等基本操作。那麼,我怎麼給 Notification 設定諸如震動、鈴聲、呼吸燈等效果呢?別急,接下來馬上就會告訴你怎麼給 Notification 新增效果。

Notification 有震動、響鈴、呼吸燈三種響鈴效果,可以通過 setDefaults(int defualts) 方法來設定。 Default 屬性有以下四種,一旦設定了 Default 效果,自定義的效果就會失效。樓主在這裡踩了坑,愣是調了半天沒找到為什麼自定義效果會消失,忘大家慎之。

//設定系統預設提醒效果,一旦設定預設提醒效果,則自定義的提醒效果會全部失效。具體可看原始碼
//新增預設震動效果,需要申請震動許可權
//<uses-permission android:name="android.permission.VIBRATE" />
Notification.DEFAULT_VIBRATE

//新增系統預設聲音效果,設定此值後,呼叫setSound()設定自定義聲音無效
Notification.DEFAULT_SOUND

//新增預設呼吸燈效果,使用時須與 Notification.FLAG_SHOW_LIGHTS 結合使用,否則無效
Notification.DEFAULT_LIGHTS

//新增上述三種預設提醒效果
Notification.DEFAULT_ALL

除了以上幾種設定 Notification 預設通知效果,還可以通過以下幾種 FLAG 設定通知效果。

//提醒效果常用 Flag
//三色燈提醒,在使用三色燈提醒時候必須加該標誌符
Notification.FLAG_SHOW_LIGHTS

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

//讓聲音、振動無限迴圈,直到使用者響應 (取消或者開啟)
Notification.FLAG_INSISTENT

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

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

//只有呼叫NotificationManager.cancel()時才會清除
Notification.FLAG_NO_CLEAR

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

Notification 通知效果的設定方式及注意事項全部在程式碼中,核心程式碼如下:

/**
* 最普通的通知效果
*/
private void showNotifyOnlyText() {
   NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
           .setSmallIcon(R.mipmap.ic_launcher)
           .setLargeIcon(mLargeIcon)
           .setContentTitle("我是隻有文字效果的通知")
           .setContentText("我沒有鈴聲、震動、呼吸燈,但我就是一個通知");
   mManager.notify(1, builder.build());
}

/**
* 展示有自定義鈴聲效果的通知
* 補充:使用系統自帶的鈴聲效果:Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
*/
private void showNotifyWithRing() {
   NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
           .setSmallIcon(R.mipmap.ic_launcher)
           .setContentTitle("我是伴有鈴聲效果的通知")
           .setContentText("美妙麼?安靜聽~")
           //呼叫系統預設響鈴,設定此屬性後setSound()會無效
           //.setDefaults(Notification.DEFAULT_SOUND)
           //呼叫系統多媒體褲內的鈴聲
           //.setSound(Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2"));
           //呼叫自己提供的鈴聲,位於 /res/values/raw 目錄下
           .setSound(Uri.parse("android.resource://com.littlejie.notification/" + R.raw.sound));
   //另一種設定鈴聲的方法
   //Notification notify = builder.build();
   //呼叫系統預設鈴聲
   //notify.defaults = Notification.DEFAULT_SOUND;
   //呼叫自己提供的鈴聲
   //notify.sound = Uri.parse("android.resource://com.littlejie.notification/"+R.raw.sound);
   //呼叫系統自帶的鈴聲
   //notify.sound = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2");
   //mManager.notify(2,notify);
   mManager.notify(2, builder.build());
}

/**
* 展示有震動效果的通知,需要在AndroidManifest.xml中申請震動許可權
* <uses-permission android:name="android.permission.VIBRATE" />
* 補充:測試震動的時候,手機的模式一定要調成鈴聲+震動模式,否則你是感受不到震動的
*/
private void showNotifyWithVibrate() {
   //震動也有兩種設定方法,與設定鈴聲一樣,在此不再贅述
   long[] vibrate = new long[]{0, 500, 1000, 1500};
   NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
           .setSmallIcon(R.mipmap.ic_launcher)
           .setContentTitle("我是伴有震動效果的通知")
           .setContentText("顫抖吧,凡人~")
           //使用系統預設的震動引數,會與自定義的衝突
           //.setDefaults(Notification.DEFAULT_VIBRATE)
           //自定義震動效果
           .setVibrate(vibrate);
   //另一種設定震動的方法
   //Notification notify = builder.build();
   //呼叫系統預設震動
   //notify.defaults = Notification.DEFAULT_VIBRATE;
   //呼叫自己設定的震動
   //notify.vibrate = vibrate;
   //mManager.notify(3,notify);
   mManager.notify(3, builder.build());
}

/**
* 顯示帶有呼吸燈效果的通知,但是不知道為什麼,自己這裡測試沒成功
*/
private void showNotifyWithLights() {
   final NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
           .setSmallIcon(R.mipmap.ic_launcher)
           .setContentTitle("我是帶有呼吸燈效果的通知")
           .setContentText("一閃一閃亮晶晶~")
           //ledARGB 表示燈光顏色、 ledOnMS 亮持續時間、ledOffMS 暗的時間
           .setLights(0xFF0000, 3000, 3000);
   Notification notify = builder.build();
   //只有在設定了標誌符Flags為Notification.FLAG_SHOW_LIGHTS的時候,才支援呼吸燈提醒。
   notify.flags = Notification.FLAG_SHOW_LIGHTS;
   //設定lights引數的另一種方式
   //notify.ledARGB = 0xFF0000;
   //notify.ledOnMS = 500;
   //notify.ledOffMS = 5000;
   //使用handler延遲傳送通知,因為連線usb時,呼吸燈一直會亮著
   Handler handler = new Handler();
   handler.postDelayed(new Runnable() {
       @Override
       public void run() {
           mManager.notify(4, builder.build());
       }
   }, 10000);
}

/**
* 顯示帶有預設鈴聲、震動、呼吸燈效果的通知
* 如需實現自定義效果,請參考前面三個例子
*/
private void showNotifyWithMixed() {
   NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
           .setSmallIcon(R.mipmap.ic_launcher)
           .setContentTitle("我是有鈴聲+震動+呼吸燈效果的通知")
           .setContentText("我是最棒的~")
           //等價於setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE);
           .setDefaults(Notification.DEFAULT_ALL);
   mManager.notify(5, builder.build());
}

/**
* 通知無限迴圈,直到使用者取消或者開啟通知欄(其實觸控就可以了),效果與FLAG_ONLY_ALERT_ONCE相反
* 注:這裡沒有給Notification設定PendingIntent,也就是說該通知無法響應,所以只能手動取消
*/
private void showInsistentNotify() {
   NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
           .setSmallIcon(R.mipmap.ic_launcher)
           .setContentTitle("我是一個死迴圈,除非你取消或者響應")
           .setContentText("啦啦啦~")
           .setDefaults(Notification.DEFAULT_ALL);
   Notification notify = builder.build();
   notify.flags |= Notification.FLAG_INSISTENT;
   mManager.notify(6, notify);
}

/**
* 通知只執行一次,與預設的效果一樣
*/
private void showAlertOnceNotify() {
   NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
           .setSmallIcon(R.mipmap.ic_launcher)
           .setContentTitle("仔細看,我就執行一遍")
           .setContentText("好了,已經一遍了~")
           .setDefaults(Notification.DEFAULT_ALL);
   Notification notify = builder.build();
   notify.flags |= Notification.FLAG_ONLY_ALERT_ONCE;
   mManager.notify(7, notify);
}

/**
* 清除所有通知
*/
private void clearNotify() {
   mManager.cancelAll();
}

至此, Notification 的基本操作都已經講完了,傳送一個帶有自定義效果的簡單通知已經不在話下。接下去,我們會講 Notification 的一些高階操作。快上車,沒時間解釋了~

補充:當使用者點選通知欄的時候,正在進行的通知,比如 Notification 的 flags = Notification.FLAG_INSISTENT ,那麼相當於使用者響應了該通知,後面的 Demo 中會給出具體的程式碼

文中如有紕漏,歡迎大家留言指出。
微博:厲聖傑
原始碼:AndroidDemo/Notification

參考

  1. Android Patterns——Notification
  2. Android User Interface——Notification
  3. 全面瞭解Android Notification

相關文章