Android通知Notification全面剖析

jamesehng發表於2016-12-02

通知

通知是您可以在應用的常規 UI 外部向使用者顯示的訊息。當您告知系統發出通知時,它將先以圖示的形式顯示在通知區域中。使用者可以開啟抽屜式通知欄檢視通知的詳細資訊。 通知區域和抽屜式通知欄均是由系統控制的區域,使用者可以隨時檢視。

這裡寫圖片描述

圖 1. 通知區域中的通知。

這裡寫圖片描述
圖 2. 抽屜式通知欄中的通知。

注:除非特別註明,否則本指南均引用版本 4 支援庫中的 NotificationCompat.Builder 類。Android 3.0(API 級別 11)中已新增類 Notification.Builder。

設計注意事項

作為 Android 使用者介面的一個重要組成部分,通知具有自己的設計指導方針。Android 5.0(API 級別 21)中引入的 Material Design 變更尤為重要。

建立通知

您可以在 NotificationCompat.Builder 物件中為通知指定 UI 資訊和操作。要建立通知,請呼叫 NotificationCompat.Builder.build(),它將返回包含您的具體規範的 Notification 物件。要發出通知,請通過呼叫 NotificationManager.notify() 將 Notification 物件傳遞給系統。

必需的通知內容

Notification 物件必須包含以下內容:

小圖示,由 setSmallIcon() 設定 標題,由 setContentTitle() 設定 詳細文字,由 setContentText() 設定

可選通知內容和設定

所有其他通知設定和內容都是可選的。如需瞭解有關它們的更多詳情,請參閱 NotificationCompat.Builder 參考文件。

通知操作

儘管通知操作都是可選的,但是您至少應向通知新增一個操作。 操作允許使用者直接從通知轉到應用中的 Activity,他們可在其中檢視一個或多個事件或執行進一步的操作。

一個通知可以提供多個操作。您應該始終定義一個當使用者點選通知時會觸發的操作;通常,此操作會在應用中開啟 Activity。 您也可以向通知新增按鈕來執行其他操作,例如,暫停鬧鈴或立即答覆簡訊;此功能自 Android 4.1 起可用。如果使用其他操作按鈕,則您還必須使這些按鈕的功能在應用的 Activity 中可用

在 Notification 內部,操作本身由 PendingIntent 定義,後者包含在應用中啟動 Activity 的 Intent。要將 PendingIntent 與手勢相關聯,請呼叫 NotificationCompat.Builder 的適當方法。例如,如果您要在使用者點選抽屜式通知欄中的通知文字時啟動 Activity,則可通過呼叫 setContentIntent() 來新增 PendingIntent。

在使用者點選通知時啟動 Activity 是最常見的操作場景。此外,您還可以在使用者清除通知時啟動 Activity。在 Android 4.1 及更高版本中,您可以通過操作按鈕啟動 Activity。

通知優先順序

您可以根據需要設定通知的優先順序。優先順序充當一個提示,提醒裝置 UI 應該如何顯示通知。 要設定通知的優先順序,請呼叫 NotificationCompat.Builder.setPriority() 並傳入一個 NotificationCompat 優先順序常量。有五個優先順序別,範圍從 PRIORITY_MIN (-2) 到 PRIORITY_MAX (2);如果未設定,則優先順序預設為 PRIORITY_DEFAULT (0)。

有關設定適當優先順序別的資訊,請參閱通知設計指南中的“正確設定和管理通知優先順序”。

建立簡單通知

以下程式碼段說明了一個指定某項 Activity 在使用者點選通知時開啟的簡單通知。 請注意,該程式碼將建立 TaskStackBuilder 物件並使用它來為操作建立 PendingIntent。啟動 Activity 時保留導航部分對此模式做了更詳盡的闡述:

NotificationCompat.Builder mBuilder =
        new NotificationCompat.Builder(this)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, ResultActivity.class);

// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
        stackBuilder.getPendingIntent(
            0,
            PendingIntent.FLAG_UPDATE_CURRENT
        );
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(mId, mBuilder.build());
複製程式碼

就這麼簡單。您的使用者現已收到通知。

將擴充套件布局應用於通知

要使通知出現在展開檢視中,請先建立一個帶有所需普通檢視選項的 NotificationCompat.Builder 物件。接下來,呼叫以擴充套件布局物件作為其引數的 Builder.setStyle()。

請記住,擴充套件通知在 Android 4.1 之前的平臺上不可用。要了解如何處理針對 Android 4.1 及更早版本平臺的通知,請閱讀處理相容性部分。

例如,以下程式碼段演示瞭如何更改在前面的程式碼段中建立的通知,以便使用擴充套件布局:

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
    .setSmallIcon(R.drawable.notification_icon)
    .setContentTitle("Event tracker")
    .setContentText("Events received")
NotificationCompat.InboxStyle inboxStyle =
        new NotificationCompat.InboxStyle();
String[] events = new String[6];
// Sets a title for the Inbox in expanded layout
inboxStyle.setBigContentTitle("Event tracker details:");
...
// Moves events into the expanded layout
for (int i=0; i < events.length; i++) {

    inboxStyle.addLine(events[i]);
}
// Moves the expanded layout object into the notification object.
mBuilder.setStyle(inBoxStyle);
...
// Issue the notification here.
複製程式碼

處理相容性

並非所有通知功能都可用於某特定版本,即便用於設定這些功能的方法位於支援庫類 NotificationCompat.Builder 中也是如此。 例如,依賴於擴充套件通知的操作按鈕僅會顯示在 Android 4.1 及更高版本的系統中,這是因為擴充套件通知本身僅在 Android 4.1 及更高版本的系統中可用。

為了確保最佳相容性,請使用 NotificationCompat 及其子類(特別是 NotificationCompat.Builder)建立通知。此外,在實現通知時,請遵循以下流程:

為所有使用者提供通知的全部功能,無論他們使用何種版本的 Android 系統。 為此,請驗證是否可從應用的 Activity 中獲得所有功能。要執行此操作,您可能需要新增新的 Activity。 例如,若要使用 addAction() 提供停止和啟動媒體播放的控制元件,請先在應用的 Activity 中實現此控制元件。 確保所有使用者均可通過點選通知啟動 Activity 來獲得該Activity中的功能。 為此,請為 Activity 建立 PendingIntent。呼叫 setContentIntent() 以將 PendingIntent 新增到通知。 現在,將要使用的擴充套件通知功能新增到通知。請記住,您新增的任何功能還必須在使用者點選通知時啟動的 Activity 中可用。

管理通知

當您需要為同一型別的事件多次發出同一通知時,應避免建立全新的通知, 而是應考慮通過更改之前通知的某些值和/或為其新增某些值來更新通知。

例如,Gmail 通過增加未讀訊息計數並將每封電子郵件的摘要新增到通知,通知使用者收到了新的電子郵件。 這稱為“堆疊”通知;通知設計指南對此進行了更詳盡的描述。

注:此 Gmail 功能需要“收件箱”擴充套件布局,該佈局是自 Android 4.1 版本起可用的擴充套件通知功能的一部分。

下文介紹如何更新和刪除通知。

更新通知

要將通知設定為能夠更新,請通過呼叫 NotificationManager.notify() 發出帶有通知 ID 的通知。 要在發出之後更新此通知,請更新或建立 NotificationCompat.Builder 物件,從該物件構建 Notification 物件,併發出與之前所用 ID 相同的 Notification。如果之前的通知仍然可見,則系統會根據 Notification 物件的內容更新該通知。相反,如果之前的通知已被清除,系統則會建立一個新通知。

以下程式碼段演示了經過更新以反映所發生事件數量的通知。 它將通知堆疊並顯示摘要:

mNotificationManager =
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Sets an ID for the notification, so it can be updated
int notifyID = 1;
mNotifyBuilder = new NotificationCompat.Builder(this)
    .setContentTitle("New Message")
    .setContentText("You've received new messages.")
    .setSmallIcon(R.drawable.ic_notify_status)
numMessages = 0;
// Start of a loop that processes data and then notifies the user
...
    mNotifyBuilder.setContentText(currentText)
        .setNumber(++numMessages);
    // Because the ID remains unchanged, the existing notification is
    // updated.
    mNotificationManager.notify(
            notifyID,
            mNotifyBuilder.build());
...
複製程式碼

刪除通知

除非發生以下情況之一,否則通知仍然可見:

使用者單獨或通過使用“全部清除”清除了該通知(如果通知可以清除)。 使用者點選通知,且您在建立通知時呼叫了 setAutoCancel()。 您針對特定的通知 ID 呼叫了 cancel()。此方法還會刪除當前通知。 您呼叫了 cancelAll() 方法,該方法將刪除之前發出的所有通知。 啟動 Activity 時保留導航 從通知中啟動 Activity 時,您必須保留使用者的預期導航體驗。 點選“返回”應該使使用者將應用的正常工作流回退到主螢幕,而點選“最新動態”則應將 Activity 顯示為單獨的任務。 要保留導航體驗,您應該在全新任務中啟動 Activity。如何設定 PendingIntent 以獲得全新任務取決於正在啟動的 Activity 的性質。一般有兩種情況:

常規 Activity

您要啟動的 Activity 是應用的正常工作流的一部分。在這種情況下,請設定 PendingIntent 以啟動全新任務併為 PendingIntent提供返回棧,這將重現應用的正常“返回”行為。 Gmail 應用中的通知演示了這一點。點選一封電子郵件訊息的通知時,您將看到訊息具體內容。 觸控返回將使您從 Gmail 回退到主螢幕,就好像您是從主螢幕(而不是通知)進入 Gmail 一樣。

無論您觸控通知時處於哪個應用,都會發生這種情況。 例如,如果您在 Gmail 中撰寫訊息時點選了一封電子郵件的通知,則會立即轉到該電子郵件。 觸控“返回”會依次轉到收件箱和主螢幕,而不是轉到您在撰寫的郵件。

特殊 Activity

僅當從通知中啟動時,使用者才會看到此 Activity。 從某種意義上說,Activity 是通過提供很難顯示在通知本身中的資訊來擴充套件通知。對於這種情況,請將 PendingIntent 設定為在全新任務中啟動。但是,由於啟動的 Activity 不是應用 Activity 流程的一部分,因此無需建立返回棧。點選“返回”仍會將使用者帶到主螢幕。 設定常規 Activity PendingIntent 要設定可啟動直接進入 Activity 的 PendingIntent,請執行以下步驟:

在清單檔案中定義應用的 Activity 層次結構。 新增對 Android 4.0.3 及更低版本的支援。為此,請通過新增 meta-data 元素作為 activity的子項來指定正在啟動的 Activity 的父項。

對於此元素,請設定 android:name="android.support.PARENT_ACTIVITY"。 設定 android:value="<parent_activity_name>",其中,<parent_activity_name> 是父 <activity> 元素的 android:name 值。請參閱下面的 XML 示例。
複製程式碼

同樣新增對 Android 4.1 及更高版本的支援。為此,請將 android:parentActivityName 屬性新增到正在啟動的 Activity 的 activity 元素中。 最終的 XML 應如下所示:

<activity
    android:name=".MainActivity"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<activity
    android:name=".ResultActivity"
    android:parentActivityName=".MainActivity">
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value=".MainActivity"/>
</activity>
複製程式碼

根據可啟動 Activity 的 Intent 建立返回棧:

建立 Intent 以啟動 Activity。

通過呼叫 TaskStackBuilder.create() 建立堆疊生成器。 通過呼叫 addParentStack() 將返回棧新增到堆疊生成器。 對於在清單檔案中所定義層次結構內的每個 Activity,返回棧均包含可啟動 Activity 的 Intent 物件。此方法還會新增一些可在全新任務中啟動堆疊的標誌。 注:儘管 addParentStack() 的引數是對已啟動 Activity 的引用,但是方法呼叫不會新增可啟動 Activity 的 Intent,而是留待下一步進行處理。

通過呼叫 addNextIntent(),新增可從通知中啟動 Activity 的 Intent。 將在第一步中建立的 Intent 作為 addNextIntent() 的引數傳遞。 如需,請通過呼叫 TaskStackBuilder.editIntentAt() 向堆疊中的 Intent 物件新增引數。有時,需要確保目標 Activity 在使用者使用“返回”導航回它時會顯示有意義的資料。 通過呼叫 getPendingIntent() 獲得此返回棧的 PendingIntent。 然後,您可以使用此 PendingIntent 作為 setContentIntent() 的引數。 以下程式碼段演示了該流程:

...
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent to the top of the stack
stackBuilder.addNextIntent(resultIntent);
// Gets a PendingIntent containing the entire back stack
PendingIntent resultPendingIntent =
        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
...
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
複製程式碼

設定特殊 Activity PendingIntent

下文介紹如何設定特殊 Activity PendingIntent。

特殊 Activity 無需返回棧,因此您不必在清單檔案中定義其 Activity 層次結構,也不必呼叫 addParentStack() 來構建返回棧。取而代之的是,您可使用清單檔案設定 Activity 任務選項,並通過呼叫 getActivity() 建立 PendingIntent:

在清單檔案中,將以下屬性新增到 Activity 的 <activity> 元素
android:name="activityclass"
Activity 的完全限定類名。
android:taskAffinity=""
與您在程式碼中設定的 FLAG_ACTIVITY_NEW_TASK 標誌相結合,這可確保此 Activity 不會進入應用的預設任務。任何具有應用預設關聯的現有任務均不受影響。
android:excludeFromRecents="true"
將新任務從“最新動態”中排除,這樣使用者就不會在無意中導航回它。
以下程式碼段顯示了該元素:
<activity
    android:name=".ResultActivity"
...
    android:launchMode="singleTask"
    android:taskAffinity=""
    android:excludeFromRecents="true">
</activity>
...
複製程式碼

構建併發出通知:

建立可啟動 Activity的 Intent。 通過使用 FLAG_ACTIVITY_NEW_TASK 和 FLAG_ACTIVITY_CLEAR_TASK 標誌呼叫 setFlags(),將 Activity 設定為在新的空任務中啟動。 為 Intent 設定所需的任何其他選項。 通過呼叫 getActivity() 從 Intent 中建立 PendingIntent。 然後,您可以使用此 PendingIntent 作為 setContentIntent() 的引數。 以下程式碼段演示了該流程:

// Instantiate a Builder object.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Creates an Intent for the Activity
Intent notifyIntent =
        new Intent(this, ResultActivity.class);
// Sets the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Creates the PendingIntent
PendingIntent notifyPendingIntent =
        PendingIntent.getActivity(
        this,
        0,
        notifyIntent,
        PendingIntent.FLAG_UPDATE_CURRENT
);

// Puts the PendingIntent into the notification builder
builder.setContentIntent(notifyPendingIntent);
// Notifications are issued by sending them to the
// NotificationManager system service.
NotificationManager mNotificationManager =
    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Builds an anonymous Notification object from the builder, and
// passes it to the NotificationManager
mNotificationManager.notify(id, builder.build());
複製程式碼

在通知中顯示進度

通知可能包括動畫形式的進度指示器,向使用者顯示正在進行的操作狀態。 如果您可以估計操作所需的時間以及任意時刻的完成進度,則使用“限定”形式的指示器(進度欄)。 如果無法估計操作的時長,則使用“非限定”形式的指示器(Activity 指示器)。

平臺的 ProgressBar 類實現中顯示有進度指示器。

要在 Android 4.0 及更高版本的平臺上使用進度指示器,需呼叫 setProgress()。對於早期版本,您必須建立包括 ProgressBar 檢視的自定義通知佈局。

下文介紹如何使用 setProgress() 在通知中顯示進度。

顯示持續時間固定的進度指示器 要顯示限定形式的進度欄,請通過呼叫 setProgress(max, progress, false) 將進度欄新增到通知,然後發出通知。隨著操作繼續進行,遞增 progress 並更新通知。操作結束時, progress 應該等於 max。呼叫 setProgress() 的常見方法是將 max 設定為 100,然後將 progress 作為操作的“完成百分比”值遞增。

您可以在操作完成後仍保留顯示進度欄,也可以將其刪除。無論哪種情況,都請記住更新通知文字以顯示操作已完成。 要刪除進度欄,請呼叫 setProgress(0, 0, false)。例如:

...
mNotifyManager =
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("Picture Download")
    .setContentText("Download in progress")
    .setSmallIcon(R.drawable.ic_notification);
// Start a lengthy operation in a background thread
new Thread(
    new Runnable() {
        @Override
        public void run() {
            int incr;
            // Do the "lengthy" operation 20 times
            for (incr = 0; incr <= 100; incr+=5) {
                    // Sets the progress indicator to a max value, the
                    // current completion percentage, and "determinate"
                    // state
                    mBuilder.setProgress(100, incr, false);
                    // Displays the progress bar for the first time.
                    mNotifyManager.notify(0, mBuilder.build());
                        // Sleeps the thread, simulating an operation
                        // that takes time
                        try {
                            // Sleep for 5 seconds
                            Thread.sleep(5*1000);
                        } catch (InterruptedException e) {
                            Log.d(TAG, "sleep failure");
                        }
            }
            // When the loop is finished, updates the notification
            mBuilder.setContentText("Download complete")
            // Removes the progress bar
                    .setProgress(0,0,false);
            mNotifyManager.notify(ID, mBuilder.build());
        }
    }
// Starts the thread by calling the run() method in its Runnable
).start();
複製程式碼

顯示持續 Activity 指示器

要顯示非限定形式的 Activity 指示器,請使用 setProgress(0, 0, true) 將其新增到通知(忽略前兩個引數),然後發出通知。這樣一來,指示器的樣式就與進度欄相同,只是其動畫還在繼續。

在操作開始之際發出通知。除非您修改通知,否則動畫將一直執行。 操作完成後,呼叫 setProgress(0, 0, false),然後更新通知以刪除 Activity 指示器。 請務必這樣做;否則,即使操作完成,動畫仍將執行。同時,請記得更改通知文字,以表明操作已完成。

要了解 Activity 指示器的工作方式,請參閱上述程式碼段。找到以下幾行:

// Sets the progress indicator to a max value, the current completion
// percentage, and "determinate" state
mBuilder.setProgress(100, incr, false);
// Issues the notification
mNotifyManager.notify(0, mBuilder.build());
將找到的這幾行替換為以下幾行:

 // Sets an activity indicator for an operation of indeterminate length
mBuilder.setProgress(0, 0, true);
// Issues the notification
mNotifyManager.notify(0, mBuilder.build());
複製程式碼

通知後設資料

通知可根據您使用以下 NotificationCompat.Builder 方法分配的後設資料進行排序:

當裝置處於“優先”模式時,setCategory() 會告知系統如何處理應用通知(例如,通知代表傳入呼叫、即時訊息還是鬧鈴)。 如果優先順序欄位設定為 PRIORITY_MAX 或 PRIORITY_HIGH 的通知還有聲音或振動,則 setPriority() 會將其顯示在小型浮動視窗中。 addPerson() 允許您向通知新增人員名單。您的應用可以使用此名單指示系統將指定人員發出的通知歸成一組,或者將這些人員發出的通知視為更重要的通知。

這裡寫圖片描述
圖 3. 顯示浮動通知的全屏 Activity

浮動通知 對於 Android 5.0(API 級別 21),當裝置處於活動狀態時(即,裝置未鎖定且其螢幕已開啟),通知可以顯示在小型浮動視窗中(也稱為“浮動通知”)。 這些通知看上去類似於精簡版的通知​​,只是浮動通知還顯示操作按鈕。 使用者可以在不離開當前應用的情況下處理或清除浮動通知。

可能觸發浮動通知的條件示例包括:

使用者的 Activity 處於全屏模式中(應用使用 fullScreenIntent),或者 通知具有較高的優先順序並使用鈴聲或振動 鎖定螢幕通知 隨著 Android 5.0(API 級別 21)的釋出,通知現在還可顯示在鎖定螢幕上。您的應用可以使用此功能提供媒體播放控制元件以及其他常用操作。 使用者可以通過“設定”選擇是否將通知顯示在鎖定螢幕上,並且您可以指定您應用中的通知在鎖定螢幕上是否可見。

設定可見性

您的應用可以控制在安全鎖定螢幕上顯示的通知中可見的詳細級別。 呼叫 setVisibility() 並指定以下值之一:

VISIBILITY_PUBLIC 顯示通知的完整內容。 VISIBILITY_SECRET 不會在鎖定螢幕上顯示此通知的任何部分。 VISIBILITY_PRIVATE 顯示通知圖示和內容標題等基本資訊,但是隱藏通知的完整內容。 設定 VISIBILITY_PRIVATE 後,您還可以提供其中隱藏了某些詳細資訊的替換版本通知內容。例如,簡訊 應用可能會顯示一條通知,指出“您有 3 條新簡訊”,但是隱藏了簡訊內容和發件人。要提供此替換版本的通知,請先使用 NotificationCompat.Builder 建立替換通知。建立專用通知物件時,請通過 setPublicVersion() 方法為其附加替換通知。

在鎖定螢幕上控制媒體播放 在 Android 5.0(API 級別 21)中,鎖定螢幕不再基於 RemoteControlClient(現已棄用)顯示媒體控制元件。取而代之的是,將 Notification.MediaStyle 模板與 addAction() 方法結合使用,後者可將操作轉換為可點選的圖示。

注:該模板和 addAction() 方法未包含在支援庫中,因此這些功能只能在 Android 5.0 及更高版本的系統上執行。

要在 Android 5.0 系統的鎖定螢幕上顯示媒體播放控制元件,請將可見性設定為 VISIBILITY_PUBLIC,如上文所述。然後,新增操作並設定 Notification.MediaStyle 模板,如以下示例程式碼中所述:

Notification notification = new Notification.Builder(context)
    // Show controls on lock screen even when user hides sensitive content.
    .setVisibility(Notification.VISIBILITY_PUBLIC)
    .setSmallIcon(R.drawable.ic_stat_player)
    // Add media control buttons that invoke intents in your media service
    .addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) // #0
    .addAction(R.drawable.ic_pause, "Pause", pausePendingIntent)  // #1
    .addAction(R.drawable.ic_next, "Next", nextPendingIntent)     // #2
    // Apply the media style template
    .setStyle(new Notification.MediaStyle()
    .setShowActionsInCompactView(1 /* #1: pause button */)
    .setMediaSession(mMediaSession.getSessionToken())
    .setContentTitle("Wonderful music")
    .setContentText("My Awesome Band")
    .setLargeIcon(albumArtBitmap)
    .build();
複製程式碼

注:棄用 RemoteControlClient 會對控制媒體產生進一步的影響。如需瞭解有關用於管理媒體會話和控制播放的新 API 的詳細資訊,請參閱媒體播放控制元件。

自定義通知佈局

您可以利用通知框架定義自定義通知佈局,由該佈局定義通知在 RemoteViews 物件中的外觀。 自定義佈局通知類似於常規通知,但是它們是基於 XML 佈局檔案中所定義的 RemoteViews。

自定義通知佈局的可用高度取決於通知檢視。普通檢視佈局限制為 64 dp,擴充套件檢視佈局限制為 256 dp。

要定義自定義通知佈局,請首先例項化 RemoteViews 物件來擴充 XML 佈局檔案。然後,呼叫 setContent(),而不是呼叫 setContentTitle() 等方法。要在自定義通知中設定內容詳細資訊,請使用 RemoteViews 中的方法設定檢視子項的值:

在單獨的檔案中為通知建立 XML 佈局。您可以根據需要使用任何檔名,但必須使用副檔名 .xml。 在您的應用中,使用 RemoteViews 方法定義通知的圖示和文字。通過呼叫 setContent() 將此 RemoteViews 物件放入 NotificationCompat.Builder 中。避免在 RemoteViews 物件上設定背景 Drawable,因為文字顏色可能使文字變得難以閱讀。 此外,RemoteViews 類中還有一些方法可供您輕鬆將 Chronometer 或 ProgressBar 新增到通知佈局。如需瞭解有關為通知建立自定義佈局的詳細資訊,請參閱 RemoteViews 參考文件。

注意:

使用自定義通知佈局時,要特別注意確保自定義佈局適用於不同的裝置方向和解析度。 儘管這條建議適用於所有“檢視”佈局,但對通知尤為重要,因為抽屜式通知欄中的空間非常有限。 不要讓自定義佈局過於複雜,同時確保在各種配置中對其進行測試。

對自定義通知文字使用樣式資源 始終對自定義通知的文字使用樣式資源。通知的背景顏色可能因裝置和系統版本的不同而異,使用樣式資源有助於您充分考慮到這一點。 從 Android 2.3 開始,系統定義了標準通知佈局文字的樣式。若要在面向 Android 2.3 或更高版本系統的多個應用中使用相同樣式,則應確保文字在顯示背景上可見。

相關文章