第十九章 Android中的通知Notification

通知(Notification)這個功能對于我們來說非常的常見。打開手機的時候,各種軟件的推送消息蜂擁而至,然后我們的通知欄被擠得滿滿的。你看到的消息提示框就是通知。

1. Notification 狀態欄通知的作用

從JellyBean 以來,通知系統做了一次被引入Android 以來最重大的結構性和功能性的變動。

  • 通知可以包含操作,用戶可以在通知抽屜中直接做出回應
  • 通知在大小和布局方面更加靈活,可以展開顯示更多的信息
  • 通知有了優先級高低的排列方式,而不僅僅是時間的排列

1.1 通知狀態欄的作用

1.顯示接收短消息以及即時信息等(短信 ,QQ,微信等)
2.顯示客戶端的推送消息 (廣告,推薦消息等)
3.顯示正在進行的事務 (播放器的顯示,版本更新等)

2. Notification的基本用法

通知的基本用法還是很靈活的,可以在活動中創建,也可以在廣播接收器中創建,還可以在服務中創建。一般在廣播和服務中用的比較多,因為只有在程序進入后臺的時候,我們才需要使用通知,活動中使用的比較少。

2.1 通知的基本布局

通知的基本布局包括:

  • 發送通知的應用圖標或者發送人的頭像
  • 通知標題和消息
  • 時間戳
  • 當主圖標顯示發送人頭像時,在副圖標位置顯示應用圖標
通知的基本布局

2.2 通知的擴展布局

通知的擴展布局顯示消息的前面幾行或者圖片的預覽,后面的信息折疊起來,這樣用戶就可以看到更多的信息。用戶可以通過 pinch-zoom 或者雙手指滑動來打開擴展布局。Android 為單條消息提供了兩種擴展布局 (文字和圖像) 供你開發應用時使用。

通知的擴展布局

從 Jelly Bean 開始,Android 支持在通知底部顯示附加操作。通過這些操作,用戶可以對通知直接執行常見的任務,而不用打開應用。這樣可以加快操作,配合上滑出消失操作,使用戶的通知抽屜體驗更加順滑。
可以放入通知中的操作有以下特點:

  • 對于該通知重要、常用和典型的操作
  • 時間緊迫的
  • 不會與相鄰的操作重復的

不要放置:

  • 模糊的
  • 和點擊通知得到的效果一樣的操作,例如閱讀或者打開

2.3 通知的優先級

從 Jelly Bean 開始,Android 為通知增加了優先級標志。這樣你可以使重要的通知相對于其他通知,總是顯示在第一個。請通過以下的表格仔細選擇通知的優先級

優先級 用戶
MAX 重要而緊急的通知,通知用戶這個事件是時間上緊迫的或者需要立即處理
HIGH 高優先級用于重要的通信內容,例如短消息或者聊天,這些都是對用戶來說比較有興趣的。
DEFAULT 默認優先級用于沒有特殊優先級分類的通知。
LOW 低優先級可以通知用戶但又不是很緊急的事件。
MIN 用于后臺消息 (例如天氣或者位置信息)。最低優先級通知將只在狀態欄顯示圖標,只有用戶下拉通知抽屜才能看到內容。
通知的優先級

2.4 創建通知的步驟

  1. 創建一個通知管理類NotificationManager,通過調用 getSystemService()的方法獲得。getSystemService方法接收一個字符串參數用于確定獲取系統的哪個服務,傳入Context.NOTIFICATION_SERVICE
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);  
  1. 使用Builder構造器創建Notification對象。這里使用 support-v4庫中提供的NotificationCompat
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);  
或者這樣寫:
Notification notification = NotificationCompat.Builder(context).builder();  
  1. 對Builder進行配置(寫法和dialog差不多)
    mBuilder.setContentTitle("測試標題")//設置通知欄標題  
    .setContentText("測試內容") //設置通知欄顯示內容
    .setContentIntent(getDefalutIntent(Notification.FLAG_AUTO_CANCEL)) //設置通知欄點擊意圖  
//  .setNumber(number) //設置通知集合的數量  
    .setTicker("測試通知來啦") //通知首次出現在通知欄,帶上升動畫效果的  
    .setWhen(System.currentTimeMillis())//通知產生的時間,會在通知信息里顯示,一般是系統獲取到的時間  
    .setPriority(Notification.PRIORITY_DEFAULT) //設置該通知優先級  
//  .setAutoCancel(true)//設置這個標志當用戶單擊面板就可以讓通知將自動取消    
    .setOngoing(false)//ture,設置他為一個正在進行的通知。他們通常是用來表示一個后臺任務,用戶積極參與(如播放音樂)或以某種方式正在等待,因此占用設備(如一個文件下載,同步操作,主動網絡連接)  
    .setDefaults(Notification.DEFAULT_VIBRATE)//向通知添加聲音、閃燈和振動效果的最簡單、最一致的方式是使用當前的用戶默認設置,使用defaults屬性,可以組合  
    //Notification.DEFAULT_ALL  Notification.DEFAULT_SOUND 添加聲音 // requires VIBRATE permission  
    .setSmallIcon(R.drawable.ic_launcher);//設置通知小ICON  
 
  1. 設置通知欄PendingIntent(點擊動作事件等都包含在這里)。PendingIntent 從名字上看和Intent 很像,它們都指明一個意圖,都可以開啟活動,開啟服務和發送廣播。但是Intent 傾向于立即執行某個動作,而PendingIntent 傾向于某個時機執行動作。

  2. 最后一步,發送通知請求

mNotificationManager.notify(notifyId, mBuilder.build());  

notify()方法有兩個參數,一個參數是id,要保證每個通知所指定的id都是不同的,第二個參數則是Notification對象。
顯示一個通知:

mNotificationManager.notify(1, mBuilder.build());  

2.5 通知的方法

1. 設置提醒的標志符號flags,添加聲音,設置閃燈,震動等效果。
兩種設置方法:
1). 實例化之后,在設置flags

Notification notification = mBuilder.build();  
notification.flags = Notification.FLAG_AUTO_CANCEL;  

2). 通過setContentIntent(PendingIntent intent)方法中的意圖設置對應的flags

public PendingIntent getDefalutIntent(int flags){  
    PendingIntent pendingIntent= PendingIntent.getActivity(this, 1, new Intent(), flags);  
    return pendingIntent;  
} 

提醒標志符成員:
Notification.FLAG_SHOW_LIGHTS //三色燈提醒,在使用三色燈提醒時候必須加該標志符
Notification.FLAG_ONGOING_EVENT //發起正在運行事件(活動中)
Notification.FLAG_INSISTENT //讓聲音、振動無限循環,直到用戶響應 (取消或者打開)
Notification.FLAG_ONLY_ALERT_ONCE //發起Notification后,鈴聲和震動均只執行一次
Notification.FLAG_AUTO_CANCEL //用戶單擊通知后自動消失
Notification.FLAG_NO_CLEAR //只有全部清除時,Notification才會清除 ,不清楚該通知(QQ的通知無法清除,就是用的這個)
Notification.FLAG_FOREGROUND_SERVICE //表示正在運行的服務

2. setDefaults(int defaults) (NotificationCompat.Builder中的方法,用于提示)
功能:向通知添加聲音、閃燈和振動效果的最簡單、使用默認(defaults)屬性,可以組合多個屬性(和方法1中提示效果一樣的)
對應屬性:
Notification.DEFAULT_VIBRATE //添加默認震動提醒 需要 VIBRATE permission
Notification.DEFAULT_SOUND // 添加默認聲音提醒
Notification.DEFAULT_LIGHTS// 添加默認三色燈提醒
Notification.DEFAULT_ALL// 添加默認以上3種全部提醒
3. setVibrate(long[] pattern)
功能:設置震動方式

.setVibrate(new long[] {0,300,500,700});  

實現效果:延遲0ms,然后振動300ms,在延遲500ms,接著在振動700ms。
寫法二:

mBuilder.build().vibrate = new long[] {0,300,500,700};  

4. setLights(intledARGB ,intledOnMS ,intledOffMS )
功能:android支持三色燈提醒,這個方法就是設置不同場景下的不同顏色的燈。
描述:其中ledARGB 表示燈光顏色、 ledOnMS 亮持續時間、ledOffMS 暗的時間。
注意:1)只有在設置了標志符Flags為Notification.FLAG_SHOW_LIGHTS的時候,才支持三色燈提醒。
2)這邊的顏色跟設備有關,不是所有的顏色都可以,要看具體設備。

.setLights(0xff0000ff, 300, 0)  

同理,實現同樣的效果:

Notification notify = mBuilder.build();  
notify.flags = Notification.FLAG_SHOW_LIGHTS;  
notify.ledARGB = 0xff0000ff;  
notify.ledOnMS = 300;  
notify.ledOffMS = 300;  

如果希望使用默認的三色燈提醒,設置了方法(2)中默認為DEFAULT_LIGHTS即可。
5. setSound(Uri sound)
功能:設置默認或則自定義的鈴聲,來提醒。

//獲取默認鈴聲  
.setDefaults(Notification.DEFAULT_SOUND)  
//獲取自定義鈴聲  
.setSound(Uri.fromFile(new File("file:///sdcard/xx/xx.mp3")))  
//獲取Android多媒體庫內的鈴聲  
.setSound(Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "5"))  

6. setPriority(int pri)
對應屬性(作用看上圖就可知道):
Notification.PRIORITY_DEFAULT
Notification.PRIORITY_HIGH
Notification.PRIORITY_LOW
Notification.PRIORITY_MAX
Notification.PRIORITY_MIN
7. setOngoing(boolean ongoing)
功能:設置為ture,表示它為一個正在進行的通知。他們通常是用來表示一個后臺任務,用戶積極參與(如播放音樂)或以某種方式正在等待,因此占用設備(如一個文件下載,同步操作,主動網絡連接)
8. setProgress(int max, int progress,boolean indeterminate)
屬性:max:進度條最大數值 、progress:當前進度、indeterminate:表示進度是否不確定,true為不確定,如下第3幅圖所示 ,false為確定下第1幅圖所示
功能:設置帶進度條的通知,可以在下載中使用

帶進度條的通知

9. 設置點擊取消
點擊通知消息之后,上面的圖標還是沒有消掉
1)在buider配置的方法中添加

.setAutoCancel(true)

2 ) 在創建管理通知類NotificationManager的時候,調用cancel()方法

NotificationManager manager= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);  
manager.cancel(1);

這里的這個1 ,是在創建通知的時候給每條通知指定的notifyId 。因此如果你想取消哪條id就傳哪個值。

2.6 PendingIntent 的用法

PendingIntent的用法很簡單。它主要提供了幾個靜態方法用于獲取PendingIntent的實現,可以根據需求使用getActivity()方法,getBroadcast()方法,getService()方法,這幾個方法里面的參數都是一樣的。第一個參數是Context ,第二個參數一般用不到傳個0就好,第三個參數是一個Intent的對象,通過它來構建PendingIntent的“意圖”,第四個用于確定PendingIntent的行為.
2.6.1 PendingIntent的位標識符:
FLAG_ONE_SHOT 表示返回的PendingIntent僅能執行一次,執行完后自動取消
FLAG_NO_CREATE 表示如果描述的PendingIntent不存在,并不創建相應的PendingIntent,而是返回NULL
FLAG_CANCEL_CURRENT 表示相應的PendingIntent已經存在,則取消前者,然后創建新的PendingIntent,這個有利于數據保持為最新的,可以用于即時通信的通信場景
FLAG_UPDATE_CURRENT 表示更新的PendingIntent

2.6.2 在各種情況下情況下它還會根據各種情況觸發效果:
contentIntent:在通知窗口區域,Notification被單擊時的響應事件由該intent觸發;
deleteIntent:當用戶點擊全部清除按鈕時,響應該清除事件的Intent;
fullScreenIntent:響應緊急狀態的全屏事件(例如來電事件),也就是說通知來的時候,跳過在通知區域點擊通知這一步,直接執行fullScreenIntent代表的事件。
1). 點擊通知欄跳轉到指定的XXActivity中

Intent intent = new Intent(context,XXX.class);  
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);  
mBuilder.setContentIntent(pendingIntent)

2). 在執行了清空全部的通知操作時候,可以設置以下方法來相應這個事件

Intent deleteIntent = new Intent();  
deleteIntent.setClass(context, XXXReceiver.class);  
deleteIntent.setAction(DELETE_ACTION);  
notification.deleteIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);  

3). 在響應緊急事件(如來電)時候,可以設置以下方法來相應這個事件

setFullScreenIntent(PendingIntent intent, boolean highPriority)

3. 創建自定義的通知欄

Notification的自定義布局是RemoteViews,和其他RemoteViews一樣,在自定義視圖布局文件中,僅支持FrameLayout、LinearLayout、RelativeLayout三種布局控件和AnalogClock、Chronometer、Button、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView和AdapterViewFlipper這些顯示控件,不支持這些類的子類或Android提供的其他控件。否則會引起ClassNotFoundException異常

3.1 創建自定義的步驟

1). 創建自定義的視圖
2). 獲取遠程視圖對象
3). 設置PendingIntent(來響應各種事件)
4). 發起Notification

1.創建自定義的視圖

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="100dp">
<ImageView
    android:id="@+id/iv_not_head_image"
    android:layout_width="0dp"
    android:layout_weight="1"
    android:layout_height="match_parent"
    android:src="@mipmap/youname"
    android:scaleType="centerCrop"
    />
    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight="3"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#0093fe">
        <TextView
            android:id="@+id/tv_not_head_title"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="歌名"
            android:gravity="center"
            android:textColor="#fff"
            android:textSize="18sp"/>
        <TextView
            android:id="@+id/tv_not_head_content"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="歌手"
            android:gravity="center"
            android:textColor="#fff"
            android:textSize="15sp"/>

    </LinearLayout>
<LinearLayout
    android:id="@+id/ll_custom_button"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:layout_weight="2"
    android:background="#334455">
    <ImageView
        android:id="@+id/iv_not_up"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:src="@drawable/btn_prev"
        android:scaleType="centerInside"
       />
    <ImageView
        android:id="@+id/iv_not_play"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:src="@drawable/btn_play"
        android:scaleType="centerInside"/>
    <ImageView
        android:id="@+id/iv_not_next"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:src="@drawable/btn_next"
        android:scaleType="centerInside"/>

</LinearLayout>


</LinearLayout>

2.獲取視圖對象

 RemoteViews mRemoteViews= new RemoteViews(getPackageName(),R.layout.notification_my_style);
        mRemoteViews.setImageViewResource(R.id.iv_not_head_image,R.mipmap.youname);

        mRemoteViews.setTextViewText(R.id.tv_not_head_title,"應思量");
        mRemoteViews.setTextViewText(R.id.tv_not_head_content,"五色石");
        if( Build.VERSION.SDK_INT <= 9){
            mRemoteViews.setViewVisibility(R.id.ll_custom_button, View.GONE);
        }else{
            mRemoteViews.setViewVisibility(R.id.ll_custom_button, View.VISIBLE);
            if(isPlay){
                mRemoteViews.setImageViewResource(R.id.iv_not_play,R.drawable.btn_pause);
            }else{
                mRemoteViews.setImageViewResource(R.id.iv_not_play,R.drawable.btn_play);
            }
        }

3.設置響應事件 ,這里設置廣播來處理點擊事件。

 //點擊事件處理
        Intent buttonIntent=new Intent(ACTION_BUTTON);
         //頭像點擊
        buttonIntent.putExtra(INTENT_BUTTONID_TAG,BUTTON_PREV_ID);
        //這里加了廣播,所及INTENT的必須用getBroadcast方法
        PendingIntent intent_head_image = PendingIntent.getBroadcast(this, 1, buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        mRemoteViews.setOnClickPendingIntent(R.id.iv_not_head_image, intent_head_image);
        //歌名
        buttonIntent.putExtra(INTENT_BUTTONID_TAG,TEXTVIEW_TITLE_ID);
        PendingIntent intent_title = PendingIntent.getBroadcast(this,2,buttonIntent,PendingIntent.FLAG_UPDATE_CURRENT);
        mRemoteViews.setOnClickPendingIntent(R.id.tv_not_head_title,intent_title);
        //歌手
        buttonIntent.putExtra(INTENT_BUTTONID_TAG,TEXTVIEW_CONTENT_ID);
        PendingIntent intent_content = PendingIntent.getBroadcast(this,3,buttonIntent,PendingIntent.FLAG_UPDATE_CURRENT);
        mRemoteViews.setOnClickPendingIntent(R.id.tv_not_head_content,intent_content);

        //上一曲
        buttonIntent.putExtra(INTENT_BUTTONID_TAG,IMAGEVIEW_LEFT_ID);
        PendingIntent intent_left = PendingIntent.getBroadcast(this,4,buttonIntent,PendingIntent.FLAG_UPDATE_CURRENT);
        mRemoteViews.setOnClickPendingIntent(R.id.iv_not_up,intent_left);
        //播放、暫停按鈕
        buttonIntent.putExtra(INTENT_BUTTONID_TAG,IMAGEVIEW_CONTENT_ID);
        PendingIntent intent_play= PendingIntent.getBroadcast(this,5,buttonIntent,PendingIntent.FLAG_UPDATE_CURRENT);
        mRemoteViews.setOnClickPendingIntent(R.id.iv_not_play, intent_play);
        //下一曲
        buttonIntent.putExtra(INTENT_BUTTONID_TAG,IMAGEVIEW_RIGHT_ID);
        PendingIntent intent_right= PendingIntent.getBroadcast(this,6,buttonIntent,PendingIntent.FLAG_UPDATE_CURRENT);
        mRemoteViews.setOnClickPendingIntent(R.id.iv_not_next, intent_right);

4.發起Notification

 NotificationManager manager= (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
   NotificationCompat.Builder  builder= new NotificationCompat.Builder(this);
        builder.setContent(mRemoteViews);
        builder.setWhen(System.currentTimeMillis());
        builder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
        builder.setOngoing(true);
        builder.setSmallIcon(R.drawable.a2);
        builder.setAutoCancel(true);
        manager.notify(1, builder.build());
自定義通知

github地址:https://github.com/wangxin3119/MyNotificationDemo

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,963評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,348評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,083評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,706評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,442評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,802評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,795評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,983評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,287評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,486評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,030評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,710評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,116評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,412評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,224評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,462評論 2 378

推薦閱讀更多精彩內容