Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android應用開發入門(三十五)通知之Notification

Android應用開發入門(三十五)通知之Notification

編輯:Android開發實例

前言

  之前一篇文章講了Android下使用Toast的方式提示消息。這篇文章講解一下在Android中使用Notification提示消息給用戶,Notification是一種具有全局效果的通知,程序一般通過NotificationManager服務來發送Notification。在本文中,將介紹Notification的常規使用,以及自定義方式的使用,對於每種不同的方式,都提供示例展示效果。

 

Notification

  Notification,俗稱通知,是一種具有全局效果的通知,它展示在屏幕的頂端,首先會表現為一個圖標的形式,當用戶向下滑動的時候,展示出通知具體的內容。

  注意:因為一些Android版本的兼容性問題,對於Notification而言,Android3.0是一個分水嶺,在其之前構建Notification推薦使用Notification.Builder構建,而在Android3.0之後,一般推薦使用NotificationCompat.Builder構建。本文的所有代碼環境均在4.3中完成,如果使用4.1一下的設備測試,請注意兼容性問題。

  通知一般通過NotificationManager服務來發送一個Notification對象來完成,NotificationManager是一個重要的系統級服務,該對象位於應用程序的框架層中,應用程序可以通過它像系統發送全局的通知。這個時候需要創建一個Notification對象,用於承載通知的內容。但是一般在實際使用過程中,一般不會直接構建Notification對象,而是使用它的一個內部類NotificationCompat.Builder來實例化一個對象(Android3.0之下使用Notification.Builder),並設置通知的各種屬性,最後通過NotificationCompat.Builder.build()方法得到一個Notification對象。當獲得這個對象之後,可以使用NotificationManager.notify()方法發送通知。

  NotificationManager類是一個通知管理器類,這個對象是由系統維護的服務,是以單例模式獲得,所以一般並不直接實例化這個對象。在Activity中,可以使用Activity.getSystemService(String)方法獲取NotificationManager對象,Activity.getSystemService(String)方法可以通過Android系統級服務的句柄,返回對應的對象。在這裡需要返回NotificationManager,所以直接傳遞Context.NOTIFICATION_SERVICE即可。

  雖然通知中提供了各種屬性的設置,但是一個通知對象,有幾個屬性是必須要設置的,其他的屬性均是可選的,必須設置的屬性如下:

  • 小圖標,使用setSamllIcon()方法設置。
  • 標題,使用setContentTitle()方法設置。
  • 文本內容,使用setContentText()方法設置。 

  

更新與移除通知

  在使用NotificationManager.notify()發送通知的時候,需要傳遞一個標識符,用於唯一標識這個通知。對於有些場景,並不是無限的添加新的通知,有時候需要更新原有通知的信息,這個時候可以重寫構建Notification,而使用與之前通知相同標識符來發送通知,這個時候舊的通知就被被新的通知所取代,起到更新通知的效果。

  對於一個通知,當展示在狀態欄之後,但是使用過後,如何取消呢?Android為我們提供兩種方式移除通知,一種是Notification自己維護,使用setAutoCancel()方法設置是否維護,傳遞一個boolean類型的數據。另外一種方式使用NotificationManager通知管理器對象來維護,它通過notify()發送通知的時候,指定的通知標識Id來操作通知,可以使用cancel(int)來移除一個指定的通知,也可以使用cancelAll()移除所有的通知。

  使用NotificationManager移除指定通知示例:

  1. NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);  
  2. mNotificationManager.cancel(0);  

PendingIntent

  對於一個通知而言,它顯示的消息是有限的,一般僅用於提示一些概要信息。但是一般簡短的消息,並不能表達需要告訴用戶的全部內容,所以需要綁定一個意圖,當用戶點擊通知的時候,調用一個意圖展示出一個Activity用來顯示詳細的內容。而Notification中,並不使用常規的Intent去傳遞一個意圖,而是使用PendingIntent。

  先來聊聊Intent和PendingIntent的區別,PendingIntent可以看做是對Intent的包裝,通過名稱可以看出PendingIntent用於處理即將發生的意圖,而Intent用來處理馬上發生的意圖。而對於通知來說,它是一個系統級的全局的通知,並不確定這個意圖被執行的時間。當在應用外部執行PendingIntent時,因為它保存了觸發App的Context,使得外部App可以如果當前App一樣執行PendingIntent裡的Intent,就算執行時觸發通知的App已經不存在了,也能通過存在PendingIntent裡的Context照常執行Intent,並且還可以處理Intent所帶來的額外的信息。

  PendingIntent提供了多個靜態的getXxx()方法,用於獲得適用於不同場景的PendingIntent對象。一般需要傳遞的幾個參數都很常規,只介紹一個flag參數,用於標識PendingIntent的構造選擇:

  • FLAG_CANCEL_CURRENT:如果構建的PendingIntent已經存在,則取消前一個,重新構建一個。
  • FLAG_NO_CREATE:如果前一個PendingIntent已經不存在了,將不再構建它。
  • FLAG_ONE_SHOT:表明這裡構建的PendingIntent只能使用一次。
  • FLAG_UPDATE_CURRENT:如果構建的PendingIntent已經存在,則替換它,常用。

 

Notification視覺風格

  Notification有兩種視覺風格,一種是標准視圖(Normal view)、一種是大視圖(Big view)。標准視圖在Android中各版本是通用的,但是對於大視圖而言,僅支持Android4.1+的版本。

  從官方文檔了解到,一個標准視圖顯示的大小要保持在64dp高,寬度為屏幕標准。標准視圖的通知主體內容有一下幾個:

  1. 通知標題。
  2. 大圖標。
  3. 通知內容。
  4. 通知消息。
  5. 小圖標。
  6. 通知的時間,一般為系統時間,也可以使用setWhen()設置。

  下面通過一個示例,模仿上面效果的通知。

  1. btnNotification.setOnClickListener(new View.OnClickListener() {  
  2.  
  3.             @Override 
  4.             public void onClick(View v) {  
  5.                 Bitmap btm = BitmapFactory.decodeResource(getResources(),  
  6.                         R.drawable.msg);  
  7.                 NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(  
  8.                         MainActivity.this).setSmallIcon(R.drawable.msg)  
  9.                         .setContentTitle("5 new message")  
  10.                         .setContentText("[email protected]");  
  11.                 mBuilder.setTicker("New message");//第一次提示消息的時候顯示在通知欄上  
  12.                 mBuilder.setNumber(12);  
  13.                 mBuilder.setLargeIcon(btm);  
  14.                 mBuilder.setAutoCancel(true);//自己維護通知的消失  
  15.                   
  16.                 //構建一個Intent  
  17.                 Intent resultIntent = new Intent(MainActivity.this,  
  18.                         ResultActivity.class);  
  19.                 //封裝一個Intent  
  20.                 PendingIntent resultPendingIntent = PendingIntent.getActivity(  
  21.                         MainActivity.this, 0, resultIntent,  
  22.                         PendingIntent.FLAG_UPDATE_CURRENT);  
  23.                 // 設置通知主題的意圖  
  24.                 mBuilder.setContentIntent(resultPendingIntent);  
  25.                 //獲取通知管理器對象  
  26.                 NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);  
  27.                 mNotificationManager.notify(0, mBuilder.build());  
  28.             }  
  29.         }); 

 顯示效果:

 

 

  而對於大視圖(Big View)而言,它的細節區域只能顯示256dp高度的內容,並且只對Android4.1+之後的設備才支持,它比標准視圖不一樣的地方,均需要使用setStyle()方法設定,它大致的效果如下:


  setStyle()傳遞一個NotificationCompat.Style對象,它是一個抽象類,Android為我們提供了三個實現類,用於顯示不同的場景。分別是:

  • NotificationCompat.BigPictureStyle, 在細節部分顯示一個256dp高度的位圖。
  • NotificationCompat.BigTextStyle,在細節部分顯示一個大的文本塊。
  • NotificationCompat.InboxStyle,在細節部分顯示一段行文本。

  如果僅僅顯示一個圖片,使用BigPictureStyle是最方便的;如果需要顯示一個富文本信息,則可以使用BigTextStyle;如果僅僅用於顯示一個文本的信息,那麼使用InboxStyle即可。後面會以一個示例來展示InboxStyle的使用,模仿上面圖片的顯示。

   實現代碼:

  1. btnBigViewNotification.setOnClickListener(new View.OnClickListener() {  
  2.  
  3.             @Override 
  4.             public void onClick(View v) {  
  5.  
  6.                 Bitmap btm = BitmapFactory.decodeResource(getResources(),  
  7.                         R.drawable.msg);  
  8.                 Intent intent = new Intent(MainActivity.this,  
  9.                         ResultActivity.class);  
  10.  
  11.                 PendingIntent pendingIntent = PendingIntent.getActivity(  
  12.                         MainActivity.this, 0, intent,  
  13.                         PendingIntent.FLAG_CANCEL_CURRENT);  
  14.  
  15.                 Notification noti = new NotificationCompat.Builder(  
  16.                         MainActivity.this)  
  17.                         .setSmallIcon(R.drawable.msg)  
  18.                         .setLargeIcon(btm)  
  19.                         .setNumber(13)  
  20.                         .setContentIntent(pendingIntent)  
  21.                         .setStyle(  
  22.                                 new NotificationCompat.InboxStyle()  
  23.                                         .addLine(  
  24.                                                 "M.Twain (Google+) Haiku is more than a cert...")  
  25.                                         .addLine("M.Twain Reminder")  
  26.                                         .addLine("M.Twain Lunch?")  
  27.                                         .addLine("M.Twain Revised Specs")  
  28.                                         .addLine("M.Twain ")  
  29.                                         .addLine(  
  30.                                                 "Google Play Celebrate 25 billion apps with Goo..")  
  31.                                         .addLine(  
  32.                                                 "Stack Exchange StackOverflow weekly Newsl...")  
  33.                                         .setBigContentTitle("6 new message")  
  34.                                         .setSummaryText("[email protected]"))  
  35.                         .build();  
  36.  
  37.                 NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);  
  38.                 mNotificationManager.notify(0, noti);  
  39.             }  
  40.         }); 

  展示效果:

 

進度條樣式的通知

  對於一個標准通知,有時候顯示的消息並不一定是靜態的,還可以設定一個進度條用於顯示事務完成的進度。

  Notification.Builder類中提供一個setProgress(int max,int progress,boolean indeterminate)方法用於設置進度條,max用於設定進度的最大數,progress用於設定當前的進度,indeterminate用於是否是一個確定進度只的進度條。通過indeterminate的設置,可以實現兩種不同樣式的進度條,一種是有進度的(false),一種是循環流動的(false)。下面分別用兩個示例演示:

  有進度的進度條,實現代碼: 

 

  1. btnProgreNotification.setOnClickListener(new View.OnClickListener() {  
  2.             @Override 
  3.             public void onClick(View v) {  
  4.                 manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);  
  5.                 builder = new NotificationCompat.Builder(MainActivity.this)  
  6.                         .setSmallIcon(R.drawable.ic_launcher)  
  7.                         .setContentTitle("Picture Download")  
  8.                         .setContentText("Download in progress");  
  9.                 builder.setAutoCancel(true);  
  10.                 //通過一個子線程,動態增加進度條刻度  
  11.                 new Thread(new Runnable() {  
  12.                     @Override 
  13.                     public void run() {  
  14.                         int incr;  
  15.                         for (incr = 0; incr <= 100; incr += 5) {  
  16.                             builder.setProgress(100, incr, false);  
  17.                             manager.notify(0, builder.build());  
  18.                             try {  
  19.                                 Thread.sleep(300);  
  20.                             } catch (InterruptedException e) {  
  21.                                 Log.i(TAG, "sleep failure");  
  22.                             }  
  23.                         }  
  24.                         builder.setContentText("Download complete")  
  25.                                 .setProgress(0, 0, false);  
  26.                         manager.notify(0, builder.build());  
  27.                     }  
  28.                 }).start();  
  29.             }  
  30.         }); 

 顯示效果:

   對於循環流動的進度條,下面是實現代碼:

  1. btnProNotification.setOnClickListener(new View.OnClickListener() {  
  2.             @Override 
  3.             public void onClick(View v) {  
  4.                 manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);  
  5.                 builder = new NotificationCompat.Builder(MainActivity.this)  
  6.                         .setSmallIcon(R.drawable.ic_launcher)  
  7.                         .setContentTitle("Picture Download")  
  8.                         .setContentText("Download in progress");  
  9.                 builder.setProgress(0, 0, true);//設置為true,表示流動  
  10.                 manager.notify(0, builder.build());  
  11.  
  12.                 //5秒之後還停止流動  
  13.                 new Thread(new Runnable() {  
  14.                     @Override 
  15.                     public void run() {  
  16.                         try {  
  17.                             Thread.sleep(5000);  
  18.                         } catch (InterruptedException e) {  
  19.                             e.printStackTrace();  
  20.                         }  
  21.                         builder.setProgress(100, 100, false);//設置為true,表示刻度  
  22.                         manager.notify(0, builder.build());  
  23.                     }  
  24.                 }).start();  
  25.             }  
  26.         }); 

 效果展示:

自定義通知

  和Toast一樣,通知也可以使用自定義的XML來自定義樣式,但是對於通知而言,因為它的全局性,並不能簡單的通過inflate膨脹出一個View,因為可能觸發通知的時候,響應的App已經關閉,無法獲取當指定的XML布局文件。所以需要使用單獨的一個RemoteViews類來操作。

  RemoteViews,描述了一個視圖層次的結構,可以顯示在另一個進程。層次結構也是從布局文件中“膨脹”出一個視圖,這個類,提供了一些基本的操作求改其膨脹的內容。

  RemoteViews提供了多個構造函數,一般使用RemoteViews(String packageName,int layoutId)。第一個參數為包的名稱,第二個為layout資源的Id。當獲取到RemoteViews對象之後,可以使用它的一系列setXxx()方法通過控件的Id設置控件的屬性。最後使用NotificationCompat.Builder.setContent(RemoteViews)方法設置它到一個Notification中。

  下面通過一個示例展示它:

  自定義的布局XML代碼:

 

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:layout_width="match_parent" 
  4.     android:layout_height="match_parent" 
  5.     android:padding="10dp" > 
  6.  
  7.     <ImageView 
  8.         android:id="@+id/imageNo" 
  9.         android:layout_width="wrap_content" 
  10.         android:layout_height="match_parent" 
  11.         android:layout_alignParentLeft="true" 
  12.         android:layout_marginRight="10dp" /> 
  13.  
  14.     <TextView 
  15.         android:id="@+id/titleNo" 
  16.         android:layout_width="wrap_content" 
  17.         android:layout_height="wrap_content" 
  18.         android:layout_toRightOf="@id/imageNo" /> 
  19.  
  20.     <TextView 
  21.         android:id="@+id/textNo" 
  22.         android:layout_width="wrap_content" 
  23.         android:layout_height="wrap_content" 
  24.         android:layout_below="@id/titleNo" 
  25.         android:layout_toRightOf="@id/imageNo" /> 
  26.  
  27. </RelativeLayout> 

  實現代碼:

  1. btnCustomNotification.setOnClickListener(new View.OnClickListener() {  
  2.             @Override 
  3.             public void onClick(View v) {  
  4.                 RemoteViews contentViews = new RemoteViews(getPackageName(),  
  5.                         R.layout.custom_notification);  
  6.                 //通過控件的Id設置屬性  
  7.                 contentViews  
  8.                         .setImageViewResource(R.id.imageNo, R.drawable.btm1);  
  9.                 contentViews.setTextViewText(R.id.titleNo, "自定義通知標題");  
  10.                 contentViews.setTextViewText(R.id.textNo, "自定義通知內容");  
  11.  
  12.                 Intent intent = new Intent(MainActivity.this,  
  13.                         ResultActivity.class);  
  14.  
  15.                 PendingIntent pendingIntent = PendingIntent.getActivity(  
  16.                         MainActivity.this, 0, intent,  
  17.                         PendingIntent.FLAG_CANCEL_CURRENT);  
  18.                 NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(  
  19.                         MainActivity.this).setSmallIcon(R.drawable.ic_launcher)  
  20.                         .setContentTitle("My notification")  
  21.                         .setTicker("new message");  
  22.                 mBuilder.setAutoCancel(true);  
  23.  
  24.                 mBuilder.setContentIntent(pendingIntent);  
  25.                 mBuilder.setContent(contentViews);  
  26.                 mBuilder.setAutoCancel(true);  
  27.                 NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);  
  28.                 mNotificationManager.notify(10, mBuilder.build());  
  29.             }  
  30.         }); 

 效果展示:

設定提示響應

  對於有些通知,需要調用一些設備的資源,使用戶能更快的發現有新通知,一般可設定的響應有:鈴聲、閃光燈、震動。對於這三個屬性,NotificationCompat.Builder提供了三個方法設定:

  • setSound(Uri sound):設定一個鈴聲,用於在通知的時候響應。傳遞一個Uri的參數,格式為“file:///mnt/sdcard/Xxx.mp3”。
  • setLights(int argb, int onMs, int offMs):設定前置LED燈的閃爍速率,持續毫秒數,停頓毫秒數。
  • setVibrate(long[] pattern):設定震動的模式,以一個long數組保存毫秒級間隔的震動。

  大多數時候,我們並不需要設定一個特定的響應效果,只需要遵照用戶設備上系統通知的效果即可,那麼可以使用setDefaults(int)方法設定默認響應參數,在Notification中,對它的參數使用常量定義了,我們只需使用即可:

  • DEFAULT_ALL:鈴聲、閃光、震動均系統默認。
  • DEFAULT_SOUND:系統默認鈴聲。
  • DEFAULT_VIBRATE:系統默認震動。
  • DEFAULT_LIGHTS:系統默認閃光。

  而在Android中,如果需要訪問硬件設備的話,是需要對其進行授權的,所以需要在清單文件AndroidManifest.xml中增加兩個授權,分別授予訪問振動器與閃光燈的權限:

  1. <!-- 閃光燈權限 --> 
  2. <uses-permission android:name="android.permission.FLASHLIGHT"/> 
  3. <!-- 振動器權限 --> 
  4. <uses-permission android:name="android.permission.VIBRATE"/> 

 

  因為只是一個屬性的設定,並且大部分時候,使用系統設定即可,這裡就不提供代碼示例了。 

  源碼下載

總結

  通知算是Android中比較常用的一個功能,可以保持自己App的長存,在用戶沒有進入App的時候,也提供了與用戶交互的可能。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved