### **通知**
**關鍵類**
* [NotificationManager](https://developer.android.com/reference/android/app/NotificationManager.html)
* [NotificationCompat](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.html)
**視頻**
[4.1 中的通知](http://www.youtube.com/watch?v=Yc8YrVc47TI&feature=player_detailpage#t=1672s)
**另請參閱**
[Android 設計:通知](https://developer.android.com/design/patterns/notifications.html)
通知是您可以在應用的常規 UI 外部向用戶顯示的消息。當您告知系統發出通知時,它將先以圖標的形式顯示在通知區域中。用戶可以打開抽屜式通知欄查看通知的詳細信息。 通知區域和抽屜式通知欄均是由系統控制的區域,用戶可以隨時查看。
:-: 
圖 1. 通知區域中的通知。
:-: 
圖 2. 抽屜式通知欄中的通知。
> 注:除非特別注明,否則本指南均引用版本 4 支持庫中的 [NotificationCompat.Builder](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html) 類。Android 3.0(API 級別 11)中已添加類 [Notification.Builder](https://developer.android.com/reference/android/app/Notification.Builder.html)。
#### **設計注意事項**
作為 Android 用戶界面的一個重要組成部分,通知具有自己的設計指導方針。Android 5.0(API 級別 21)中引入的 Material Design 變更尤為重要,您應查閱[Material Design](https://developer.android.com/training/material/index.html)培訓資料了解詳細信息。 要了解如何設計通知及其交互,請閱讀[通知](https://developer.android.com/design/patterns/notifications.html)設計指南。
#### **創建通知**
您可以在 NotificationCompat.Builder 對象中為通知指定 UI 信息和操作。要創建通知,請調用 [NotificationCompat.Builder.build()](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#build()),它將返回包含您的具體規范的 [Notification](https://developer.android.com/reference/android/app/Notification.html) 對象。要發出通知,請通過調用 [NotificationManager.notify()](https://developer.android.com/reference/java/lang/Object.html#notify()) 將 Notification 對象傳遞給系統。
##### **必需的通知內容**
Notification 對象必須包含以下內容:
* 小圖標,由 setSmallIcon() 設置
* 標題,由 setContentTitle() 設置
* 詳細文本,由 setContentText() 設置
##### **可選通知內容和設置**
所有其他通知設置和內容都是可選的。如需了解有關它們的更多詳情,請參閱 NotificationCompat.Builder 參考文檔。
##### **通知操作**
盡管通知操作都是可選的,但是您至少應向通知添加一個操作。 操作允許用戶直接從通知轉到應用中的 [Activity](https://developer.android.com/reference/android/app/Activity.html),他們可在其中查看一個或多個事件或執行進一步的操作。
一個通知可以提供多個操作。您應該始終定義一個當用戶點擊通知時會觸發的操作;通常,此操作會在應用中打開 Activity。 您也可以向通知添加按鈕來執行其他操作,例如,暫停鬧鈴或立即答復短信;此功能自 Android 4.1 起可用。如果使用其他操作按鈕,則您還必須使這些按鈕的功能在應用的 Activity 中可用;請參閱[處理兼容性](https://developer.android.com/guide/topics/ui/notifiers/notifications.html#Compatibility)部分,以了解更多詳情。
在 Notification 內部,操作本身由 [PendingIntent](https://developer.android.com/reference/android/app/PendingIntent.html) 定義,后者包含在應用中啟動 Activity 的 Intent。要將 PendingIntent 與手勢相關聯,請調用 NotificationCompat.Builder 的適當方法。例如,如果您要在用戶點擊抽屜式通知欄中的通知文本時啟動 Activity,則可通過調用 [setContentIntent()](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#setContentIntent(android.app.PendingIntent)) 來添加 PendingIntent。
在用戶點擊通知時啟動 Activity 是最常見的操作場景。此外,您還可以在用戶清除通知時啟動 Activity。在 Android 4.1 及更高版本中,您可以通過操作按鈕啟動 Activity。如需了解更多信息,請閱讀參考指南的 NotificationCompat.Builder 部分。
##### **通知優先級**
您可以根據需要設置通知的優先級。優先級充當一個提示,提醒設備 UI 應該如何顯示通知。 要設置通知的優先級,請調用 NotificationCompat.Builder.setPriority() 并傳入一個 NotificationCompat 優先級常量。有五個優先級別,范圍從 [PRIORITY_MIN](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.html#PRIORITY_MIN) (-2) 到 [PRIORITY_MAX](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.html#PRIORITY_MAX) (2);如果未設置,則優先級默認為 [PRIORITY_DEFAULT](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.html#PRIORITY_DEFAULT) (0)。
有關設置適當優先級別的信息,請參閱通知設計指南中的“正確設置和管理通知優先級”。
##### **創建簡單通知**
以下代碼段說明了一個指定某項 Activity 在用戶點擊通知時打開的簡單通知。 請注意,該代碼將創建 [TaskStackBuilder](https://developer.android.com/reference/android/support/v4/app/TaskStackBuilder.html) 對象并使用它來為操作創建 PendingIntent。[啟動 Activity 時保留導航](https://developer.android.com/guide/topics/ui/notifiers/notifications.html#NotificationResponse)部分對此模式做了更詳盡的闡述:
~~~
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()](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#setStyle(android.support.v4.app.NotificationCompat.Style))。
請記住,擴展通知在 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)創建通知。此外,在實現通知時,請遵循以下流程:
1. 為所有用戶提供通知的全部功能,無論他們使用何種版本的 Android 系統。 為此,請驗證是否可從應用的 Activity 中獲得所有功能。要執行此操作,您可能需要添加新的 Activity。
例如,若要使用 addAction() 提供停止和啟動媒體播放的控件,請先在應用的 Activity 中實現此控件。
2. 確保所有用戶均可通過點擊通知啟動 Activity 來獲得該Activity中的功能。 為此,請為 Activity 創建 PendingIntent。調用 setContentIntent() 以將 PendingIntent 添加到通知。
3. 現在,將要使用的擴展通知功能添加到通知。請記住,您添加的任何功能還必須在用戶點擊通知時啟動的 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,請執行以下步驟:
1. 在清單文件中定義應用的 Activity 層次結構。
* 添加對 Android 4.0.3 及更低版本的支持。為此,請通過添加 [`<meta-data>`](https://developer.android.com/guide/topics/manifest/meta-data-element.html) 元素作為 [`<activity>`](https://developer.android.com/guide/topics/manifest/activity-element.html)的子項來指定正在啟動的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>
~~~
2. 根據可啟動 Activity 的 Intent 創建返回棧:
* 創建 Intent 以啟動 Activity。
* 通過調用 TaskStackBuilder.create() 創建堆棧生成器。
* 通過調用 addParentStack() 將返回棧添加到堆棧生成器。 對于在清單文件中所定義層次結構內的每個 Activity,返回棧均包含可啟動 Activity 的 Intent 對象。此方法還會添加一些可在全新任務中啟動堆棧的標志。
> 注:盡管 addParentStack() 的參數是對已啟動 Activity 的引用,但是方法調用不會添加可啟動 Activity 的 Intent,而是留待下一步進行處理。
* 通過調用 [addNextIntent()](https://developer.android.com/reference/android/support/v4/app/TaskStackBuilder.html#addParentStack(android.app.Activity)),添加可從通知中啟動 Activity 的 Intent。 將在第一步中創建的 Intent 作為 addNextIntent() 的參數傳遞。
* 如需,請通過調用 [TaskStackBuilder.editIntentAt()](https://developer.android.com/reference/android/support/v4/app/TaskStackBuilder.html#editIntentAt(int)) 向堆棧中的 Intent 對象添加參數。有時,需要確保目標 Activity 在用戶使用“返回”導航回它時會顯示有意義的數據。
* 通過調用 [getPendingIntent()](https://developer.android.com/reference/android/support/v4/app/TaskStackBuilder.html#getPendingIntent(int, int)) 獲得此返回棧的 PendingIntent。 然后,您可以使用此 PendingIntent 作為 [setContentIntent()](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#setContentIntent(android.app.PendingIntent)) 的參數。
以下代碼段演示了該流程:
~~~
...
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](https://developer.android.com/reference/android/app/PendingIntent.html)。
特殊 Activity 無需返回棧,因此您不必在清單文件中定義其 Activity 層次結構,也不必調用 addParentStack() 來構建返回棧。取而代之的是,您可使用清單文件設置 Activity 任務選項,并通過調用 getActivity() 創建 PendingIntent:
1. 在清單文件中,將以下屬性添加到 Activity 的 [`<activity>`](https://developer.android.com/guide/topics/manifest/activity-element.html) 元素
* `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>
...
~~~
2. 構建并發出通知:
* 創建可啟動 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](https://developer.android.com/reference/android/widget/ProgressBar.html) 類實現中顯示有進度指示器。
要在 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 ](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html)方法分配的元數據進行排序:
* 當設備處于“優先”模式時,setCategory() 會告知系統如何處理應用通知(例如,通知代表傳入呼叫、即時消息還是鬧鈴)。
* 如果優先級字段設置為 PRIORITY_MAX 或 PRIORITY_HIGH 的通知還有聲音或振動,則 setPriority() 會將其顯示在小型浮動窗口中。
* addPerson() 允許您向通知添加人員名單。您的應用可以使用此名單指示系統將指定人員發出的通知歸成一組,或者將這些人員發出的通知視為更重要的通知。
#### **浮動通知**
對于 Android 5.0(API 級別 21),當設備處于活動狀態時(即,設備未鎖定且其屏幕已打開),通知可以顯示在小型浮動窗口中(也稱為“浮動通知”)。 這些通知看上去類似于精簡版的通知??,只是浮動通知還顯示操作按鈕。 用戶可以在不離開當前應用的情況下處理或清除浮動通知。
可能觸發浮動通知的條件示例包括:
* 用戶的 Activity 處于全屏模式中(應用使用 fullScreenIntent),或者
* 通知具有較高的優先級并使用鈴聲或振動
:-: 
圖 3. 顯示浮動通知的全屏 Activity
#### **鎖定屏幕通知**
隨著 Android 5.0(API 級別 21)的發布,通知現在還可顯示在鎖定屏幕上。您的應用可以使用此功能提供媒體播放控件以及其他常用操作。 用戶可以通過“設置”選擇是否將通知顯示在鎖定屏幕上,并且您可以指定您應用中的通知在鎖定屏幕上是否可見。
#### **設置可見性**
您的應用可以控制在安全鎖定屏幕上顯示的通知中可見的詳細級別。 調用 [setVisibility()](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#setVisibility(int)) 并指定以下值之一:
* [VISIBILITY_PUBLIC](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.html#VISIBILITY_PUBLIC) 顯示通知的完整內容。
* [VISIBILITY_SECRET](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.html#VISIBILITY_SECRET) 不會在鎖定屏幕上顯示此通知的任何部分。
* [VISIBILITY_PRIVATE](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.html#VISIBILITY_PRIVATE) 顯示通知圖標和內容標題等基本信息,但是隱藏通知的完整內容。
設置 VISIBILITY_PRIVATE 后,您還可以提供其中隱藏了某些詳細信息的替換版本通知內容。例如,短信 應用可能會顯示一條通知,指出“您有 3 條新短信”,但是隱藏了短信內容和發件人。要提供此替換版本的通知,請先使用 NotificationCompat.Builder 創建替換通知。創建專用通知對象時,請通過 setPublicVersion() 方法為其附加替換通知。
#### **在鎖定屏幕上控制媒體播放**
在 Android 5.0(API 級別 21)中,鎖定屏幕不再基于 [RemoteControlClient](https://developer.android.com/reference/android/media/RemoteControlClient.html)(現已棄用)顯示媒體控件。取而代之的是,將 [Notification.MediaStyle](https://developer.android.com/reference/android/app/Notification.MediaStyle.html) 模板與 [addAction()](https://developer.android.com/reference/android/app/Notification.Builder.html#addAction(android.app.Notification.Action)) 方法結合使用,后者可將操作轉換為可點擊的圖標。
> 注:該模板和 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 的詳細信息,請參閱[媒體播放控件](https://developer.android.com/about/versions/android-5.0.html#MediaPlaybackControl)。
#### **自定義通知布局**
您可以利用通知框架定義自定義通知布局,由該布局定義通知在 [RemoteViews](https://developer.android.com/reference/android/widget/RemoteViews.html) 對象中的外觀。 自定義布局通知類似于常規通知,但是它們是基于 XML 布局文件中所定義的 RemoteViews。
自定義通知布局的可用高度取決于通知視圖。普通視圖布局限制為 64 dp,擴展視圖布局限制為 256 dp。
要定義自定義通知布局,請首先實例化 RemoteViews 對象來擴充 XML 布局文件。然后,調用 setContent(),而不是調用 setContentTitle() 等方法。要在自定義通知中設置內容詳細信息,請使用 RemoteViews 中的方法設置視圖子項的值:
1. 在單獨的文件中為通知創建 XML 布局。您可以根據需要使用任何文件名,但必須使用擴展名 .xml。
2. 在您的應用中,使用 RemoteViews 方法定義通知的圖標和文本。通過調用 setContent() 將此 RemoteViews 對象放入 NotificationCompat.Builder 中。避免在 RemoteViews 對象上設置背景 [Drawable](https://developer.android.com/reference/android/graphics/drawable/Drawable.html),因為文本顏色可能使文本變得難以閱讀。
此外,RemoteViews 類中還有一些方法可供您輕松將 [Chronometer](https://developer.android.com/reference/android/widget/Chronometer.html) 或 [ProgressBar](https://developer.android.com/reference/android/widget/ProgressBar.html) 添加到通知布局。如需了解有關為通知創建自定義布局的詳細信息,請參閱 RemoteViews 參考文檔。
> **注意**:使用自定義通知布局時,要特別注意確保自定義布局適用于不同的設備方向和分辨率。 盡管這條建議適用于所有“視圖”布局,但對通知尤為重要,因為抽屜式通知欄中的空間非常有限。 不要讓自定義布局過于復雜,同時確保在各種配置中對其進行測試。
#### **對自定義通知文本使用樣式資源**
始終對自定義通知的文本使用樣式資源。通知的背景顏色可能因設備和系統版本的不同而異,使用樣式資源有助于您充分考慮到這一點。 從 Android 2.3 開始,系統定義了標準通知布局文本的樣式。若要在面向 Android 2.3 或更高版本系統的多個應用中使用相同樣式,則應確保文本在顯示背景上可見。
- 前言
- Google官網對Android API各版本的介紹
- jelly Bean(果凍豆)Android 4.1、4.2、4.3
- Android 4.1
- Android 4.2
- Android 4.3
- KitKat(Android 4.4.*)巧克力
- Android 4.4 APIS
- Lollipop(棒棒糖)Android 5.*
- Android 5.0 APIs
- Android 5.0 Changes(變更)
- Android 5.1APIs
- Marshmallow(棉花糖)Android 6.0
- Android 6.0 APIs
- Android 6.0 Changes(變更)
- Android 6.0 Samples
- Android 6.0 Testing
- Nougat(牛扎塘)Android 7.*
- Android 7.0
- API
- 行為變更
- 示例
- Android 7.1
- 開發者API
- 示例Sample
- Oreo(奧利奧)8.*
- Android 8.0
- 功能和 API
- Android 8.0 行為變更
- 向 Android 8.0 遷移應用
- Android 8.0 示例
- Android 8.1
- 后臺執行限制
- 后臺位置限制
- API指南
- Android 簡介
- 應用基礎知識
- 設備兼容性
- 系統權限
- 請求權限
- 定義權限
- 平臺架構
- Java8 概覽
- 在ART上驗證應用行為
- 應用組件
- Intent 和 Intent 過濾器(Google官網介紹)
- 通用intent
- Activity
- 任務和返回棧(官網譯文)
- 概覽屏幕
- 活動簡介
- 活動生命周期
- 活動狀態更改
- 進程和應用程序生命周期
- 包裹和捆綁
- 最近的屏幕
- 片段
- 加載器
- 服務Service
- 綁定服務
- AIDL
- 內容提供程序
- 內容提供程序基礎知識
- 創建內容提供程序
- 日歷提供程序
- 聯系人提供程序
- 存儲訪問框架
- 使用存儲訪問框架打開文件
- 創建自定義文檔提供程序
- 應用小部件
- 應用小部件主機
- 進程和線程
- 應用資源
- 概覽
- 提供資源
- 訪問資源
- 處理運行時變更
- 本地化
- ICU4J Android框架API
- Android上的國際化
- 語言和語言區域
- 復雜的XML資源
- 資源類型
- 動畫
- 顏色狀態列表
- 可繪制對象
- 布局
- 菜單
- 字符串
- 樣式
- 其他類型
- 應用清單
- <action>
- <activity>
- <activity-alias>
- <application>
- <category>
- <compatiable-screens>
- <data>
- <grant-uri-permission>
- <intent-filter>
- <manifest>
- <meta-data>
- <path-permission>
- <permission>
- <permission-group>
- <permission-tree>
- <provider>
- <receiver>
- <service>
- <supporte-gl-texture>
- <supports-screens>
- <uses-configuration>
- <uses-feature>
- <uses-library>
- <uses-permission>
- <uses-permission-sdk-23>
- <uses-sdk>
- 用戶界面
- 界面概覽
- 界面布局
- 線性布局
- 相對布局
- 列表視圖
- 網格視圖
- 回收站視圖
- 外觀和感覺
- 可下載的字體
- XML中的字體
- 表情符號兼容性
- 自動調整TextView
- 樣式和主題-
- 輸入控件
- 按鈕
- 文本字段
- 復選框
- 單選按鈕
- 切換按鈕
- 微調框
- 選取器
- 輸入事件
- 菜單Menu
- 設置
- 對話框
- 通知
- Toast
- 自適應圖標
- 應用快捷方式
- 搜索
- 創建搜索界面
- 添加近期查詢建議
- 添加自定義建議
- 可搜索配置
- 多窗口支持
- 拖放
- 無障礙功能
- 為應用設置無障礙功能
- 無障礙功能開發者檢查單
- 構建無障礙服務
- 讓應用更容易訪問
- 使用節點樹調試
- 構建可訪問自定義視圖
- 樣式和主題
- 自定義組件
- 動畫和圖形
- 概覽介紹
- 屬性動畫
- 視圖動畫
- 可繪制動畫
- 畫布和可繪制對象
- 基于物理的動畫
- Spring Animation
- Fling Animation
- OpenGL ES
- 硬件加速
- 計算
- RenderScript
- 高級RenderScript
- Runtime API Reference(參考)
- Numerical Types(數字類型)
- Object Types(對象類型)
- Conversion Functions(轉換函數)
- Mathematical Constants and Functions(數學常量和函數)
- Vector Math Functions(矢量數學函數)
- Matrix Functions(矩陣函數)
- Quaternion Functions(四元數函數)
- Atomic Update Functions(原子更新函數)
- Time Functions and Types(時間函數和類型)
- Allocation Data Access Functions(分配數據訪問函數)
- Object Characteristics Functions(對象特性函數)
- Kernel Invocation Functions and Types(內核調用函數和類型)
- Input/Output Functions(輸入輸出函數)
- Debugging Functions(調試函數)
- Graphics Functions and Types(圖形函數和類型)
- Index(索引)
- Media Apps(媒體應用)
- Media Apps Overview(媒體應用程序概述)
- Working with a Media Session(使用媒體會話)
- Building an Audio App(建立一個音頻應用)
- Building a Media Browser Service(構建媒體瀏覽器服務)
- Building a Media Browser Client(構建媒體瀏覽器客戶端)
- Media Session Callbacks(媒體會話回調)
- Building a Video App(建立一個視頻應用)
- Building a Video Player Activity(建立一個視頻播放器Activity)
- Media Session Callbacks-(媒體會話回調)
- Responding to Media Buttons(響應媒體按鈕)
- Handling Changes in Audio Output(處理音頻輸出的變化)
- Managing Audio Focus(管理音頻焦點)
- The Google Assistant and Media Apps(Google智能助理和媒體應用)
- 媒體和相機
- Supported Media Formats(支持的媒體格式)
- MediaPlayer(媒體播放器)
- MediaRecorder
- ExoPlayer
- Controller Amplitude with VolumeShaper(VolumeShaper控制器振幅)
- Media Routing(媒體路由)
- MediaRouter API
- MediaRouteProvider API
- Camera API(相機API)
- 位置和傳感器
- Location and Maps(位置和地圖)
- Location Strategies(位置策略)
- Sensors Overview(傳感器概覽)
- Motion Sensors(運動傳感器)
- Position Sensors(位置傳感器)
- Environment Sensors(環境傳感器)
- Raw GNSS Measurements(原始的GNSS測量)
- 連接
- Bluetooth
- Bluetooth Low Energy(藍牙低功耗)
- NFC
- NFC Basics(NFC基礎知識)
- Advanced NFC(高級NFC)
- Host-based Card Emulation(基于主機的卡模擬)
- Telecom(電信)
- Self-Managed ConnectionServices(自我管理的連接服務)
- Wi-Fi P2P
- Wi-Fi Aware
- Companion Device Pairing
- USB
- Accessory(配件)
- Host(主機)
- SIP
- 文本和輸入
- Autofill Framework(自動填充框架)
- Test your app with autofill(使用自動填充測試你的應用)
- Building autofill services(構建自動填充服務)
- Copy and Paste(復制和粘貼)
- Creating an IME(創建IME)
- Image Keyboard(圖像鍵盤)
- Spelling Checker(拼寫檢查程序)
- 數據存儲
- Storage Options(存儲選項)
- Data Backup(數據備份)
- Account Transfer API(賬戶轉移API)
- Auto Backup(自動備份)
- Key/Value Backup(鍵值備份)
- Testing Backup and Restore(測試備份和還原)
- App Install Location(應用安裝位置)
- 庫
- 支持庫
- 功能
- 修訂歷史記錄
- 庫設置
- 數據綁定庫
- 測試支持庫
- 管理
- 設備策略
- 網絡應用
- Supporting Different Screens in Web Apps(在網絡應用中支持不同屏幕)
- Building Web Apps in WebView(在WebView中構建網絡應用)
- Managing WebViews
- Migrating to WebView in Android 4.4(遷移到Android4.4中的WebView)
- Debugging Web Apps(調試網絡應用)
- Best Practices for Web Apps(網絡應用最佳做法)
- 最佳實踐
- Supporting Multiple Screens(支持多種屏幕)
- Distributing to Specific Screens(分配到特定屏幕)
- Screen Compatibility Mode(屏幕兼容性模式)
- Designing for Seamlessness
- Supporting Tablets and Handsets
- 培訓