Android 消息通知欄用法詳解(一)

Android 消息通知欄用法詳解(二) 適配8.0

通知(Notification) 是Android 系統比較有特色的一個功能,當某個應用程序希望向用戶發出一些提示信息的時,而該應用程序又處於後臺,就可以藉助通知來實現。比如微信彈窗。通過這篇文章,我們將學習到

  • Notification 的基本用法
  • Notification 聲音、優先級、多文字和大圖片的顯示
  • Notification 高級玩法
  • 自定義 Notification 的佈局

官網 Nitification 資料

一、基本用法

通知可以在 廣播、activity 或者 service 去創建,不過在 activity 創建得比較少,一般都是應用在後臺了,才需要去弄,不過我們是demo,所以寫哪都沒關係。

創建通知的基本步驟如下:

  1. 使用getSystemService 拿到 NotificationManager 的管理類
  2. 使用NotificationCompat 設置標題、內容、圖片等
  3. 最後調用 NotificationManager 的 notify() 調出通知欄

上面中,爲什麼要使用 NotificationCompat 呢,因爲Android系統的每一個版本都會對通知這部分功能進行或多或少的修改,API 比較不穩定,所以這裏使用 v4 的包去兼容,當然,如果你使用 androidx,也就沒啥問題了。
所以,一個簡單的通知實例如下 :

以下代碼建議在8.0之下運行,8.0以上,請參考下一篇文章

首先創建 NotificationManager

mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
 mBuilder = new NotificationCompat.Builder(this)
          .setContentTitle("這是標題")
          .setContentText("我是內容,我是demo")
          .setWhen(System.currentTimeMillis())
          .setSmallIcon(R.mipmap.ic_launcher)
          .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher));
 
  //通過 builder.build() 拿到 notification
  mNotificationManager.notify(1, mBuilder.build());

解釋如下:

  • setContentTitle 爲設置標題
  • setContentText 爲正文內容
  • setWhen 爲通知創建時間,以 ms 爲單位
  • setSmallIcon 通知的小圖標,注意只能使用 純 alpha 圖層的圖片進行設置
  • setLargeIcon 通知欄的大圖標

都設置完成之後,只要使用 nofity() 即可,其中,第一個參數爲 id,後面用來取消通知的。所以隨便填一個數字即可,效果如下。
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20200327070642163.png

可以看到,小圖標是灰色的。當然了,google 要求是 alpha 的圖層呢。
什麼是 純 alpha 的圖層圖片呢?通俗來講,就是圖片不要帶顏色就可以了,當然UI設計師肯定知道,就是用 alpha 層去繪製圖片嗎,咱們也可以從 阿里巴巴的圖片庫下載,比如:

在這裏插入圖片描述

然後咱們設置一下
在這裏插入圖片描述
但是,發現默認還是灰色的,這裏可以使用 setcolor 去設置:

 .setColor(getResources().getColor(R.color.colorPrimary))

在這裏插入圖片描述
這裏咱們就設置好了小圖標了

1.1 設置點擊事件

一般的通知欄都是可以點擊的,但是我們點擊了一下,發現並沒有什麼用。當然,我們都沒設置點擊事件。
notification 的點擊事件,可以通過設置 setContentIntent 來實現。它需要傳遞一個 PendingIntent。從而實現點擊之後的跳轉意圖。
PendingIntent 的用法也很簡單,它可以通過 getActivity(),getBroadcast() 和 getService() 來獲取不同的實例,一個簡單獲取 activity 的方法如下:

Intent intent = new Intent(this,SecondActivity.class);
PendingIntent pi = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_CANCEL_CURRENT);

它的參數也比較簡單,第一個爲 context,第二個爲 requestCode,一般用不到,intent 即你要跳轉的意圖。第四個參數有5種選擇,分別如下:

  • FLAG_CANCEL_CURRENT:如果當前系統中已經存在一個相同的 PendingIntent 對象,那麼就將先將已有的 PendingIntent 取消,然後重新生成一個 PendingIntent 對象。
  • FLAG_IMMUTABLE:創建的PendingIntent不可變,API23加入。
  • FLAG_NO_CREATE:如果當前系統中不存在相同的 PendingIntent 對象,系統將不會創建該 PendingIntent 對象而是直接返回 null 。
  • FLAG_ONE_SHOT:該 PendingIntent 只作用一次。
  • FLAG_UPDATE_CURRENT:如果系統中已存在該 PendingIntent 對象,那麼系統將保留該 PendingIntent 對象,但是會使用新的 Intent 來更新之前 PendingIntent 中的 Intent 對象數據,例如更新 Intent 中的 Extras。

一般第四個傳輸,傳遞 0 或者FLAG_CANCEL_CURRENT 都可以。
所以,我們的通知代碼改一下:

        mBuilder = new NotificationCompat.Builder(this)
                 .setContentTitle("這是標題")
                 .setContentText("我是內容,我是demo")
                 .setWhen(System.currentTimeMillis())
                 .setSmallIcon(R.mipmap.ic_launcher)
                 .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))
                 .setContentIntent(pi);
         //通過 builder.build() 拿到 notification
         mNotificationManager.notify(1, mBuilder.build());

1.2 取消通知

點擊之後,發現確實跳轉了,但是通知欄還在。取消共有兩種方式

  1. setAutoCancel(true) 在builder 那裏,添加自動取消的功能
  2. mNotificationManager.cancel(1); 通過取消 id 取消,如果有 tag ,也可以使用 cancel(tag,id) 來取消

1.3 通知更新

更新通知,只需要重新 notify 相同的 id 即可,如果通知欄還在,則更新內容,如果不存在,則增加一個新的通知欄,如下,我們更新一下內容:

 mBuilder.setContentText("我更新了內容");
 mNotificationManager.notify(1,mBuilder.build());

在這裏插入圖片描述

二、通知欄效果

上面,咱們只是簡單的實現了通知欄,但是一些好玩的效果,咱們並沒有實現,這節,一起來看看通知欄的效果。

(請用真機測試)

2.1 聲音

很多通知欄,都有聲音的效果,同樣,我們也可以設置。使用 setSound 即可實現,比如:

mBuilder = new NotificationCompat.Builder(this)
		  ...
         //這個看各自的手機的鈴聲的路徑
          .setSound(Uri.fromFile(new File("system/media/audio/notifications/Argon.ogg")))
          .setAutoCancel(true);

除了自定義,還可以使用默認鈴聲:

.setDefaults(NotificationCompat.DEFAULT_SOUND)

2.2 震動

除了聲音,還可以讓手機震動,使用的是 setVibrate,它的參數爲一個 long 的數組,以 ms 爲單位,如果我們想讓手機震動1s,延時一秒,再震動一次,當然,它需要向申請權限

<uses-permission android:name="android.permission.VIBRATE"/>
.setVibrate(new long[]{0,1000,1000,1000})

同理,也可以使用默認震動效果:

.setDefaults(NotificationCompat.DEFAULT_VIBRATE)

2.3 LED燈

現在手機都LED燈,在手機息屏或者未接來電燈,還是還有必要的。同樣,可以使用 setLights() 來實現效果。它又三個參數,第一個是設置燈的顏色,第二個是燈亮的時間,第三個則是燈暗的時間。如下:

.setLights(Color.RED,1000,1000)

同理,用默認的

.setDefaults(NotificationCompat.DEFAULT_LIGHTS)

ps:在國內百花齊放的環境中,上面那玩意基本無效,只能看各自的廠商的說明文檔去適配了。

如果你覺得,上面的設置太麻煩,還有一個方法,直接全部設置成默認的:

.setDefaults(NotificationCompat.DEFAULT_ALL)

三、Notification 的高級玩法

在實際應用中,我們常常需要配合一下實際場所來靈活應用通知欄。比如長文字,打圖片、回覆信息、或者跳轉等。下面一起來學習。

3.1 優先級

優先級在 7.1 及以下有用,8.0 則使用 channel 來設置。
通知欄是可以設置優先級的,它有5個常亮可以選

  • PRIORITY_DEFAULT 默認優先級
  • PRIORITY_MIN 優先級最低,某個特定場合才顯示
  • PRIORITY_LOW 優先級較低,系統可能將這類通知縮小,或者改變它的顯示位置,比如靠後的位置
  • PRIORITY_HIGH 表示較高程度,系統可能對它進行方法,或者改變位置,比如靠前的位置
  • PRIORITY_MAX 優先級最高,這類通知會讓用戶立刻看到

比如,我們設置了 PRIORITY_MAX ,直接回顯示出通知欄的效果:
在這裏插入圖片描述

3.2 setStyle 展開式通知

很多時候,我們想顯示一段比較長的文字,或者一個比較大的圖片,使用默認的 setContentText 或者 setLargeIcon 是不行的,但是可以使用 setStyle ,setStyle 可以讓通知欄變大來顯示通知。

3.2.1 長文字

比如,顯示一段長文字:

.setStyle(new NotificationCompat.BigTextStyle().bigText("我是內容,我是demo\n我不是測試\n 我是長文字啊"))

效果如下:
在這裏插入圖片描述

3.2.2 大圖片

設置一張圖片:

  .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.update_app_top_bg))
               .setStyle(new NotificationCompat.BigPictureStyle()
                       .bigPicture(BitmapFactory.decodeResource(getResources(),
                       R.mipmap.update_app_top_bg)).bigLargeIcon(null)
               )

在這裏插入圖片描述

3.3 添加按鈕

一個通知最多可以提供三個操作按鈕,然該用戶可以快速響應,比如暫停,上一曲下一曲這些常用的按鈕,這裏,可以通過 addAction 去編寫,並把 PendingIntent 關聯進去,比如廣播:

mBuilder = new NotificationCompat.Builder(this)
     ......
        .addAction(R.mipmap.enter,"上一曲",pi)
        .addAction(R.mipmap.enter,"開始",pi)
        .addAction(R.mipmap.enter,"下一曲",pi);

效果如下:
在這裏插入圖片描述

3.4 添加回復操作

google 在 Android 7.0 (API 24) 中引入允許用戶直接回復的的組件,使用 RemoeInput 設置好key,並把它交給 action,即可實現。先看效果
在這裏插入圖片描述
首先,創建 RemoteInput.Builder() 的實例,並設置好 key 值,這個後面在 intent 會拿到。
然後,創建 PendingIntent,爲了方便實驗,添加一個廣播
最後,創建 Action,把 remoteInput 和 pendingIntent 穿進去,代碼如下:

 private NotificationCompat.Action getRemoveAction(){
     //添加一個回覆組件,
     RemoteInput remoteInput = new RemoteInput.Builder(REPLY_KEY)
             .build();

     //添加一個 pendingIntent 的廣播
     PendingIntent replyPi = PendingIntent.getBroadcast(this,2,
             new Intent("com.zhengsr.test"),PendingIntent.FLAG_UPDATE_CURRENT);

     //構建 action
     NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.mipmap.enter,
             "回覆",replyPi).addRemoteInput(remoteInput).build();

     return action;

 }

然後直接添加 action 即可:

        mBuilder = new NotificationCompat.Builder(this)
   				....
                .addAction(getRemoveAction())
            ;

3.4.1 拿到回覆內容

如果想要拿到用戶的輸入內容,則可以調用 RemoteInput.getResultsFromIntent(intent) ,即可拿到 Bundle 並拿到數據,如:

    class  MyBroadcastReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            Bundle bundle = RemoteInput.getResultsFromIntent(intent);
            if (bundle != null) {
                String replay = bundle.getString(REPLY_KEY);
                Log.d(TAG, "zsr onReceive: "+replay);
            }
        }
    }

在這裏插入圖片描述
同樣,也可以使用 NotificationCompat.MessagingStyle 去專門傳遞消息。具體參考官方資料。

3.5 顯示進度條

通知欄還可以顯示進度條,在 builder 中使用 setProgress。
在這裏插入圖片描述

setProgress(int max, int progress, boolean indeterminate)

參數都能看得明白。比如,當我們開始的進度條,可以設置爲:

setProgress(100,0,false)

更新的話,直接改變 progress 即可,如果想要取消,則 setProgress(0,0,false)就可

3.6 顯示緊急通知

在某些情況下,就算屏幕鎖屏了,一些通知還是要顯示的,比如電話,鬧鐘等。當然,通知欄也支持,根據設備的情況,會分兩種情況

  • 設備鎖定 : 如果設備鎖定了,則顯示全屏的 Acitivyt,直接覆蓋全屏
  • 設備爲鎖定: 則還是以通知欄的形式出現

可以通過設置 setFullScreenIntent(PendingIntent intent ,boolean highPriority) 來設置,如:

        mBuilder = new NotificationCompat.Builder(this)
                .setContentTitle("緊急通知")
                .setContentText("這是一條緊急通知")
                .setWhen(System.currentTimeMillis())
                ..
                .setFullScreenIntent(pi,true)

其中 pi 爲你要跳轉的 PendingIntent。除了默認的情況,還可以通過設置 setVisibility(int visibility) 來設置鎖屏屏幕的範圍,共有三種選擇:

  • VISIBILITY_PUBLIC 顯示通知的完整內容。
  • VISIBILITY_SECRET 不在鎖定屏幕上顯示該通知的任何部分。
  • VISIBILITY_PRIVATE 顯示基本信息,例如通知圖標和內容標題,但隱藏通知的完整內容。你如,顯示"您有三條新短信",但是發件人和內容不可見。

四、自定義佈局

一般情況下,系統的通知,並不能滿足我們的需求,且爲了保證每個版本的樣式統一。都會採用自定義佈局的形式。
需要注意的是。在創建自定義佈局的時候,我們需要提供兩個 layout,一個收起的視圖,它的高度上限爲 64dp。一個是展開之後,它的上限爲 256dp

4.1 爲內容區域創建自定義佈局

一般的自定義佈局中,我們可以藉助通用模板去構建一個基本佈局,即保留時間戳,通知圖標等裝飾,而自定義由標題和文本內容的區域。
這個時候,可以使用 NotificationCompat.DecoratedCustomViewStyle 設置到 style 中,一般步驟如下:

  1. 構建基本通知,使用NotificationCompat.Builder
  2. 調用 setStyle().想其傳遞 NotificationCompat.DecoratedCustomViewStyle 實例
  3. 將其自定義佈局擴展爲 RemoveteViews 實例
  4. 調用 setCustomContentView 設置收起的通知佈局
  5. 調用 setCustomBigContentView 設置擴展的通知佈局

如果爲多媒體播放控件創建自定義通知。可以使用NotificationCompat.DecoratedMediaCustomViewStyle 類

例如:

RemoteViews cusRemoveView = new RemoteViews(getPackageName(),R.layout.cus_notify_small);
     RemoteViews cusRemoveExpandView = new RemoteViews(getPackageName(),R.layout.cus_notify_large);

     mBuilder = new NotificationCompat.Builder(this)
             .setWhen(System.currentTimeMillis())
             .setSmallIcon(R.mipmap.ic_launcher)
             .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
             .setCustomContentView(cusRemoveView)
             .setCustomBigContentView(cusRemoveExpandView);

其中,當我們在自定義佈局時,通知的背景顏色可能因爲版本而異,如果要跟隨系統,在設置 TextView 控件時,可以使用 TextAppearance_Compat_Notification 樣式,比如標題的TextAppearance_Compat_Notification_Title。 這樣就能保證在不同版本中,textview 始終是正常顯示的。比如 R.layout_cus_notify_small:

注意,目前layout只支持 LinearLayout、FrameLayout、RelativeLayout三種基本佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="64dp"
    android:orientation="vertical"
    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/TextAppearance.Compat.Notification.Title"
        android:text="我是標題"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/TextAppearance.Compat.Notification.Info"
        android:text="我是內容"/>


</LinearLayout>

而,R.layout_cus_notify_large 中,給其中一個 TextView設置紅色,不設置 style,看看效果:
在這裏插入圖片描述
在這裏插入圖片描述
避免在 RemoteViews 上設置背景顏色,可能會導致文辦顏色無法讀取的問題

4.2 創建完全的自定義通知背景

如果你不想用系統的時間戳,通知圖標等。可以去掉 setStyle(),只添加 setCustomContentView 和 setCustomBigContentView 即可。
在這裏插入圖片描述
在這裏插入圖片描述

要支持低於 Android 4.1(API 級別 16)的 Android 版本,您還應調用 setContent(),向其傳遞同一 RemoteViews 對象。

如需獲取更多使用通知的示例代碼,請參閱 Android 通知示例

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章