Notification的作用
Notification是一種全局效果的通知,在系統的通知欄中顯示。既然作為通知,其基本作用有:
- 顯示接收到短消息、即時信息等
- 顯示客戶端的推送(廣告、優惠、新聞等)
- 顯示正在進行的事物(后台運行的程序,如音樂播放進度、下載進度)
Notification的基本操作:
Notification的基本操作主要有創建、更新和取消三種。一個Notification的必要屬性有三項,如果不設置的話在運行時會拋出異常:
- 小圖標,通過setSmallIcon方法設置
- 標題,通過setContentTitle方法設置
- 內容,通過setContentText方法設置。
除了以上三項,其他均為可選項,不過一般而言,通知需要有交互的功能,所以一般Notification具有Action屬性,這樣就能跳轉到App的某一個Activity、啟動一個service或者發送一個Broadcast。
當系統受到通知時,可以通過震動、鈴聲、呼吸燈等多種方式進行提醒。
下面就從Notification的基本操作逐條介紹:
- Notification的創建
Notification的創建過程主要涉及到Notification.Builder、Notification、NotificationManager
Notification.Builder:
使用建造者模式構建Notification對象。由於Notification.Builder僅支持Android4.1及之后的版本,為了解決兼容性的問題,使用V4兼容庫中的NotifivationCompat.Builder類。
Notification:通知對應類,保存通知相關的數據。NotificationManager向系統發送通知時會用到。
NotificationManager:通知管理類,調用NotificationManager的notify方法可以向系統發送通知。
獲取 NotificationManager 對象:
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
前面講到,Notification有三個必要屬性以及一個很有必要的屬性Action。下面我們就創建一個簡單的Notification,主要有以下三步:
- 獲取NotificationManager實例
- 實例化NotificationCompat.Builder並設置相關屬性
- 通過builder.build方法來生成Notification對象,並發送通知
private void sendNotification(){
Intent intent = new Intent(this,SettingsActivity.class);
PendingIntent mPendingIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_ONE_SHOT);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
//設置小圖標
.setSmallIcon(R.mipmap.ic_launcher)
//點擊后自動清除
.setAutoCancel(true)
//設置通知標題
.setContentTitle("最簡單的通知")
//設置通知內容
.setContentText("真的很簡單很簡單很簡單")
//設置通知的動作
.setContentIntent(mPendingIntent)
//設置通知時間,默認為系統發出通知的時間
.setWhen(System.currentTimeMillis());
//第一個參數為Notification的id
notificationManager.notify(2,builder.build());
}
其中為了實現Action屬性,我們需要創建Intent、PendingIntent和setContentIntent()這幾步。
不難發現,其中的PendingIntent的設置才是其中的關鍵。
PendingIntent支持三種待定的意圖:啟動Activity,啟動Service和發送Broadcast。對應於它的三個接口方法。
| static PendingIntent |
getActivity(Context context,int requestCode,Intent intent,int flags) 獲取一個PendingIntent,該意圖發生時,相當於Context.startActivity(Intent) |
| static PendingIntent |
getService (Context context,int requestCode,Intent intent,int flags) 獲取一個PendingIntent,該意圖發生時,相當於Context.startService (Intent) |
| static PendingIntent |
getBroadcast(Context context,int requestCode,Intent intent,int flags) 獲取一個PendingIntent,該意圖發生時,相當於Context.sendBroadcast(Intent) |
其中context和intent不需要講,主要說一下requestCode和flags。其中requestCode是PendingIntent發送發的請求碼,多數情況下設置為0即可,requestCode會影響到flags的效果。
PendingIntent相同:Intent相同且requestCode也相同。(Intent相同需要ComponentName和intent-filter相同)
flags的常見類型有:
FLAG_ONE_SHOT:只能被使用一次,然后就會被自動cancel,如果后續還有相同的PendingIntent。那么他們的send方法就會調用失敗。
FLAG_NO_CREATE:如果當前系統中不存在相同的PendingIntent對象,系統不會創建該PendingIntent對象,而是直接返回null。(很少使用)
FLAG_CANCEL_CURRENT:如果當前系統中已經存在一個相同的 PendingIntent 對象,那么就將先將已有的 PendingIntent 取消,然后重新生成一個 PendingIntent 對象。
FLAG_UPDATE_CURRENT:當前描述的PendingIntent如果已經存在,那么它們會被更新,即Intent中的Extras會被替換到最新的。
- Notification的更新
更新通知的操作很簡單,只需要再次發送一次相同ID的通知即可,如果之前的通知還沒有被取消,則會直接更新該通知相關的屬性;如果之前的通知已經被取消,則會重新創建一個新的通知。
更新通知和發送通知采用同樣的方法。
- Notification的取消
取消通知的方式主要有以下5種:
- 點擊通知欄的清除按鈕,會清除所有可清除的通知
- 設置了setAutoCancel()或者設置了flags為FLAG_AUTO_CANCEL的通知,點擊通知時會自動清除。
- 通過NotificationManager調用cancel(int id)來取消指定id的通知
- 通過NotificationManager調用cancel(String tag,int id)方法清除指定Tag和ID的通知。
- 通過NotificationManager調用cancelAll()清除所有該應用之前發送的通知
如果是通過NotificationManager.notify(String tag, int id, Notification notify) 方法創建的通知,那么只能通過 NotificationManager.cancel(String tag, int id) 或cancelAll()方法才能清除對應的通知,調用NotificationManager.cancel(int id) 無效。
- Notification的通知效果
前面提到了Notification的通知效果,有了通知效果更能提醒用戶去查看Notification。
Notification的通知效果有震動、呼吸燈、鈴聲三種,可以通過builder中的setDefaults(int defaults)方法來設置,屬性有以下四種,一旦設置了默認效果,自定義效果就會失效。
//添加默認震動效果,需要申請震動權限 //<uses-permission android:name="android.permission.VIBRATE" /> Notification.DEFAULT_VIBRATE //添加系統默認聲音效果,設置此值后,調用setSound()設置自定義聲音無效 Notification.DEFAULT_SOUND //添加默認呼吸燈效果,使用時須與 Notification.FLAG_SHOW_LIGHTS 結合使用,否則無效 Notification.DEFAULT_LIGHTS //添加上述三種默認提醒效果 Notification.DEFAULT_ALL
鈴聲:
//調用系統默認響鈴,設置此屬性后setSound()會無效
//.setDefaults(Notification.DEFAULT_SOUND)
//調用系統多媒體褲內的鈴聲
//.setSound(Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2"));
//調用自己提供的鈴聲,位於 /res/values/raw 目錄下
.setSound(Uri.parse("android.resource://com.littlejie.notification/" + R.raw.sound))
震動:
long[] vibrate = new long[]{0, 500, 1000, 1500};
//使用系統默認的震動參數,會與自定義的沖突
//.setDefaults(Notification.DEFAULT_VIBRATE)
//自定義震動效果
.setVibrate(vibrate);
呼吸燈
//ledARGB 表示燈光顏色、 ledOnMS 亮持續時間、ledOffMS 暗的時間 .setLights(0xFF0000, 3000, 3000);
另一種方式:
Notification notification = builder.build(); //只有在設置了標志符Flags為Notification.FLAG_SHOW_LIGHTS的時候,才支持呼吸燈提醒。 notify.flags = Notification.FLAG_SHOW_LIGHTS; //設置lights參數的另一種方式 //notify.ledARGB = 0xFF0000; //notify.ledOnMS = 500; //notify.ledOffMS = 5000;
還可以通過以下幾種Flag來設置通知效果
//提醒效果常用 Flag
//三色燈提醒,在使用三色燈提醒時候必須加該標志符
Notification.FLAG_SHOW_LIGHTS
//發起正在運行事件(活動中)
Notification.FLAG_ONGOING_EVENT
//讓聲音、振動無限循環,直到用戶響應 (取消或者打開)
Notification.FLAG_INSISTENT
//發起Notification后,鈴聲和震動均只執行一次
Notification.FLAG_ONLY_ALERT_ONCE
//用戶單擊通知后自動消失
Notification.FLAG_AUTO_CANCEL
//只有調用NotificationManager.cancel()時才會清除
Notification.FLAG_NO_CLEAR
//表示正在運行的服務
Notification.FLAG_FOREGROUND_SERVICE
上面講到的Notification的布局都是系統默認的,當然有時候處於需求,我們可能需要自定義Notification的布局。
那如何實現Notification的自定義布局呢?
這里就需要提出一個新的知識點RemoteView,望文生義,即遠程View。
RemoteView表示的是一種View結構,它可以在其他進程中顯示(具體來講是SystemServer進程),由於它是在其他進程中顯示,為了更新它的界面,我們不能簡單地使用普通View的那一套方法,RemoteView提供了一系列Set方法用於更新界面。
下面就是一個簡單的示例;
package com.pignet.remoteviewtest;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RemoteViews;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnNotification = (Button) findViewById(R.id.btn_notification);
btnNotification.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendNotification();
}
});
}
private void sendNotification(){
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification =new Notification();
notification.icon=R.mipmap.ic_launcher;
notification.when=System.currentTimeMillis();
notification.flags=Notification.FLAG_AUTO_CANCEL;
//跳轉意圖
Intent intent = new Intent(this,SettingsActivity.class);
//建立一個RemoteView的布局,並通過RemoteView加載這個布局
RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.layout_notification);
//為remoteView設置圖片和文本
remoteViews.setTextViewText(R.id.message,"第一條通知");
remoteViews.setImageViewResource(R.id.image,R.mipmap.ic_launcher_round);
//設置PendingIntent
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
//為id為openActivity的view設置單擊事件
remoteViews.setOnClickPendingIntent(R.id.openActivity,pendingIntent);
//將RemoteView作為Notification的布局
notification.contentView =remoteViews;
//將pendingIntent作為Notification的intent,這樣當點擊其他部分時,也能實現跳轉
notification.contentIntent=pendingIntent;
notificationManager.notify(1,notification);
}
}
有圖:


