通知(Notification)這個(gè)功能對(duì)于我們來(lái)說(shuō)非常的常見(jiàn)。打開(kāi)手機(jī)的時(shí)候,各種軟件的推送消息蜂擁而至,然后我們的通知欄被擠得滿(mǎn)滿(mǎn)的。你看到的消息提示框就是通知。
1. Notification 狀態(tài)欄通知的作用
從JellyBean 以來(lái),通知系統(tǒng)做了一次被引入Android 以來(lái)最重大的結(jié)構(gòu)性和功能性的變動(dòng)。
- 通知可以包含操作,用戶(hù)可以在通知抽屜中直接做出回應(yīng)
- 通知在大小和布局方面更加靈活,可以展開(kāi)顯示更多的信息
- 通知有了優(yōu)先級(jí)高低的排列方式,而不僅僅是時(shí)間的排列
1.1 通知狀態(tài)欄的作用
1.顯示接收短消息以及即時(shí)信息等(短信 ,QQ,微信等)
2.顯示客戶(hù)端的推送消息 (廣告,推薦消息等)
3.顯示正在進(jìn)行的事務(wù) (播放器的顯示,版本更新等)
2. Notification的基本用法
通知的基本用法還是很靈活的,可以在活動(dòng)中創(chuàng)建,也可以在廣播接收器中創(chuàng)建,還可以在服務(wù)中創(chuàng)建。一般在廣播和服務(wù)中用的比較多,因?yàn)橹挥性诔绦蜻M(jìn)入后臺(tái)的時(shí)候,我們才需要使用通知,活動(dòng)中使用的比較少。
2.1 通知的基本布局
通知的基本布局包括:
- 發(fā)送通知的應(yīng)用圖標(biāo)或者發(fā)送人的頭像
- 通知標(biāo)題和消息
- 時(shí)間戳
- 當(dāng)主圖標(biāo)顯示發(fā)送人頭像時(shí),在副圖標(biāo)位置顯示應(yīng)用圖標(biāo)
2.2 通知的擴(kuò)展布局
通知的擴(kuò)展布局顯示消息的前面幾行或者圖片的預(yù)覽,后面的信息折疊起來(lái),這樣用戶(hù)就可以看到更多的信息。用戶(hù)可以通過(guò) pinch-zoom 或者雙手指滑動(dòng)來(lái)打開(kāi)擴(kuò)展布局。Android 為單條消息提供了兩種擴(kuò)展布局 (文字和圖像) 供你開(kāi)發(fā)應(yīng)用時(shí)使用。
從 Jelly Bean 開(kāi)始,Android 支持在通知底部顯示附加操作。通過(guò)這些操作,用戶(hù)可以對(duì)通知直接執(zhí)行常見(jiàn)的任務(wù),而不用打開(kāi)應(yīng)用。這樣可以加快操作,配合上滑出消失操作,使用戶(hù)的通知抽屜體驗(yàn)更加順滑。
可以放入通知中的操作有以下特點(diǎn):
- 對(duì)于該通知重要、常用和典型的操作
- 時(shí)間緊迫的
- 不會(huì)與相鄰的操作重復(fù)的
不要放置:
- 模糊的
- 和點(diǎn)擊通知得到的效果一樣的操作,例如閱讀或者打開(kāi)
2.3 通知的優(yōu)先級(jí)
從 Jelly Bean 開(kāi)始,Android 為通知增加了優(yōu)先級(jí)標(biāo)志。這樣你可以使重要的通知相對(duì)于其他通知,總是顯示在第一個(gè)。請(qǐng)通過(guò)以下的表格仔細(xì)選擇通知的優(yōu)先級(jí)
優(yōu)先級(jí) | 用戶(hù) |
---|---|
MAX | 重要而緊急的通知,通知用戶(hù)這個(gè)事件是時(shí)間上緊迫的或者需要立即處理 |
HIGH | 高優(yōu)先級(jí)用于重要的通信內(nèi)容,例如短消息或者聊天,這些都是對(duì)用戶(hù)來(lái)說(shuō)比較有興趣的。 |
DEFAULT | 默認(rèn)優(yōu)先級(jí)用于沒(méi)有特殊優(yōu)先級(jí)分類(lèi)的通知。 |
LOW | 低優(yōu)先級(jí)可以通知用戶(hù)但又不是很緊急的事件。 |
MIN | 用于后臺(tái)消息 (例如天氣或者位置信息)。最低優(yōu)先級(jí)通知將只在狀態(tài)欄顯示圖標(biāo),只有用戶(hù)下拉通知抽屜才能看到內(nèi)容。 |
2.4 創(chuàng)建通知的步驟
- 創(chuàng)建一個(gè)通知管理類(lèi)NotificationManager,通過(guò)調(diào)用 getSystemService()的方法獲得。getSystemService方法接收一個(gè)字符串參數(shù)用于確定獲取系統(tǒng)的哪個(gè)服務(wù),傳入Context.NOTIFICATION_SERVICE
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- 使用Builder構(gòu)造器創(chuàng)建Notification對(duì)象。這里使用 support-v4庫(kù)中提供的NotificationCompat
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
或者這樣寫(xiě):
Notification notification = NotificationCompat.Builder(context).builder();
- 對(duì)Builder進(jìn)行配置(寫(xiě)法和dialog差不多)
mBuilder.setContentTitle("測(cè)試標(biāo)題")//設(shè)置通知欄標(biāo)題
.setContentText("測(cè)試內(nèi)容") //設(shè)置通知欄顯示內(nèi)容
.setContentIntent(getDefalutIntent(Notification.FLAG_AUTO_CANCEL)) //設(shè)置通知欄點(diǎn)擊意圖
// .setNumber(number) //設(shè)置通知集合的數(shù)量
.setTicker("測(cè)試通知來(lái)啦") //通知首次出現(xiàn)在通知欄,帶上升動(dòng)畫(huà)效果的
.setWhen(System.currentTimeMillis())//通知產(chǎn)生的時(shí)間,會(huì)在通知信息里顯示,一般是系統(tǒng)獲取到的時(shí)間
.setPriority(Notification.PRIORITY_DEFAULT) //設(shè)置該通知優(yōu)先級(jí)
// .setAutoCancel(true)//設(shè)置這個(gè)標(biāo)志當(dāng)用戶(hù)單擊面板就可以讓通知將自動(dòng)取消
.setOngoing(false)//ture,設(shè)置他為一個(gè)正在進(jìn)行的通知。他們通常是用來(lái)表示一個(gè)后臺(tái)任務(wù),用戶(hù)積極參與(如播放音樂(lè))或以某種方式正在等待,因此占用設(shè)備(如一個(gè)文件下載,同步操作,主動(dòng)網(wǎng)絡(luò)連接)
.setDefaults(Notification.DEFAULT_VIBRATE)//向通知添加聲音、閃燈和振動(dòng)效果的最簡(jiǎn)單、最一致的方式是使用當(dāng)前的用戶(hù)默認(rèn)設(shè)置,使用defaults屬性,可以組合
//Notification.DEFAULT_ALL Notification.DEFAULT_SOUND 添加聲音 // requires VIBRATE permission
.setSmallIcon(R.drawable.ic_launcher);//設(shè)置通知小ICON
設(shè)置通知欄PendingIntent(點(diǎn)擊動(dòng)作事件等都包含在這里)。PendingIntent 從名字上看和Intent 很像,它們都指明一個(gè)意圖,都可以開(kāi)啟活動(dòng),開(kāi)啟服務(wù)和發(fā)送廣播。但是Intent 傾向于立即執(zhí)行某個(gè)動(dòng)作,而PendingIntent 傾向于某個(gè)時(shí)機(jī)執(zhí)行動(dòng)作。
最后一步,發(fā)送通知請(qǐng)求
mNotificationManager.notify(notifyId, mBuilder.build());
notify()方法有兩個(gè)參數(shù),一個(gè)參數(shù)是id,要保證每個(gè)通知所指定的id都是不同的,第二個(gè)參數(shù)則是Notification對(duì)象。
顯示一個(gè)通知:
mNotificationManager.notify(1, mBuilder.build());
2.5 通知的方法
1. 設(shè)置提醒的標(biāo)志符號(hào)flags,添加聲音,設(shè)置閃燈,震動(dòng)等效果。
兩種設(shè)置方法:
1). 實(shí)例化之后,在設(shè)置flags
Notification notification = mBuilder.build();
notification.flags = Notification.FLAG_AUTO_CANCEL;
2). 通過(guò)setContentIntent(PendingIntent intent)方法中的意圖設(shè)置對(duì)應(yīng)的flags
public PendingIntent getDefalutIntent(int flags){
PendingIntent pendingIntent= PendingIntent.getActivity(this, 1, new Intent(), flags);
return pendingIntent;
}
提醒標(biāo)志符成員:
Notification.FLAG_SHOW_LIGHTS //三色燈提醒,在使用三色燈提醒時(shí)候必須加該標(biāo)志符
Notification.FLAG_ONGOING_EVENT //發(fā)起正在運(yùn)行事件(活動(dòng)中)
Notification.FLAG_INSISTENT //讓聲音、振動(dòng)無(wú)限循環(huán),直到用戶(hù)響應(yīng) (取消或者打開(kāi))
Notification.FLAG_ONLY_ALERT_ONCE //發(fā)起Notification后,鈴聲和震動(dòng)均只執(zhí)行一次
Notification.FLAG_AUTO_CANCEL //用戶(hù)單擊通知后自動(dòng)消失
Notification.FLAG_NO_CLEAR //只有全部清除時(shí),Notification才會(huì)清除 ,不清楚該通知(QQ的通知無(wú)法清除,就是用的這個(gè))
Notification.FLAG_FOREGROUND_SERVICE //表示正在運(yùn)行的服務(wù)
2. setDefaults(int defaults) (NotificationCompat.Builder中的方法,用于提示)
功能:向通知添加聲音、閃燈和振動(dòng)效果的最簡(jiǎn)單、使用默認(rèn)(defaults)屬性,可以組合多個(gè)屬性(和方法1中提示效果一樣的)
對(duì)應(yīng)屬性:
Notification.DEFAULT_VIBRATE //添加默認(rèn)震動(dòng)提醒 需要 VIBRATE permission
Notification.DEFAULT_SOUND // 添加默認(rèn)聲音提醒
Notification.DEFAULT_LIGHTS// 添加默認(rèn)三色燈提醒
Notification.DEFAULT_ALL// 添加默認(rèn)以上3種全部提醒
3. setVibrate(long[] pattern)
功能:設(shè)置震動(dòng)方式
.setVibrate(new long[] {0,300,500,700});
實(shí)現(xiàn)效果:延遲0ms,然后振動(dòng)300ms,在延遲500ms,接著在振動(dòng)700ms。
寫(xiě)法二:
mBuilder.build().vibrate = new long[] {0,300,500,700};
4. setLights(intledARGB ,intledOnMS ,intledOffMS )
功能:android支持三色燈提醒,這個(gè)方法就是設(shè)置不同場(chǎng)景下的不同顏色的燈。
描述:其中l(wèi)edARGB 表示燈光顏色、 ledOnMS 亮持續(xù)時(shí)間、ledOffMS 暗的時(shí)間。
注意:1)只有在設(shè)置了標(biāo)志符Flags為Notification.FLAG_SHOW_LIGHTS的時(shí)候,才支持三色燈提醒。
2)這邊的顏色跟設(shè)備有關(guān),不是所有的顏色都可以,要看具體設(shè)備。
.setLights(0xff0000ff, 300, 0)
同理,實(shí)現(xiàn)同樣的效果:
Notification notify = mBuilder.build();
notify.flags = Notification.FLAG_SHOW_LIGHTS;
notify.ledARGB = 0xff0000ff;
notify.ledOnMS = 300;
notify.ledOffMS = 300;
如果希望使用默認(rèn)的三色燈提醒,設(shè)置了方法(2)中默認(rèn)為DEFAULT_LIGHTS即可。
5. setSound(Uri sound)
功能:設(shè)置默認(rèn)或則自定義的鈴聲,來(lái)提醒。
//獲取默認(rèn)鈴聲
.setDefaults(Notification.DEFAULT_SOUND)
//獲取自定義鈴聲
.setSound(Uri.fromFile(new File("file:///sdcard/xx/xx.mp3")))
//獲取Android多媒體庫(kù)內(nèi)的鈴聲
.setSound(Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "5"))
6. setPriority(int pri)
對(duì)應(yīng)屬性(作用看上圖就可知道):
Notification.PRIORITY_DEFAULT
Notification.PRIORITY_HIGH
Notification.PRIORITY_LOW
Notification.PRIORITY_MAX
Notification.PRIORITY_MIN
7. setOngoing(boolean ongoing)
功能:設(shè)置為ture,表示它為一個(gè)正在進(jìn)行的通知。他們通常是用來(lái)表示一個(gè)后臺(tái)任務(wù),用戶(hù)積極參與(如播放音樂(lè))或以某種方式正在等待,因此占用設(shè)備(如一個(gè)文件下載,同步操作,主動(dòng)網(wǎng)絡(luò)連接)
8. setProgress(int max, int progress,boolean indeterminate)
屬性:max:進(jìn)度條最大數(shù)值 、progress:當(dāng)前進(jìn)度、indeterminate:表示進(jìn)度是否不確定,true為不確定,如下第3幅圖所示 ,false為確定下第1幅圖所示
功能:設(shè)置帶進(jìn)度條的通知,可以在下載中使用
9. 設(shè)置點(diǎn)擊取消
點(diǎn)擊通知消息之后,上面的圖標(biāo)還是沒(méi)有消掉
1)在buider配置的方法中添加
.setAutoCancel(true)
2 ) 在創(chuàng)建管理通知類(lèi)NotificationManager的時(shí)候,調(diào)用cancel()方法
NotificationManager manager= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancel(1);
這里的這個(gè)1 ,是在創(chuàng)建通知的時(shí)候給每條通知指定的notifyId 。因此如果你想取消哪條id就傳哪個(gè)值。
2.6 PendingIntent 的用法
PendingIntent的用法很簡(jiǎn)單。它主要提供了幾個(gè)靜態(tài)方法用于獲取PendingIntent的實(shí)現(xiàn),可以根據(jù)需求使用getActivity()方法,getBroadcast()方法,getService()方法,這幾個(gè)方法里面的參數(shù)都是一樣的。第一個(gè)參數(shù)是Context ,第二個(gè)參數(shù)一般用不到傳個(gè)0就好,第三個(gè)參數(shù)是一個(gè)Intent的對(duì)象,通過(guò)它來(lái)構(gòu)建PendingIntent的“意圖”,第四個(gè)用于確定PendingIntent的行為.
2.6.1 PendingIntent的位標(biāo)識(shí)符:
FLAG_ONE_SHOT 表示返回的PendingIntent僅能執(zhí)行一次,執(zhí)行完后自動(dòng)取消
FLAG_NO_CREATE 表示如果描述的PendingIntent不存在,并不創(chuàng)建相應(yīng)的PendingIntent,而是返回NULL
FLAG_CANCEL_CURRENT 表示相應(yīng)的PendingIntent已經(jīng)存在,則取消前者,然后創(chuàng)建新的PendingIntent,這個(gè)有利于數(shù)據(jù)保持為最新的,可以用于即時(shí)通信的通信場(chǎng)景
FLAG_UPDATE_CURRENT 表示更新的PendingIntent
2.6.2 在各種情況下情況下它還會(huì)根據(jù)各種情況觸發(fā)效果:
contentIntent:在通知窗口區(qū)域,Notification被單擊時(shí)的響應(yīng)事件由該intent觸發(fā);
deleteIntent:當(dāng)用戶(hù)點(diǎn)擊全部清除按鈕時(shí),響應(yīng)該清除事件的Intent;
fullScreenIntent:響應(yīng)緊急狀態(tài)的全屏事件(例如來(lái)電事件),也就是說(shuō)通知來(lái)的時(shí)候,跳過(guò)在通知區(qū)域點(diǎn)擊通知這一步,直接執(zhí)行fullScreenIntent代表的事件。
1). 點(diǎn)擊通知欄跳轉(zhuǎn)到指定的XXActivity中
Intent intent = new Intent(context,XXX.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
mBuilder.setContentIntent(pendingIntent)
2). 在執(zhí)行了清空全部的通知操作時(shí)候,可以設(shè)置以下方法來(lái)相應(yīng)這個(gè)事件
Intent deleteIntent = new Intent();
deleteIntent.setClass(context, XXXReceiver.class);
deleteIntent.setAction(DELETE_ACTION);
notification.deleteIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);
3). 在響應(yīng)緊急事件(如來(lái)電)時(shí)候,可以設(shè)置以下方法來(lái)相應(yīng)這個(gè)事件
setFullScreenIntent(PendingIntent intent, boolean highPriority)
3. 創(chuàng)建自定義的通知欄
Notification的自定義布局是RemoteViews,和其他RemoteViews一樣,在自定義視圖布局文件中,僅支持FrameLayout、LinearLayout、RelativeLayout三種布局控件和AnalogClock、Chronometer、Button、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView和AdapterViewFlipper這些顯示控件,不支持這些類(lèi)的子類(lèi)或Android提供的其他控件。否則會(huì)引起ClassNotFoundException異常
3.1 創(chuàng)建自定義的步驟
1). 創(chuàng)建自定義的視圖
2). 獲取遠(yuǎn)程視圖對(duì)象
3). 設(shè)置PendingIntent(來(lái)響應(yīng)各種事件)
4). 發(fā)起Notification
1.創(chuàng)建自定義的視圖
<?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.獲取視圖對(duì)象
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,"應(yīng)思量");
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.設(shè)置響應(yīng)事件 ,這里設(shè)置廣播來(lái)處理點(diǎn)擊事件。
//點(diǎn)擊事件處理
Intent buttonIntent=new Intent(ACTION_BUTTON);
//頭像點(diǎn)擊
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.發(fā)起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());