Android開發者指南-創建狀態欄通知(Status Bar)[原創譯文]

User Interface

--Notifying the User

--Creating Status Bar Notifications

版本:Android 3.2

 

快速查看

·           狀態欄(status bar)通知允許應用程序以不干擾當前activity的方式將事件通知用戶。

·           可以給通知綁定一個意圖(intent),當用戶點擊時系統會執行此意圖。

 

在本文中

基礎知識

管理通知

創建通知

更新通知

添加聲音

添加振動

添加閃光

其他特性

創建自定義的展開View

關鍵類

Notification

NotificationManager

狀態欄(status bar)通知將一個圖標填加到系統的狀態欄中(包含一條可選的提示文本信息),並將一條展開信息添加到通知窗口中。當用戶選中展開信息時,Android將執行一個此通知已定義的意圖Intent(通常用於彈出一個Activity)。你還可以對通知進行配置,用設備提供的聲音、振動、閃光來提醒用戶。

 

當後臺服務(Service)需要對某個事件發出提醒並且需要用戶響應時,狀態欄通知就能發揮作用了。後臺服務從來不會啓動Activity來接收用戶的交互,取而代之的是應該創建一個狀態欄通知,在用戶點選後再由通知來啓動Activity

 

以下截圖展示了一個左側帶有通知圖標的狀態欄:

Android開發者指南-創建狀態欄通知(Status <wbr>Bar)[原創譯文]

下圖展示了“Notifications”窗口內的通知展開信息。用戶可通過下拉狀態欄(或在Home菜單裏選中通知)來顯示這個通知窗口。

Android開發者指南-創建狀態欄通知(Status <wbr>Bar)[原創譯文]

 

基礎知識

Activity或者Service都能初始化一個狀態欄通知。可因爲Activity只有在活動狀態並獲得焦點時才能執行操作,所以還是建議用Service來創建狀態欄通知。這樣,即使用戶正在使用其他程序或者設備已經休眠時,仍然可以從後臺創建通知。要創建一個通知,須用到兩個類:Notification類和NotificationManager類。

 

Notification類的一個實例來定義狀態欄通知的屬性,比如圖標、展開信息,以及播放聲音等附屬設置。NotificationManager是一個Android系統服務,用於管理和運行所有通知。NotificationManager不能被實例化,爲了把Notification傳給它,你可以用getSystemService()方法獲取一個NotificationManager的引用。在需要通知用戶時再調用notify()方法將Notification對象傳給它。

 

要創建一個狀態欄通知:

1. 獲取NotificationManager的引用:

String ns =Context.NOTIFICATION_SERVICE; 

NotificationManager mNotificationManager =(NotificationManager)getSystemService(ns);

2. 實例化Notification

int icon = R.drawable.notification_icon; 

CharSequence tickerText ="Hello"; 

longwhen=System.currentTimeMillis(); 

Notification notification =newNotification(icon, tickerText,when);

3. 指定通知的展開信息和Intent

Context context = getApplicationContext(); 

CharSequence contentTitle ="My notification"; 

CharSequence contentText ="Hello World!"; 

Intent notificationIntent =newIntent(this,MyClass.class); 

PendingIntent contentIntent =PendingIntent.getActivity(this,0,notificationIntent,0); 

notification.setLatestEventInfo(context, contentTitle, contentText,contentIntent);

4. Notification對象傳給NotificationManager:

privatestaticfinalint HELLO_ID =1;  

mNotificationManager.notify(HELLO_ID, notification);

好了,現在用戶已經能看到通知了。

 

管理通知

系統服務NotificationManager管理着所有的通知,只能通過getSystemService()方法來獲取它的引用。例如:

String ns =Context.NOTIFICATION_SERVICE; 

NotificationManager mNotificationManager =(NotificationManager)getSystemService(ns);

如果想要發送狀態欄通知,通過notify(int, Notification)傳遞Notification對象給NotificationManager即可。第一個參數是Notification 的唯一ID,第二個參數是Notification對象。ID在整個應用程序範圍內唯一標識NotificationNotification需要更新;應用程序可能管理着多種不同的通知,在用戶通過各自定義的Intent返回應用程序時必須能選擇正確的動作執行之,因此上述參數是必需的。

要實現用戶從通知窗口內點選後自動清除狀態欄通知,請在Notification對象中加入“FLAG_AUTO_CANCEL”標誌。也可以傳入通知IDcancel(int)手動清除,或者用cancelAll()清除所有你創建的通知。

 

創建通知

Notification對象定義了通知消息顯示在狀態欄和通知窗口上的細節內容,以及其他提醒設置(比如:聲音、閃光等)。

 

狀態欄通知必須包括以下內容:

·       狀態欄圖標

·       展開窗口view的標題和展開信息(除非用了自定義展開view

·       PendingIntent,當通知被點選時執行

 

狀態欄通知的可選設置包括:

·       狀態欄提示信息

·       提醒聲音

·       震動設置

·       LED燈閃光設置

 

Notification基礎庫(譯者注:原文是starter-kit,但綜合上下文並非“初學者套件”的意思)裏包含了構造方法Notification(int, CharSequence, long)setLatestEventInfo(Context, CharSequence, CharSequence, PendingIntent)方法。這已經可以定義Notification的所有設置。以下代碼段演示了對通知基本的設置:

int icon = R.drawable.notification_icon;        // icon from resources 

CharSequence tickerText ="Hello";              // ticker-text 

longwhen=System.currentTimeMillis();         // notification time 

Context context = getApplicationContext();      // application Context 

CharSequence contentTitle ="My notification";  // expanded message title 

CharSequence contentText ="Hello World!";      // expanded message text 

 

Intent notificationIntent =newIntent(this,MyClass.class); 

PendingIntent contentIntent =PendingIntent.getActivity(this,0,notificationIntent,0); 

 

// the next two lines initialize the Notification, using the configurations above 

Notification notification =newNotification(icon, tickerText,when); 

notification.setLatestEventInfo(context, contentTitle, contentText,contentIntent);

 

更新通知

應用程序可以在事件正在進行時更新狀態欄通知。比如,前一條短信還未讀,可又來了一條新短信,短信程序爲了正確顯示未讀短信的總數,可以更新已有的通知。此時,更新原有通知要比向NotificationManager新增一條通知更合理些,因爲避免了通知窗口的顯示混亂。

 

因爲NotificationManager對每個通知都用一個整數ID進行了唯一標識,新的通知內容可以用setLatestEventInfo()方法方便地進行修改,然後再次調用notify()顯示出來。

 

除了Context、展開信息的標題和文本外,可以利用對象的成員值修改每個屬性。要修改通知的文本信息,只能對contentTitlecontentText參數賦新值並調用setLatestEventInfo(),然後再調用notify()方法來更新通知。(當然,如果已經創建了自定義擴展view,那麼標題和文本的修改就無效了)。

 

添加聲音

可以用缺省提示音(由用戶指定)或者程序指定聲音來提醒用戶。

 

要使用用戶缺省提示音,給defaults屬性添加“DEFAULT_SOUND”:

notification.defaults |=Notification.DEFAULT_SOUND;

 

要使用應用程序指定的聲音,則傳遞一個Uri引用給sound屬性。以下例子使用已保存在設備SD卡上的音頻文件作爲提示音:

notification.sound =Uri.parse("file:///sdcard/notification/ringer.mp3");

 

在下面的例子裏,音頻文件從內部MediaStore類的ContentProvider中獲取:

notification.sound =Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI,"6");

這時,已知有資源ID6的媒體文件,並且已添加到Uri內容中。如果不知道確切的ID,則必須先用ContentResolver查詢MediaStore中所有可用的資源。關於使用ContentResolver的詳細信息請參閱Content Providers文檔。

 

如果期望在用戶響應通知或取消通知前,聲音一直持續循環播放,可以把FLAG_INSISTENT加入flags屬性中。

注意:如果defaults屬性包含了“DEFAULT_SOUND”,則缺省提示音將覆蓋sound屬性裏指定的聲音。

 

添加振動

可以用缺省震動模式或程序指定的振動模式來提醒用戶。

 

要用缺省震動模式,給屬性defaults添加“DEFAULT_VIBRATE即可:

notification.defaults |=Notification.DEFAULT_VIBRATE;

 

要自定義震動模式,須給vibrate屬性傳遞一個long類型的數組:

long[] vibrate ={0,100,200,300}; 

notification.vibrate = vibrate;

長整型數組定義了震動開和關交替的時間(毫秒)。第一個數是開始振動前的等待時間(震動關閉),第二個數是第一次開啓振動的持續時間,第三個數是下一次關閉時間,如此類推。振動模式的持續時間沒有限制,但不能設置爲重複振動。

注意:如果defaults屬性包含了“DEFAULT_VIBRATE”,則缺省的震動模式將會覆蓋vibrate屬性裏指定的模式。

 

添加閃光

要想用LED閃光來提醒用戶,可以執行缺省閃光模式(如果可用的話),也可以自定義閃光的顏色和模式。

 

要使用缺省的閃光設置,給屬性defaults添加“DEFAULT_LIGHTS”即可:

notification.defaults |=Notification.DEFAULT_LIGHTS;

 

要自定義顏色和模式,則須指定ledARGB屬性(指顏色)、ledOffMS屬性(閃光關閉毫秒數)、ledOnMS屬性(閃光開啓毫秒數),並在“flags”屬性里加入“FLAG_SHOW_LIGHTS”:

notification.ledARGB =0xff00ff00; 

notification.ledOnMS =300; 

notification.ledOffMS =1000; 

notification.flags |=Notification.FLAG_SHOW_LIGHTS;

上例實現了綠色光閃爍300毫秒間歇1秒的閃光。每個設備的LED燈不可能支持所有顏色的發光,不同的設備所能支持的顏色也各不相同,因此硬件將按照最接近的顏色來發光。綠色是最常見的提醒色。

 

其他特性

利用Notification的屬性和標誌位,可以給通知添加更多的特性。

 

下面列出了其中一些常用的特性:

FLAG_AUTO_CANCEL”標誌

flags屬性中增加此標誌,則在通知窗口點選後能自動取消通知。

FLAG_INSISTENT”標誌

flags屬性中增加此標誌,則在用戶響應前一直循環播放聲音。

FLAG_ONGOING_EVENT”標誌

flags屬性中增加此標誌,則將通知放入通知窗口的“正在運行”(Ongoing)組中。表示應用程序正在運行——進程仍在後臺運行,即使應用程序不可見(比如播放音樂或接聽電話)。

FLAG_NO_CLEAR”標誌

flags屬性中增加此標誌,表示通知不允許被“清除通知”按鈕清除。這在期望通知保持運行時特別有用。

number屬性

表示通知所代表的事件數量。此數字顯示在狀態欄圖標上。要利用此屬性,必須在第一次創建通知時設爲1。(如果只是在更新通知時才把此值從0改成任意大於0的數,則數字不會顯示出來。)

iconLevel屬性

表示通知圖標當前的LevelListDrawable等級。通過改變這個值,可以在狀態欄中顯示圖標的動畫,這個值與LevelListDrawabledrawable的定義相關。詳情請參閱LevelListDrawable

 

程序能自定義更多特性,詳情請參閱Notification

 

創建自定義的展開View認情況下,通知窗口中的展開視圖(view)包括基本的標題和文本信息。這是由setLatestEventInfo()contentTitlecontentText參數指定的。不過仍可以用RemoteViews來自定義一個展開視圖的佈局。右側的截圖就展示了一個自定義展開視圖的例子,其中用到了LinearLayout 佈局中的ImageViewTextView

 

要自定義展開信息的佈局,需要實例化一個RemoteViews對象,並將它傳遞給NotificationcontentView屬性,同時把PendingIntent傳給contentIntent屬性。

 

通過例子是對創建自定義展開視圖最好的理解方式:

1. 爲展開視圖新建XML佈局,建立一個名爲custom_notification_layout.xml的佈局文件,內容如下:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" 

              android:orientation="horizontal" 

              android:layout_width="fill_parent" 

              android:layout_height="fill_parent" 

              android:padding="3dp" 

              > 

    <ImageViewandroid:id="@+id/image" 

              android:layout_width="wrap_content" 

              android:layout_height="fill_parent" 

              android:layout_marginRight="10dp" 

              /> 

    <TextViewandroid:id="@+id/text" 

              android:layout_width="wrap_content" 

              android:layout_height="fill_parent" 

              android:textColor="#000" 

              /> 

</LinearLayout>

此佈局用於展開視圖,但ImageViewTextView的內容還需要由應用程序來定義。RemoteViews提供了一些方便的方法來定義這些內容。

 

2. 在應用程序代碼裏,用RemoveViews的方法來定義圖片和文字。然後把RemoteViews對象傳給NotificationcontentView屬性,如下所示:

RemoteViews contentView =newRemoteViews(getPackageName(),R.layout.custom_notification_layout); 

contentView.setImageViewResource(R.id.image, R.drawable.notification_image); 

contentView.setTextViewText(R.id.text,"Hello, this message is in a custom expanded view"); 

notification.contentView = contentView;

如上:先把程序package名和佈局資源ID傳給RemoteViews的構造方法。然後用setImageViewResource()setTextViewText()定義ImageViewTextView的內容,分別把View對象的資源ID、所賦的內容作爲參數傳入。最後,把RemoteViews對象傳給NotificationcontentView屬性。

 

3. 由於自定義視圖不需要執行setLatestEventInfo()方法,因此必須用contentIntent屬性來定義一個通知所要執行的意圖Intent ,如下:

Intent notificationIntent =newIntent(this,MyClass.class); 

PendingIntent contentIntent =PendingIntent.getActivity(this,0,notificationIntent,0); 

notification.contentIntent = contentIntent;

 

4. 現在通知可以如常發送了:

mNotificationManager.notify(CUSTOM_VIEW_ID, notification);

 

RemoteViews類還包含了一些方法,便於在通知的展開視圖裏增加ChronometerProgressBar。關於用RemoteViews創建自定義佈局的詳細信息,請參閱RemoteViews類的參考文檔。

 

注意:當建立一個自定義展開視圖時,必須特別小心,保證自定義的佈局能正常工作在不同的設備方向和分辨率下。這個建議對於所有在Android上創建的View佈局都是適用的,但在這種情況下尤爲重要,因爲佈局實際可用的屏幕區域非常有限。不要把自定義佈局設計得過於複雜,並且一定要在各種環境配置下進行測試。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章