Android 之 Notification 必須掌握知識點
創建并發送一個系統通知
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mu_16jj.notificationdemo.MainActivity">
<TextView
android:id="@+id/tv_send_notification"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_centerInParent="true"
android:gravity="center"
android:background="@color/colorAccent"
android:text="send notification"
android:textSize="16sp" />
</RelativeLayout>
很簡單的布局,就一個 TextView 利用其點擊事件來發送通知。
創建 Notification
private void createNotification() {
notification = new NotificationCompat.Builder(MainActivity.this)
.setContentTitle("Notification title")
.setTicker("Ticker method function...")
.setContentText("Notification content text")
.setSubText("subtext...")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher_round)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.large_icon))
.build();
}
通過 NotificationCompat.Build 來構建一個 Notification 對象,并設置一系列屬性(每個屬性對應的效果后面展示)。
發送按鈕監聽
notificationManager.notify(1, notification);
這里需要說明的是,Notification 的發送還是由 NotificationManager 來管理的,第一個參數用來標識一個唯一的 Notification;第二個參數就是需要發送的 Notification 對象。我們在 onCreate 方法中通過以下代碼初始化了通知管理器對象:
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
運行效果
通知效果
屬性介紹
創建通知時的一些基本屬性就利用效果圖解釋完了,其中的 setTicker 需要真機運行才可以看到效果。
可是,這個時候我們點擊這條通知后,該通知一直在系統狀態欄,既沒有消失,也沒有頁面跳轉,這并不是我們想要的效果,所以下面就來實現點擊通知跳轉頁面,這里以系統提供的登錄 Activity 為目的界面。
-
實現點擊跳轉界面
修改我們創建通知的方法
private void createNotification() {
Intent intent = new Intent(this, LoginActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
notification = new NotificationCompat.Builder(MainActivity.this)
.setContentTitle("Notification title")
.setContentText("Notification content text")
.setSubText("subtext...")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher_round)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.large_icon))
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build();
}
可以看到,這里增加了一個 setContentIntent 方法,該方法接收一個 PendingIntent 參數,而獲取該實例則可以有三種途徑:getActivity(),getBroadcast(),getService();這幾個方法所接收的參數都是相同的,第一個是上下文,第二個參數一般很少使用,傳 0 即可,第三個參數便是點擊通知需要跳轉的 Intent 意圖對象(LoginActivity直接使用 AS 提供的模板),第四個參數用于確定 PendingIntent 的行為,有 4 種植可選:FLAG_ONE_SHOT,FLAG_NO_CREATE,CANCEL_CURRENT 和 FLAG_UPDATE_CURRENT。
運行效果
主要常量
FLAG_CANCEL_CURRENT:如果當前系統中已經存在一個相同的 PendingIntent 對象,那么就將先前已有的 PendingIntent 取消,然后重新生成一個 PendingIntent 對象。
FLAG_NO_CREATE:如果當前系統中不存在相同的 PendingIntent 對象,系統將不會創建該 PendingIntent 對象而是直接返回 null。
FLAG_ONE_SHOT:該 PendingIntent 只作用一次。在該 PendingIntent 對象通過send() 方法觸發過后,PendingIntent 將自動調用 cancel() 進行銷毀,那么如果你再調用 send() 方法的話,系統將會返回一個 SendIntentException。
FLAG_UPDATE_CURRENT:如果系統中有一個和你描述的 PendingIntent 對等的PendingInent,那么系統將使用該 PendingIntent 對象,但是會使用新的 Intent 來更新之前 PendingIntent 中的 Intent 對象數據,例如更新 Intent 中的 Extras。
PendingIntent 和 Intent
PendingIntent 是一個特殊的 Intent,主要區別是 intent 是立馬執行,PendingIntent 是待確定的 Intent。PendingIntent 的操作實際上是傳入的 intent 的操作。使用 pendingIntent 的目的主要是用于所包含的 intent 執行是否滿足某些條件。
- 實現點擊通知后,這條通知從系統狀態欄消失
有兩種辦法,一種是給 Notification 設置
setAutoCancel(true)
另一種是通過通知管理器調用 cancel 方法,該方法有一個參數,就是我們前面發送的時候設置的唯一標識。
通知,設置特效
我們常見的手機 APP 當有推送消息或者電話之類的通知時,我們的手機 LED 燈會亮起來,而且顏色也會不一樣,有時候還會有聲音,或者震動之類的,下面就來學習這些方法,這里我通過監聽手機鎖屏的廣播來發送通知(效果會更好),不再使用上面的按鈕來發送(鎖屏速度快的話效果還是可以看到的)。
創建通知代碼
private void createNotification() {
Intent intent = new Intent(this, LoginActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
notification = new NotificationCompat.Builder(MainActivity.this)
.setContentTitle("Notification title")
.setContentText("Notification content text")
.setSubText("subtext...")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher_round)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.large_icon))
// 跳轉界面 系統狀態欄通知消失
.setContentIntent(pendingIntent)
.setAutoCancel(true)
// 收到通知時播放聲音并震動
.setDefaults(NotificationCompat.DEFAULT_SOUND) // 默認通知聲音
// .setSound(Uri.fromFile(new File("/system/media/audio/ringtones/Luna.ogg")))
.setVibrate(new long[]{0, 1000, 1000, 1000})
// LED 燈顏色
.setLights(Color.RED, 1000, 1000)
// 根據手機的當前環境使用默認
// .setDefaults(NotificationCompat.DEFAULT_ALL)
.build();
}
這里的注釋已經很清楚了,需要注意的是震動是需要權限的:
<uses-permission android:name="android.permission.VIBRATE" />
廣播接收器
/**
* 監聽手機鎖屏
*/
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
notificationManager.notify(1, notification);
}
}
}
關注注冊廣播問題,請看《 Android 廣播介紹以及使用示例 》
-
高級之 setStyle() 和 setPriority() 方法
-
通知內容支持長文本
.setStyle(new NotificationCompat.BigTextStyle().bigText("The failures and reverses which await men - and one after another sadden the brow of youth - add a dignity to the prospect of human life, which no Arcadian success would do. -- Henry David Thoreau"))
運行效果
-
- 通知內容支持大圖片
.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(), R.drawable.large_icon)))
-
通知優先級
通知的優先級共有五個常量值可選:PRIORITY_DEFAULT(默認);PRIORITY_MIN 最低優先級,系統可能在特定場景才會顯示這條通知,比如用戶下拉狀態欄;PRIORITY_LOW 較低優先級,系統可能會將這類通知縮小,或改變其顯示的順序,將其排在更重要的通知之后;PRIORITY_HIGH 表示較高優先級,系統可能會將這類通知放大、改變其顯示的順序,將其排在靠前的位置; PRIORITY_MAX 表示最高的重要通知,這類通知必須要讓用戶立刻看到,甚至需要用戶做出響應操作。
.setPriority(NotificationCompat.PRIORITY_MAX)
運行效果(PRIORITY_MAX)
自定義布局通知
我們在已有的界面基礎上再增加一個 TextView 用它的點擊事件來發送自定義通知,自定義通知代碼如下:
/**
* 創建自定義布局通知
*/
private void createCustomNotification() {
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
remoteViews.setImageViewResource(R.id.iv_cus_notification, R.mipmap.ic_launcher);
remoteViews.setTextViewText(R.id.tv_cus_notification, "Notification of Android");
remoteViews.setTextViewText(R.id.btn_cus_notification, "Button");
cusNotification = new NotificationCompat.Builder(MainActivity.this)
// 切記,一定要設置,否則通知顯示不出來
.setSmallIcon(R.mipmap.ic_launcher)
.setContent(remoteViews)
.setTicker("Custom Notification")
.setAutoCancel(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.build();
}
可以看到,相比系統通知的創建,這里多了一個新的 API——RemoteViews. 我們的自定義布局就是通過它來加載,通過它的一系列 setXXX 方法可以給我們的布局中控件設置相關屬性,然后通過 Builder 的 setContent 方法將其設置上去,這樣我們的自定義通知效果就實現了。
點擊事件
notificationManager.notify(2, cusNotification);
運行效果
關于通知的自定義布局從效果就可以看到,很簡單,這里不貼出。
注意點
自定義通知布局的可用高度取決于通知視圖。普通視圖布局限制為 64 dp,擴展視圖布局限制為 256 dp。
無論是系統通知還是自定義布局通知,smallIcon 是必須設置的。
來自:https://juejin.im/post/58ec1c210ce463006babbba8