《Android Dev Guide》系列教程16:使用者通知(3)建立狀態列通知
懶骨頭(http://blog.csdn.com/iamlazybone)
一個狀態列通知,會在系統的狀態列添加一個表徵圖,並且在狀態視窗添加一條資訊。當使用者點擊這個資訊時,android會發送一個intent請求,通常是啟動一個已定義的activity。你可以添加聲音、震動、閃屏給裝置來提醒使用者。
通常一個後台服務運行時,如果需要提醒使用者一些事件、或者讓使用者反饋一些資訊時,通常用到狀態列提醒。一個後台Service永遠不會自己運行一個activity來接受使用者互動,一般的,後台服務會添加一個狀態列通知來與使用者進行互動。
顯示了一個狀態列通知:
接下來的會顯示狀態列視窗。使用者可以開啟這個視窗通過下滑狀態列。或者使用menu菜單鍵選擇。
基礎知識
一個activity或者Service可以初始化狀態列通知,因為activity只有在活動狀態下才能執行一些命令,所以你需要從一個service來建立狀態通知。當使用者啟動了其他程式或者裝置已經休眠時,通過這種方式,通知就可以在後台被建立。你要用到這兩個類:Notification類和NotificationManager類。
Notification類來定義狀態通知的屬性,比標,提示資訊,或者提示聲音。NotificationManager是一個android系統的服務,來管理和運行所有通知的,他不能被執行個體化,你可以用getSystemService()方法獲得他的控制代碼。當你想通知使用者時,調用notify()方法即可。
建立一個功能表列通知:
1-獲得MotificationManager的引用。
String ns = Context.NOTIFICATION_SERVICE;<br />NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
2-執行個體化Notification:
int icon = R.drawable.notification_icon;<br />CharSequence tickerText = "Hello";<br />long when = System.currentTimeMillis();<br />Notification notification = new Notification(icon, tickerText, when);
3-定義Notification,如顯示icon、目標intent等資訊
Context context = getApplicationContext();<br />CharSequence contentTitle = "My notification";<br />CharSequence contentText = "Hello World!";<br />Intent notificationIntent = new Intent(this, MyClass.class);<br />PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);<br />notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
4-傳遞給Manager.
private static final int HELLO_ID = 1;<br />mNotificationManager.notify(HELLO_ID, notification);
好了,一個通知寫完了。
管理你的通知
NotificationManager是一個管理所有通知的系統服務。你可以通過getSystemService()方法得到她的控制代碼:
String ns = Context.NOTIFICATION_SERVICE;<br />NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
當你想發送一個狀態列通知時,通過notify(int,Notification)方法傳遞Notification對象給NotificationManager,第一個參數是Notification的id,第二個參數是通知的對象。id是一個唯一的標示,當你改變通知或者進行一些的活動時必須要用到它。
當使用者從通知視窗選擇了某個通知時,會給這個通知添加一個“FLAG_AUTO_CANCEL”標記來移除這個通知。你也可以使用cancel(int)方法,通過指定通知id來取消某個通知,或者乾脆cancelAll()。
建立一個通知
一個通知對象定義了顯示在狀態列的一些細節資訊,和所有通知方式,例如聲音、閃光。
一個狀態列通知必須包括以下幾點:
@ 顯示在狀態列的表徵圖
@ 一個標題(除非你自訂了提示介面)
@ 一個Pending Intent,即點擊後要做的操作。
可選項包括以下:
@ 狀態列提示文本
@ 提示聲音
@ 震動
@ 閃光
初學者套件?為新的通知包含了MNotification(int,CharSequence,long)構造方法和setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)方法。這些參數是一個通知的必要參數。下面的程式碼片段是一個簡單的例子:
int icon = R.drawable.notification_icon; // icon from resources<br />CharSequence tickerText = "Hello"; // ticker-text<br />long when = System.currentTimeMillis(); // notification time<br />Context context = getApplicationContext(); // application Context<br />CharSequence contentTitle = "My notification"; // expanded message title<br />CharSequence contentText = "Hello World!"; // expanded message text<br />Intent notificationIntent = new Intent(this, MyClass.class);<br />PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);<br />// the next two lines initialize the Notification, using the configurations above<br />Notification notification = new Notification(icon, tickerText, when);<br />notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
更新通知
你可以在事件改變時修改狀態列的通知。例如,當有一條未讀簡訊時又來了一條簡訊,此時狀態列應該顯示新的簡訊。像這種情況下,添加一條洗得通知不如更改原有通知更加合理,因為後者能避免通知的混亂。
因為每個通知都有一個唯一的Id,你可以通過setLatestEventInfo()方法修改通知,然後調用notify()讓其顯示。
你可以修改每個屬性,除了context和下拉狀態列時顯示的標題和文本。你可以通過setLatestEventInfo()方法給contentTitle和conTentText設定文本資訊,然後調用notify()方法來更新通知。(當然了你可以建立自己的布局檔案,那樣的話更新顯示文本就沒有效果了)。
添加聲音
你可以使用預設的聲音來提醒使用者有一個新通知。方法是添加一個“DEFAULT_SOUND”參數。
notification.defaults |= Notification.DEFAULT_SOUND;
如果使用非預設的聲音,需要傳遞一個URI資源引用。例如:
notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3");
下個例子中,音頻檔案從MediaStore類中擷取:
notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
這種情況下,資源id為6的音頻檔案時已知的,並且已添加到content的URI中。如果你不知道exact ID,你必須在MediaStore中查詢所有可用的資源。參考 Content Providers文檔。
如果你想讓提示聲音一直播放知道使用者響應位置,你可以添加“FLAG_INSISTENT”參數。
注意:如果包含“DEFAULT_SOUND”參數,那麼預設聲音會覆蓋其他的聲音設定。
添加震動
你可以使用預設的震動方式提示使用者:
notification.defaults |= Notification.DEFAULT_VIBRATE;
或者使用自己的震動方式,例如:
long[] vibrate = {0,100,200,300};<br />notification.vibrate = vibrate;
這個數組定義了交替的震動和關閉,一毫秒為單位。第一個值是等待多久開始震動,第二個值是第一次震動的時間,第三個是停止震動的時間,以此類推。定義多長時間都行,但是不能設定為重複。
注意:如果設定了預設,則其他震動方式無效。
添加手機燈閃爍
讓手機閃動LED燈,你可以實現預設的閃動色繪製。或者定義自己的閃動效果。
使用預設的閃光效果,代碼如下:
notification.defaults |= Notification.DEFAULT_LIGHTS;
定義自己的效果,可以設定顏色、定義顯示的時間,一些常用的值如下:
notification.ledARGB = 0xff00ff00;<br />notification.ledOnMS = 300;<br />notification.ledOffMS = 1000;<br />notification.flags |= Notification.FLAG_SHOW_LIGHTS;
在這個例子裡,綠燈先顯示300毫秒然後關閉一秒鐘,裝置不是支援所有的顏色,而且不是所有的裝置都支援相同顏色。所以裝置會按照指定值顯示最接近的顏色。綠色是常見的顏色。
通知的更多特性
你可以添加幾個特性到你的通知中去。下面是一些有用的設定:
"FLAG_AUTO_CANCEL"標記
這個標記會在使用者選擇查看通知視窗後自動關閉通知。
"FLAG_INSISTENT"
在使用者響應之前一直重複
"FLAG_ONGOING_EVENT"
添加這個標記把通知分在“正在運行”組中,說明程式正在運行,或者後台運行,甚至當程式不可見時,例如播放音樂或者電話中時。
"FLAG_NO_CLEAR"
這個標記讓你的通知不會被Clear按鈕所取消。對一直進行中的通知非常有用。
number field
標記表示當前通知所代表的事件數目。這個數字顯示在icon之上。如果你打算這樣使用,當通知第一次建立時必須從1開始計數。如果你改變了他的值從0或其他值開始,那麼他將不會顯示。
iconLevel field
這個值指當前icon的LevelListDrawable等級。通過改變這個值,你可以讓狀態列的icon顯示動畫。
更多詳細的特性和使用方法餐卡Notification類。
建立一個自訂的通知視圖
預設情況下,下拉的Notification視窗包含一個標題和文本資訊。setLatestEventInfo()有兩個預設的參數contentTitle和contentText 。然而你通過RemoteViews也可以定義自己下拉通知視圖。上賣弄的就顯示了一個自訂布局的通知視圖,包括一個TextView和ImageView。
定義自己的通知視圖,執行個體化RemoteViews對象並且傳遞給contentView。給contentIntent欄位傳遞PendingIntent值。建立一個自訂的通知視圖最好的理解方法就是寫一個例子:
1-建立xml布局檔案。例如:custom_notification_layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br /> android:orientation="horizontal"<br /> android:layout_width="fill_parent"<br /> android:layout_height="fill_parent"<br /> android:padding="3dp"<br /> ><br /> <ImageView android:id="@+id/image"<br /> android:layout_width="wrap_content"<br /> android:layout_height="fill_parent"<br /> android:layout_marginRight="10dp"<br /> /><br /> <TextView android:id="@+id/text"<br /> android:layout_width="wrap_content"<br /> android:layout_height="fill_parent"<br /> android:textColor="#000"<br /> /><br /></LinearLayout>
這是一個自訂的擴充通知的視圖,但是ImageView和TextView仍然需要程式定義。RemoteViews提供一些方便的方法來讓你定義content。
2-下面的代碼,使用RemoveViews 的方法定義image和text。然後傳遞RemoteViews 對象給通知的contentView欄位。如下:
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);<br />contentView.setImageViewResource(R.id.image, R.drawable.notification_image);<br />contentView.setTextViewText(R.id.text, "Hello, this message is in a custom expanded view");<br />notification.contentView = contentView;
就像顯示的那樣,傳遞程式的包名,布局的資源id給RemoteViews的構造方法。然後,定義ImageView和TextView的content,使用setImageViewResource()和setTextViewText().這種情況下,傳遞你要設定的view對象的引用id。最後把RemoteViews 對象傳遞給contentView。
3-因為你不需要setLatestEventInfo()了,你必須為通知定義一個intent,例如:
Intent notificationIntent = new Intent(this, MyClass.class);<br />PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);<br />notification.contentIntent = contentIntent;
4-通知可以這樣調用:
mNotificationManager.notify(CUSTOM_VIEW_ID, notification);
RemoteViews 類也包含一些方法讓你輕鬆地添加Chronometer或者ProgressBar在你的通知view裡。
注意:當建立一個自訂的通知view,你必須特別小心自訂的布局來適用不同裝置的解析度。尤其這種情況下,更要特別的小心,過於複雜的布局一定要多多測試。