標籤:
最近時不時地有人問我這樣或那樣的通知如何?,所以本文將根據個人經驗對Notification做個總結,以供參考!
什麼是通知(Notification)
通知是一個可以在應用程式正常的使用者介面之外顯示給使用者的訊息。
通知發出時,它首先出現在狀態列的通知區域中,使用者開啟通知抽屜可查看通知詳情。通知區域和通知抽屜都是使用者可以隨時查看的系統控制區域。
作為安卓使用者介面的重要組成部分,通知有自己的設計指南。在Android 5.0(API level 21)中引入的 Material Design 的變化是特別重要的,更多資訊請閱讀 通知設計指南。
如何建立通知
隨著Android系統不斷升級,Notification的建立方式也隨之變化,主要變化如下:
Android 3.0之前
Android 3.0 (API level 11)之前,使用new Notification()方式建立通知:
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, ResultActivity.class), 0); Notification notification = new Notification(icon, tickerText, when); notification.setLatestEventInfo(this, title, content, contentIntent); mNotifyMgr.notify(NOTIFICATIONS_ID, notification);
Android 3.0 (API level 11)及更高版本
Android 3.0開始棄用new Notification()方式,改用Notification.Builder()來建立通知:
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, ResultActivity.class), 0); Notification notification = new Notification.Builder(this) .setSmallIcon(R.drawable.notification_icon) .setContentTitle("My notification") .setContentText("Hello World!") .setContentIntent(contentIntent) .build(); // getNotification() deprecated in API level 16 mNotifyMgr.notify(NOTIFICATIONS_ID, notification);
這裡需要注意: “build()” 是Androdi 4.1(API level 16)加入的,用以替代”getNotification()”。API level 16開始棄用”getNotification()”
相容Android 3.0之前的版本
為了相容API level 11之前的版本,v4 Support Library中提供了NotificationCompat.Builder()這個替代方法。它與Notification.Builder()類似,二者沒有太大區別。
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, ResultActivity.class), 0);NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.notification_icon) .setContentTitle("My notification") .setContentText("Hello World!") .setContentIntent(contentIntent);mNotifyMgr.notify(NOTIFICATIONS_ID, mBuilder.build());
註:除特別說明外,本文將根據 NotificationCompat.Builder() 展開解析,Notification.Builder()類似。
通知基本用法
通知的必要屬性
一個通知必須包含以下三項屬性:
- 小表徵圖,對應 setSmallIcon()
- 通知標題,對應 setContentTitle()
- 詳細資料,對應 setContentText()
其他屬性均為可選項,更多屬性方法請參考NotificationCompat.Builder。
儘管其他都是可選的,但一般都會為通知添加至少一個動作(Action),這個動作可以是跳轉到Activity、啟動一個Service或發送一個Broadcas等。 通過以下方式為通知添加動作:
- 使用PendingIntent
- 通過大視圖通知的 Action Button //僅支援Android 4.1 (API level 16)及更高版本,稍後會介紹
建立通知
1、執行個體化一個NotificationCompat.Builder對象
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.notification_icon) .setContentTitle("My notification") .setContentText("Hello World!");
NotificationCompat.Builder自動化佈建的預設值:
- priority: PRIORITY_DEFAULT
- when: System.currentTimeMillis()
- audio stream: STREAM_DEFAULT
2、定義並設定一個通知動作(Action)
Intent resultIntent = new Intent(this, ResultActivity.class); PendingIntent resultPendingIntent = PendingIntent.getActivity( this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT); mBuilder.setContentIntent(resultPendingIntent);
3、產生Notification對象
Notificatioin notification = mBuilder.build();
4、使用NotificationManager發送通知
// Sets an ID for the notificationint mNotificationId = 001;// Gets an instance of the NotificationManager serviceNotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);// Builds the notification and issues it.mNotifyMgr.notify(mNotificationId, notification);
更新通知
更新通知很簡單,只需再次發送相同ID的通知即可,如果之前的通知依然存在則會更新通知屬性,如果之前通知不存在則重新建立。
範例程式碼:
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // Sets an ID for the notification, so it can be updated int notifyID = 1; NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(this) .setContentTitle("New Message") .setContentText("You‘ve received new messages.") .setSmallIcon(R.drawable.ic_notify_status); int numMessages = 0; // Start of a loop that processes data and then notifies the user ... mNotifyBuilder.setContentText("new content text") .setNumber(++numMessages); // Because the ID remains unchanged, the existing notification is updated. mNotifyMgr.notify(notifyID, mNotifyBuilder.build()); ...
取消通知
取消通知有如下4種方式:
- 點擊通知欄的清除按鈕,會清除所有可清除的通知
- 設定了 setAutoCancel() 或 FLAG_AUTO_CANCEL的通知,點擊該通知時會清除它
- 通過 NotificationManager 調用 cancel() 方法清除指定ID的通知
- 通過 NotificationManager 調用 cancelAll() 方法清除所有該應用之前發送的通知
通知類型
大視圖通知
通知有兩種視圖:普通視圖和大視圖。
普通視圖:
大視圖:
預設情況下為普通視圖,可通過NotificationCompat.Builder.setStyle()設定大視圖。
注: 大視圖(Big Views)由Android 4.1(API level 16)開始引入,且僅支援Android 4.1及更高版本。
構建大視圖通知
以為例:
1、構建Action Button的PendingIntent
Intent dismissIntent = new Intent(this, PingService.class); dismissIntent.setAction(CommonConstants.ACTION_DISMISS); PendingIntent piDismiss = PendingIntent.getService(this, 0, dismissIntent, 0); Intent snoozeIntent = new Intent(this, PingService.class); snoozeIntent.setAction(CommonConstants.ACTION_SNOOZE); PendingIntent piSnooze = PendingIntent.getService(this, 0, snoozeIntent, 0);
2、構建NotificatonCompat.Builder對象
NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_stat_notification) .setContentTitle(getString(R.string.notification)) .setContentText(getString(R.string.ping)) .setDefaults(Notification.DEFAULT_ALL) // requires VIBRATE permission // 該方法在Android 4.1之前會被忽略 .setStyle(new NotificationCompat.BigTextStyle() .bigText(msg)) //添加Action Button .addAction (R.drawable.ic_stat_dismiss, getString(R.string.dismiss), piDismiss) .addAction (R.drawable.ic_stat_snooze, getString(R.string.snooze), piSnooze);
3、其他步驟與普通視圖相同
進度條通知
明確進度的進度條
使用setProgress(max, progress, false)來更新進度。
max: 最大進度值
progress: 當前進度
false: 是否是不明確的進度條
類比下載過程,樣本如下:
int id = 1; ... 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; for (incr = 0; incr <= 100; incr+=5) { mBuilder.setProgress(100, incr, false); mNotifyManager.notify(id, mBuilder.build()); try { // Sleep for 5 seconds Thread.sleep(5*1000); } catch (InterruptedException e) { Log.d(TAG, "sleep failure"); } } mBuilder.setContentText("Download complete")//下載完成 .setProgress(0,0,false); //移除進度條 mNotifyManager.notify(id, mBuilder.build()); } } ).start();
,分別為下載過程中進度條通知 和 下載完成移除進度條後的通知。
不確定進度的進度條
使用setProgress(0, 0, true)來表示進度不明確的進度條
mBuilder.setProgress(0, 0, true); mNotifyManager.notify(id, mBuilder.build());
浮動通知(Heads-up Notifications)
Android 5.0(API level 21)開始,當螢幕未上鎖且亮屏時,通知可以以小視窗形式顯示。使用者可以在不離開當前應用前提下操作該通知。
:
NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(this) .setContentTitle("New Message") .setContentText("You‘ve received new messages.") .setSmallIcon(R.drawable.ic_notify_status) .setFullScreenIntent(pendingIntent, false);
以下兩種情況會顯示浮動通知:
- setFullScreenIntent(),如上述樣本。
- 通知擁有高優先順序且使用了鈴聲和震動
鎖屏通知
Android 5.0(API level 21)開始,通知可以顯示在鎖屏上。使用者可以通過設定選擇是否允許敏感的通知內容顯示在安全的鎖屏上。
你的應用可以通過setVisibility()控制通知的顯示等級:
- VISIBILITY_PRIVATE : 顯示基本資料,如通知的表徵圖,但隱藏通知的全部內容
- VISIBILITY_PUBLIC : 顯示通知的全部內容
- VISIBILITY_SECRET : 不顯示任何內容,包括表徵圖
自訂通知
Android系統允許使用RemoteViews來自訂通知。
自訂普通視圖通知高度限制為64dp,大視圖通知高度限制為256dp。同時,建議自訂通知盡量簡單,以提高相容性。
自訂通知需要做如下操作:
1、建立自訂通知布局
2、使用RemoteViews定義通知群組件,標、文字等
3、調用setContent()將RemoteViews對象綁定到NotificationCompat.Builder
4、同正常發送通知流程
注意: 避免為通知設定背景,因為相容性原因,有些文字可能看不清。
定義通知文本樣式
通知的背景顏色在不同的裝置和版本中有所不同,Android2.3開始,系統定義了一套標準通知文本樣式,建議自訂通知使用標準樣式,這樣有助於通知文本可見。
通知文本樣式:
Android 5.0之前可用:android:style/TextAppearance.StatusBar.EventContent.Title // 通知標題樣式 android:style/TextAppearance.StatusBar.EventContent // 通知內容樣式 Android 5.0及更高版本: android:style/TextAppearance.Material.Notification.Title // 通知標題樣式 android:style/TextAppearance.Material.Notification // 通知內容樣式
更多通知的標準樣式和布局,可參考源碼frameworks/base/core/res/res/layout路徑下的通知模版如:
Android 5.0之前: notification_template_base.xml notification_template_big_base.xml notification_template_big_picture.xml notification_template_big_text.xml Android 5.0 及更高版本: notification_template_material_base.xml notification_template_material_big_base.xml notification_template_material_big_picture.xml notification_template_part_chronometer.xml notification_template_progressbar.xml 等等。
保留Activity返回棧
常規Activity
預設情況下,從通知啟動一個Activity,按返回鍵會回到主畫面。但某些時候有按返回鍵仍然留在當前應用的需求,這就要用到TaskStackBuilder了。
1、在manifest中定義Activity的關係
Android 4.0.3 及更早版本<activity android:name=".ResultActivity"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity"/></activity>Android 4.1 及更高版本<activity android:name=".ResultActivity" android:parentActivityName=".MainActivity"></activity>
2、建立返回棧PendingIntent
Intent resultIntent = new Intent(this, ResultActivity.class);TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);// 添加返回棧stackBuilder.addParentStack(ResultActivity.class);// 添加Intent到棧頂stackBuilder.addNextIntent(resultIntent);// 建立包含返回棧的pendingIntentPendingIntent 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());
上述操作後,從通知啟動ResultActivity,按返回鍵會回到MainActivity,而不是主畫面。
特殊Activity
預設情況下,從通知啟動的Activity會在近期工作清單裡出現。如果不需要在近期任務裡顯示,則需要做以下操作:
1、在manifest中定義Activity
<activity android:name=".ResultActivity" android:launchMode="singleTask" android:taskAffinity="" android:excludeFromRecents="true"></activity>
2、構建PendingIntent
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);Intent notifyIntent = new Intent(this, ResultActivity.class);// Sets the Activity to start in a new, empty tasknotifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);PendingIntent notifyPendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);builder.setContentIntent(notifyPendingIntent);NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);mNotificationManager.notify(id, builder.build());
上述操作後,從通知啟動ResultActivity,此Activity不會出現在近期工作清單中。
通知常見屬性和常量
通知的提醒方式
1、聲音提醒
2、震動提醒
預設震動
notification.defaults |= Notification.DEFAULT_VIBRATE;
自訂震動
long[] vibrate = {100, 200, 300, 400}; //震動效果
// 表示在100、200、300、400這些時間點交替啟動和關閉震動 notification.vibrate = vibrate;
3、閃爍提醒
預設閃爍
notification.defaults |= Notification.DEFAULT_LIGHTS;
自訂閃爍
notification.ledARGB = 0xff00ff00; // LED燈的顏色,綠燈
notification.ledOnMS = 300; // LED燈顯示的毫秒數,300毫秒
notification.ledOffMS = 1000; // LED燈關閉的毫秒數,1000毫秒
notification.flags |= Notification.FLAG_SHOW_LIGHTS; // 必須加上這個標誌
常見的Flags
FLAG_AUTO_CANCEL
當通知被使用者點擊之後會自動被清除(cancel)
FLAG_INSISTENT
在使用者響應之前會一直重複提醒音
FLAG_ONGOING_EVENT
表示正在啟動並執行事件
FLAG_NO_CLEAR
通知欄點擊“清除”按鈕時,該通知將不會被清除
FLAG_FOREGROUND_SERVICE
表示當前服務是前台服務
更多Notification屬性詳見Notification。
That’s all! 更多通知知識點等待你來發掘,歡迎補充!
參考資料
Notifications
原創文章,歡迎轉載,轉載請註明出處
我的簡書帳號是ConnorLin,歡迎光臨!
歡迎關注我的
你真的瞭解Android Notification嗎?