通知的常見應用模式
A1.普通通知的發送流程
// 獲取通知服務對象NotificationManager NotificationManager notiManager = (NotificationManager) getSystemService(mContext.NOTIFICATION_SERVICE); // 創建Notification對象 NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext); builder.setTicker("Ticker"); // 通知彈出時狀態欄的提示文本 builder.setContentInfo("Info..."); // builder.setContentTitle("Title") // 通知標題 .setContentText("Content") // 通知內容 .setSmallIcon(R.drawable.logo_dzone_strawberry); // 通知小圖標 builder.setDefaults(Notification.DEFAULT_SOUND); // 設置聲音/震動等 Notification notification = builder.build(); // 設置通知的點擊行為:自動取消/跳轉等 builder.setAutoCancel(true); // 通過NotificationManager發送通知 notiManager.notify(1003, notification);
A2.攜帶意圖的通知
… // 與普通通知相同 // 獲取通知服務對象NotificationManager Intent intent = new Intent(this, ModxExam2Activity.class); intent.putExtra("msg", "我發送了一個通知"); // 攜帶內容 //getIntent().getStringExtra("msg"); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, //請求碼 intent, //意圖對象 PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(pendingIntent); … // 與普通通知相同
A3.大視圖通知
BigPictureStyle創建大視圖樣式,可以通過Builder.addAction()添加確認按鈕。
… // 與普通通知相同 // 獲取通知服務對象NotificationManager NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(builder); bigPictureStyle.setSummaryText("SummaryText"); // 大圖模式顯示內容,取代小圖 bigPictureStyle.setBigContentTitle("BigContentTitle"); // 大圖模式標題,取代小圖 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo_dzone_strawberry); bigPictureStyle.bigLargeIcon(bitmap); bigPictureStyle.bigPicture(bitmap); // 大圖bitmap notiManager.notify(1005, bigPictureStyle.build()); … // 與普通通知相同
A4.進度條通知
… // 與普通通知相同 // 獲取通知服務對象NotificationManager builder.setProgress(100, progress, false); … // 與普通通知相同
A5.自定義通知
notiManager = (NotificationManager) getSystemService(mContext.NOTIFICATION_SERVICE); NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext); // 使用RemoteViews創建view RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notify_layout_type1); remoteViews.setTextViewText(R.id.textView1, "setTextViewText"); remoteViews.setTextColor(R.id.textView1, Color.BLUE); remoteViews.setImageViewResource(R.id.imageView1, R.drawable.logo_dzone_strawberry); builder.setContent(remoteViews); builder.setSmallIcon(R.drawable.logo_dzone_strawberry); notiManager.notify(1008, builder.build());
通知總結
S1.通知的更新@link
要想更新通知,需要利用 NotificationManager.notify() 的 id 參數,該 id 在應用內需要唯一。要想更新特定 id 的通知,只需要創建新的 Notification,並發出與之前所用 id 相同的 Notification。如果之前的通知仍然可見,則系統會根據新的 Notification 對象的內容更新該通知。相反,如果之前的通知已被清除,系統則會創建一個新通知。
S2.刪除通知@link
刪除通知可以有多種方式:
1. 通過 NotificationCompat.Builder 設置 setAutoCancel(true),這樣當用戶點擊通知后,通知自動刪除;
2. 通過 NotificationManager.cancel(id) 方法,刪除指定 id 的通知;
3. 通過 NotificationManager.cancelAll() 方法,刪除該應用的所有通知;
S3.意圖跳轉@link
PendingIntent可以看做是對Intent的包裝,通過名稱可以看出PendingIntent用於處理即將發生的意圖,而Intent用來用來處理馬上發生的意圖。而對於通知來說,它是一系統級的全局通知,並不確定這個意圖被執行的時間。當在應用外部執行PendingIntent時,因為它保存了觸發應用的Context,使得外部應用可以如在當前應用中一樣,執行PendingIntent里的Intent,就算執行的時候響應通知的應用已經被銷毀了,也可以通過存在PendingIntent里的Context照常執行它,並且還可以處理Intent說帶來的額外信息。
PendingIntent提供了多個靜態的getXxx()方法,用於獲得適用於不同場景的PendingIntent對象。一般需要傳遞的幾個參數都很常規,只介紹一個flag參數,用於標識PendingIntent的構造選擇:
FLAG_CANCEL_CURRENT:如果構建的PendingIntent已經存在,則取消前一個,重新構建一個。
FLAG_NO_CREATE:如果前一個PendingIntent已經不存在了,將不再構建它。
FLAG_ONE_SHOT:表明這里構建的PendingIntent只能使用一次。
FLAG_UPDATE_CURRENT:如果構建的PendingIntent已經存在,則替換它,常用。
擴展內容
E1.浮動通知
E2.鎖屏上展示
E3.閃光燈設置/自定義聲音
E4.設置時間
實用方案
P1.自定義通知
參考:
參考:
官方API
Notifications google
Android 通知欄Notification的整合 全面學習 詳細(E4)(CSDN)
Android 開發之 Notification 詳解 全面(E1/E2)
Android--通知之Notification 全面(承香墨影)
全面了解Android Notification 全()簡書
大視圖
Android官方開發文檔Training系列課程中文版:通知用戶之大視圖通知
demo代碼

public void onClick(View view) { switch (view.getId()) { case R.id.button1: notifyNormalType1(); break; case R.id.button2: notifyWithIntentType2(); break; case R.id.button3: notifyBigPicType3(); break; case R.id.button4: newThreadProgress(); break; case R.id.button5: notifyCustomType5(); break; } }

NotificationManager notiManager; /** * 發送普通通知 * SS1.創建Builder對象(NotificationCompat.Builder) * SS2.添加通知設置內容 * SS3.創建通知對象通過Builder.build()構造返回 * SS4.獲取通知管理器 * SS5.發出通知(通知ID,通知對象) */ private void notifyNormalType1() { // 獲取通知服務對象NotificationManager notiManager = (NotificationManager) getSystemService(mContext.NOTIFICATION_SERVICE); // 創建Notification對象 NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext); builder.setTicker("Ticker"); // 通知彈出時狀態欄的提示文本 builder.setContentInfo("Info..."); // builder.setContentTitle("Title") // 通知標題 .setContentText("Content") // 通知內容 .setSmallIcon(R.drawable.logo_dzone_strawberry); // 通知小圖標 builder.setDefaults(Notification.DEFAULT_SOUND); // 設置聲音/震動等 // builder.setDefaults(Notification.DEFAULT_ALL); // 設置聲音+震動 Notification notification = builder.build(); // 設置通知的點擊行為:自動取消/跳轉等 builder.setAutoCancel(true); // 單獨設置未跳轉? // 通過NotificationManager發送通知 notiManager.notify(1003, notification); } /** * 發送攜帶意圖的通知 * SS1.創建Builder對象(NotificationCompat.Builder) * SS2.添加通知設置內容 * SS+.在Builder中加入一個意圖過濾器builder.setContentIntent(PendingIntent) * 給PendingIntent的Intent參數添加跳轉的目標Activity * SS3.創建通知對象通過Builder.build()構造返回 * SS4.獲取通知管理器 * SS5.發出通知(請求碼,通知對象) */ private void notifyWithIntentType2() { notiManager = (NotificationManager) getSystemService(ModxExam1Activity.NOTIFICATION_SERVICE); NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext); builder.setTicker("彈出時提示..."); builder.setContentInfo("內容:帶意圖的通知"); builder.setContentTitle("通知標題") .setContentText("通知下面的文本") .setSmallIcon(R.drawable.logo_dzone_strawberry); builder.setDefaults(Notification.DEFAULT_SOUND); Intent intent = new Intent(this, ModxExam2Activity.class); intent.putExtra("msg", "我發送了一個通知"); //getIntent().getStringExtra("msg"); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, //請求碼 intent, //意圖對象 PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(pendingIntent); builder.setAutoCancel(true); //點擊自動取消通知 Notification notification = builder.build(); notiManager.notify(1003, notification); } /** * 發送大視圖通知 * SS1.創建Builder對象(NotificationCompat.Builder) * SS2.添加通知設置內容 * SS+.創建BigPictureStyle傳入builder,並設置BigPictureStyle屬性 * SS3.創建通知對象通過BigPictureStyle.build()構造返回 * SS4.獲取通知管理器 * SS5.發出通知(請求碼,通知對象) * mark * 大視圖通知的特點: * 1.必須設置setSmallIcon,設置小圖標,已收到通知小圖標會在狀態欄顯示, * 用戶下拉獲得通知的時候,小圖會顯示在大圖標的右下角 * 2.大圖通知的標題內容設置會覆蓋原來的小圖通知的設置 * 3.bigPicture方法設置的圖片會在一個比較大的視圖中顯示 * 兼容性問題?honor6plus 6.0 */ private void notifyBigPicType3() { notiManager = (NotificationManager) getSystemService(ModxExam1Activity.NOTIFICATION_SERVICE); Intent intent = new Intent(this, ModxExam2Activity.class); intent.putExtra("msg", "我發送了一個通知"); //getIntent().getStringExtra("msg"); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, //請求碼 intent, //意圖對象 PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext); builder.setTicker("Ticker"); builder.setContentInfo("Info"); builder.setContentTitle("Title") .setContentText("Content") .setSmallIcon(R.drawable.logo_dzone_strawberry); builder.setDefaults(Notification.DEFAULT_SOUND); /** * 在大視圖通知中設置一個按鈕 * 點擊無法取消? * http://blog.csdn.net/sahadev_/article/details/51714799 */ builder.setStyle(new NotificationCompat.BigTextStyle() .bigText("msg...")) .addAction (R.drawable.logo_dzone_strawberry, "123", pendingIntent) .addAction (R.drawable.logo_dzone_strawberry, "456", pendingIntent); builder.setContentIntent(pendingIntent); builder.setAutoCancel(true); NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(builder); bigPictureStyle.setSummaryText("SummaryText"); // 大圖模式顯示內容,取代小圖 bigPictureStyle.setBigContentTitle("BigContentTitle"); // 大圖模式標題,取代小圖 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo_dzone_strawberry); bigPictureStyle.bigLargeIcon(bitmap); bigPictureStyle.bigPicture(bitmap); // 大圖bitmap notiManager.notify(1005, bigPictureStyle.build()); } /** * 進度通知處理 * SS1. */ private int i; private final int CODE_START = 1001; // 開始 private final int CODE_RUN = 1002; // 下載中 private final int CODE_END = 1003; // 下載完成 private final int NOF_MSG_CODE = 10086; // notification code Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case CODE_START: notifyProgressType4(0, CODE_START); break; case CODE_RUN: notifyProgressType4(msg.arg1, CODE_RUN); break; case CODE_END: notifyProgressType4(0, CODE_END); break; } } }; NotificationCompat.Builder builder; /** * 發送進度通知 * @param progress 進度 * @param code 識別碼 */ private void notifyProgressType4(int progress, int code) { notiManager = (NotificationManager) getSystemService(mContext.NOTIFICATION_SERVICE); if (builder == null) { builder = new NotificationCompat.Builder(mContext); builder.setTicker("Ticker"); builder.setContentInfo("info"); builder.setContentTitle("變形金剛2.avi") .setContentText("default content...") .setSmallIcon(R.drawable.logo_dzone_strawberry); //必須設置 } if (code == CODE_RUN) { // 參數三設置為true/false 是否允許使用不確定模式,在不確定模式下,進度條動畫無限循環 builder.setProgress(100, progress, false); builder.setContentText("loading..."); } else if (code == CODE_START) { builder.setContentText("ready to download"); } else if (code == CODE_END) { builder.setProgress(0, 0, false); builder.setContentText("download finished,would you open it?"); Intent intent = new Intent(this, ModxExam2Activity.class); intent.putExtra("msg", "我發送了一個通知"); //getIntent().getStringExtra("msg"); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, // 請求碼 intent, //意圖對象 PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(pendingIntent); builder.setDefaults(Notification.DEFAULT_SOUND); builder.setAutoCancel(true); } Notification notification = builder.build(); notiManager.notify(NOF_MSG_CODE, notification); } Message message; NotificationManager notifyManager; /** * 模擬下載線程 */ private void newThreadProgress() { new Thread(new Runnable() { @Override public void run() { try { notifyManager = (NotificationManager) getSystemService(mContext.NOTIFICATION_SERVICE); message = new Message(); // 每次都要NEW一個message??? message.what = CODE_START; // 開始 handler.sendMessage(message); for (i = 0; i <= 100; i++) { Thread.sleep(200); // SystemClock.sleep(200); LogUtil.infoE("" + i); notifyManager.cancel(NOF_MSG_CODE); message = new Message(); message.what = CODE_RUN; // 正在運行 message.arg1 = i; handler.sendMessage(message); } notifyManager.cancel(CODE_RUN); message = new Message(); message.what = CODE_END; // 結束了 handler.sendMessage(message); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } /** * 自定義通知 * 必須設置setSmallIcon */ private void notifyCustomType5() { notiManager = (NotificationManager) getSystemService(mContext.NOTIFICATION_SERVICE); NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext); // 使用RemoteViews創建view RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notify_layout_type1); remoteViews.setTextViewText(R.id.textView1, "setTextViewText"); remoteViews.setTextColor(R.id.textView1, Color.BLUE); remoteViews.setImageViewResource(R.id.imageView1, R.drawable.logo_dzone_strawberry); builder.setContent(remoteViews); builder.setSmallIcon(R.drawable.logo_dzone_strawberry); notiManager.notify(1008, builder.build()); ToastUtil.showS(this, "Type5"); }