Android10.0通知Notification的使用這一篇就夠了

前言

最近一段時間寫的都是android源碼的文章,前幾天在公司作了一個需求是關於前臺服務的,在寫前臺服務的時候深刻使用到了通知,今天就先寫一篇文章總結一下通知的相關內容,後面有時間了在介紹一下前臺服務的相關內容。java

通知概述

本篇文章主要介紹通知的如下知識點:android

  1. 不一樣android版本上通知功能
  2. 通知的結構
  3. 建立通知
  4. 通知的操做
  5. 從通知啓動 Activity
  6. 展開式通知
  7. 通知渠道
  8. 通知的級別
  9. 自定義通知

上面的這麼多內容基本覆蓋了通知百分之八十的知識點,瞭解這些足夠平常通知的使用了。程序員

不一樣android版本上通知功能

Android 4.1(API 級別 16)api

  • 引入了展開式通知模板(稱爲通知樣式),能夠提供較大的通知內容區域來顯示信息。用戶可使用單指向上/向下滑動的手勢來展開通知。

Android 5.0(API 級別 21)微信

  • 引入了鎖定屏幕和浮動通知。
  • 向 API 集添加了通知是否在鎖定屏幕上顯示的方法 (setVisibility()),以及指定通知文本的「公開」版本的方法。
  • 添加了 setPriority() 方法,告知系統該通知應具備的「干擾性」(例如,將其設置爲「高」,可以使該通知以浮動通知的形式顯示)。

Android 7.0(API 級別 24)app

  • 用戶可使用內聯回覆直接在通知內回覆(用戶能夠輸入文本,而後將其發送給通知的父級應用)。

Android 8.0(API 級別 26)佈局

  • 如今必須將單個通知放入特定渠道中。
  • 用戶如今能夠按渠道關閉通知,而不是關閉應用的全部通知。
  • 包含活動通知的應用會在應用圖標上方顯示通知「標誌」。(小圓點或數字)
  • 用戶能夠暫停抽屜式通知欄中的通知。您能夠爲通知設置自動超時。
  • 能夠設置通知的背景顏色。

通知的結構

在這裏插入圖片描述

  1. 小圖標:此爲必要圖標,經過 setSmallIcon() 設置。
  2. 應用名稱:此由系統提供。
  3. 時間戳:此由系統提供,不過您能夠經過 setWhen() 進行替換,或使用 setShowWhen(false) 將其隱藏。
  4. 大圖標:此爲可選圖標(一般僅用於聯繫人照片;請勿將其用於應用圖標),經過 setLargeIcon() 設置。
  5. 標題:此爲可選內容,經過 setContentTitle() 設置。
  6. 文本:此爲可選內容,經過 setContentText() 設置。

建立通知

爲了在不一樣的android版本中兼容通知,android在support-compat包中提供了NotificationCompat和NotificationManagerCompat來幫助咱們更加方便的使用通知。
因爲咱們是在android10上使用通知,因此咱們必須兼容全部的android版本,那麼咱們建立通知的步驟就以下:
測試

  1. 建立渠道:在android8.0以上須要建立,如下不用建立
  2. 設置點擊事件
  3. 構造Notification對象並顯示通知
    在這裏插入圖片描述

1.建立渠道

因爲咱們只須要在android8.0以上建立,因此在代碼中進行判斷:gradle

private String createNotificationChannel(String channelID, String channelNAME, int level) {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            NotificationChannel channel = new NotificationChannel(channelID, channelNAME, level);
            manager.createNotificationChannel(channel);
            return channelID;
        } else {
            return null;
        }
    }

這裏封裝了一個方法,若是api大於android8.0就建立渠道返回渠道id,不然返回空。這裏我只傳了三個必要的參數,還有其餘的設置在通知渠道那一節單獨介紹。動畫

2.設置點擊事件

每一個通知都應該對點按操做作出響應,一般是在應用中打開對應於該通知的 Activity。爲此,您必須指定經過 PendingIntent 對象定義的內容 Intent,並將其傳遞給 setContentIntent()。

Intent intent = new Intent(this, Main2Activity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

3.構造Notification對象並顯示通知

Intent intent = new Intent(this, Main2Activity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
        String channelId = createNotificationChannel("my_channel_ID", "my_channel_NAME", NotificationManager.IMPORTANCE_HIGH);
        NotificationCompat.Builder notification = new NotificationCompat.Builder(this, channelId)
                .setContentTitle("通知")
                .setContentText("收到一條消息")
                .setContentIntent(pendingIntent)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setAutoCancel(true);
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
        notificationManager.notify(100, notification.build());

這裏經過NotificationCompat.Builder構造通知須要的信息,注意這裏調用了setAutoCancel(true),它會在用戶點按通知後自動移除通知,若是不調用或者傳參數爲false就會在點擊後依然存在,可是若是用戶清除下拉框的全部消息會把這樣的通知清理掉。若是不想用戶把他清理掉呢?能夠調用setOngoing(true)方法,這樣除非你的app死掉或者在代碼中取消,不然他都不會消失。

通知的操做

1.添加操做按鈕

一個通知最多能夠提供三個操做按鈕,讓用戶能夠快速響應,例如暫停提醒,甚或回覆短信。但這些操做按鈕不該該重複用戶在點按通知時執行的操做。

要添加操做按鈕,請將 PendingIntent 傳遞給 addAction() 方法。這就像是設置通知的默認點按操做,不一樣的是不會啓動 Activity,而是能夠完成各類其餘任務,例如啓動在後臺執行做業的 BroadcastReceiver,這樣該操做就不會干擾已經打開的應用。

Intent snoozeIntent = new Intent(this, MyBroadcastReceiver.class);
    snoozeIntent.setAction(ACTION_SNOOZE);
    snoozeIntent.putExtra(EXTRA_NOTIFICATION_ID, 0);
    PendingIntent snoozePendingIntent =
            PendingIntent.getBroadcast(this, 0, snoozeIntent, 0);
    NotificationCompat.Builder notification = new NotificationCompat.Builder(this, channelId)
                .setContentTitle("通知")
                .setContentText("收到一條消息")
                .setContentIntent(pendingIntent)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .addAction(R.drawable.icon, "按鈕", snoozeIntent )
                .setAutoCancel(true);

在這裏插入圖片描述

2.添加進度條

通知能夠包含動畫形式的進度指示器,向用戶顯示正在進行的操做狀態。
經過setProgress(max, progress, false)方法來設置和更新進度

  • 第一個參數進度的最大值
  • 第二個參數是當前進度值
  • 第三個參數是是不是肯定性進度條,具體意思看我下面的例子
NotificationCompat.Builder notification = new NotificationCompat.Builder(this, channelId)
                .setContentTitle("通知")
                .setContentText("收到一條消息")
                .setContentIntent(pendingIntent)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .addAction(R.drawable.icon, "按鈕", pendingIntent)
                .setAutoCancel(true);
        // Issue the initial notification with zero progress
        int PROGRESS_MAX = 100;
        int PROGRESS_CURRENT = 0;
        notification.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
        notificationManager.notify(100, notification.build());

上面對進度條進行了初始化,而後不斷調用下面的方法進行更新:

//更新
        notification.setContentText("Download complete")
                .setProgress(0,0,false);
        notificationManager.notify(100, notification.build());

在這裏插入圖片描述
上面的例子是一個肯定性的進度條,這個怎麼理解呢,我給大家看一個不肯定性的進度條大家就知道了,將第三個參數設置爲true,效果以下:
在這裏插入圖片描述

3.設置鎖定屏幕公開範圍

要控制鎖定屏幕中通知的可見詳情級別,請調用 setVisibility() 並指定如下值之一:

  • VISIBILITY_PUBLIC 顯示通知的完整內容。
  • VISIBILITY_SECRET 不在鎖定屏幕上顯示該通知的任何部分。
  • VISIBILITY_PRIVATE 顯示基本信息,例如通知圖標和內容標題,但隱藏通知的完整內容。

4.更新通知

要在發出此通知後對其進行更新,請再次調用 NotificationManagerCompat.notify(),並將以前使用的具備同一 ID 的通知傳遞給該方法。若是以前的通知已被關閉,則系統會建立一個新通知。
您能夠選擇性調用 setOnlyAlertOnce(),這樣通知只會在通知首次出現時打斷用戶(經過聲音、振動或視覺提示),而以後更新則不會再打斷用戶。

5.移除通知

除非發生如下狀況之一,不然通知仍然可見:

  • 用戶關閉通知。
  • 用戶點擊通知,且您在建立通知時調用了 setAutoCancel()。
  • 您針對特定的通知 ID 調用了 cancel()。此方法還會刪除當前通知。
  • 您調用了 cancelAll() 方法,該方法將移除以前發出的全部通知。
  • 若是您在建立通知時使用 setTimeoutAfter() 設置了超時,系統會在指定持續時間事後取消通知。若是須要,您能夠在指定的超時持續時間過去以前取消通知。

從通知啓動 Activity

通知的點擊操做是由PendingIntent實現的,經過PendingIntent能夠跳轉Activity,開啓服務,發送廣播,咱們着重來說一下跳轉Activity的操做,跳轉分爲兩種類型,一是這個Activity單獨在一個任務棧中,點擊返回就直接返回到桌面;二是這個Activity擁有一個定義好的返回棧,點擊返回會根據任務棧順序進行回退。

1.單獨任務棧

因爲從通知啓動的「特殊 Activity」不須要返回堆棧,所以您能夠經過調用 getActivity() 來建立 PendingIntent,但您還應確保在清單中定義了相應的任務選項。
在清單中,將如下屬性添加到 元素中。

android:taskAffinity=""

與您將在代碼中使用的 FLAG_ACTIVITY_NEW_TASK 標記結合使用,將此屬性設置爲空能夠確保這類 Activity 不會進入應用的默認任務。具備應用默認類似性的任何現有任務都不會受到影響。

android:excludeFromRecents=「true」

用於從「最近」中排除新任務,以避免用戶意外返回它。

<activity
        android:name=".ResultActivity"
        android:launchMode="singleTask"
        android:taskAffinity=""
        android:excludeFromRecents="true">
    </activity>
Intent intent = new Intent(this, Main2Activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

2.完整任務棧

定義應用的 Activity 層次結構
經過嚮應用清單文件中的每一個 元素添加 android:parentActivityName 屬性,定義 Activity 的天然層次結構。例如:

<activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
  
    <activity
        android:name=".ResultActivity"
        android:parentActivityName=".MainActivity" />
        ...
    </activity>

構建包含返回堆棧的 PendingIntent
要啓動包含 Activity 的返回堆棧的 Activity,您須要建立 TaskStackBuilder 的實例並調用 addNextIntentWithParentStack(),向其傳遞您要啓動的 Activity 的 Intent。

只要您爲每一個 Activity 定義了父 Activity(如上文所述),就能夠調用 getPendingIntent() 來接收包含整個返回堆棧的 PendingIntent。

Intent resultIntent = new Intent(this, ResultActivity.class);
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    stackBuilder.addNextIntentWithParentStack(resultIntent);
    PendingIntent resultPendingIntent =
            stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

若有必要,您能夠經過調用 TaskStackBuilder.editIntentAt() 向堆棧中的 Intent 對象添加參數。有時候須要這樣作,以確保返回堆棧中的 Activity 在用戶向上導航到它時顯示有意義的數據。

展開式通知

基本通知一般包括標題、一行文本,以及用戶能夠執行的一項或多項響應操做。要提供更多信息,您還能夠應用本頁介紹的多個通知模板之一來建立大型展開式通知。

1.添加大圖片

在這裏插入圖片描述

NotificationCompat.Builder notification = new NotificationCompat.Builder(this, channelId)
                .setContentTitle("通知")
                .setContentText("收到一條消息")
                .setContentIntent(pendingIntent)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setStyle(new NotificationCompat.BigPictureStyle()
                        .bigPicture(BitmapFactory.decodeResource(getResources(), R.drawable.image)))
                .setAutoCancel(true);

這裏經過setStyle來使用系統提供的模版建立大圖片通知,要使該圖片僅在通知收起時顯示爲縮略圖,請調用 setLargeIcon() 並傳入該圖片,同時調用 BigPictureStyle.bigLargeIcon() 並傳入 null,這樣大圖標就會在通知展開時消失:
在這裏插入圖片描述

NotificationCompat.Builder notification = new NotificationCompat.Builder(this, channelId)
                .setContentTitle("通知")
                .setContentText("收到一條消息")
                .setContentIntent(pendingIntent)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.image))
                .setStyle(new NotificationCompat.BigPictureStyle()
                        .bigPicture(BitmapFactory.decodeResource(getResources(), R.drawable.image))
                        .bigLargeIcon(null))
                .setAutoCancel(true);

2.添加大文本

應用 NotificationCompat.BigTextStyle,以在通知的展開內容區域顯示文本:

NotificationCompat.Builder notification = new NotificationCompat.Builder(this, channelId)
                .setContentTitle("通知")
                .setContentText("收到一條消息")
                .setContentIntent(pendingIntent)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setStyle(new NotificationCompat.BigTextStyle()
                        .bigText("不管是否意識到 Gradle 的存在,每位 Android 程序員都會直接或間接的與 Gradle 打交道。每當經過 Android Studio 新建一個工程時,AS 都會自動建立一個通用的目錄結構,而後就能夠進行開發,在 app 的 build.gradle 中添加一些依賴,點擊右上角的 Sync Now"))
                .setAutoCancel(true);

在這裏插入圖片描述

3.收件箱樣式的通知

若是您想要添加多個簡短的摘要行(例如收到的電子郵件的片斷),可對通知應用 NotificationCompat.InboxStyle。這樣,您就能夠添加多條內容文本,而且每條文本均截斷爲一行,而不是顯示爲 NotificationCompat.BigTextStyle 提供的一行連續文本。

要添加新行,最多可調用 addLine() 6 次。若是添加的行超過 6 行,則僅顯示前 6 行。

NotificationCompat.Builder notification = new NotificationCompat.Builder(this, channelId)
                .setContentTitle("通知")
                .setContentText("收到一條消息")
                .setContentIntent(pendingIntent)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setStyle(new NotificationCompat.InboxStyle()
                        .addLine("不管是否意識到 Gradle 的存在,每位 Android 程序員都會直接或間接的與 Gradle 打交道。每當經過 Android Studio 新建一個工程時")
                        .addLine("AS 都會自動建立一個通用的目錄結構,而後就能夠進行開發,在 app 的 build.gradle 中添加一些依賴,點擊右上角的 Sync Now")
                        .addLine("編寫代碼,點擊綠色小箭頭 Run 運行代碼,一切都這麼美好"))
                .setAutoCancel(true);

在這裏插入圖片描述

通知渠道

從 Android 8.0(API 級別 26)開始,全部的通知都必須分配到相應的渠道。對於每一個渠道,您能夠設置應用於其中的全部通知的視覺和聽覺行爲(也就是通知的級別)。而後,用戶能夠更改這些設置,並肯定您應用中的哪些通知渠道應具備干擾性或應該可見。我認爲添加這個功能主要是爲了讓用戶可以更透明的管理通知。(百分之九十九的人都不知道,知道也不會去看,唉!!!)
咱們來看一下酷狗音樂的通知渠道狀況(不一樣的手機廠商系統不一樣顯示會有出入):
在這裏插入圖片描述
能夠看到酷狗總共有5個通知渠道,咱們看一下酷狗推送消息這個渠道:
在這裏插入圖片描述
渠道詳情裏有重要程度(也就是通知的級別)、提示音、震動等設置,這些都是咱們能夠在代碼中設置的,固然用戶也能夠主動的修改他們。




前面已經講了通知渠道的建立,下面來看一下建立的時候能夠作哪些額外操做:

NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            NotificationChannel channel = new NotificationChannel(channelID, channelNAME, level);
            //設置提示音
            channel.setSound();
            //開啓指示燈
            channel.enableLights();
            //開啓震動
            channel.enableVibration();
            //設置鎖屏展現
            channel.setLockscreenVisibility();
            //設置渠道描述
            channel.setDescription();
            manager.createNotificationChannel(channel);

這裏只列舉了一部分,在Android 7.1(API 級別 25)如下這些都是直接在NotificationCompat.Builder中設置的,只是在 Android 8.0(API 級別 26)上把這些功能拆分到了渠道設置上。
在建立了渠道以後就沒法更改這些設置了。 這裏須要單獨講一下,不管咱們調用多少次建立渠道的方法,對於同一個渠道ID只有第一次建立是有效的,由於建立的時候會去判斷是否存在這個渠道,若是存在是不會從新建立的。其實這麼說也不徹底對,有興趣的能夠看一下我在文章最後作的一個分析。

雖然在建立渠道以後咱們不能再去修改他,可是咱們能夠獲取渠道設置,由於渠道設置對用戶是透明的,用戶能夠去隨意的設置他,因此咱們能夠在獲取渠道設置以後引導用戶設置咱們想要的行爲。好比我是微信的開發者,微信的通知被用戶手動關掉了,我在檢測到通知被關以後就會去告訴用戶這個通知很重要不能關掉,而後引導用戶跳到那個頁面進行設置。主要的步驟以下:

1.讀取通知渠道設置

  1. 經過調用 getNotificationChannel() 或 getNotificationChannels() 獲取 NotificationChannel 對象。
  2. 查詢特定的渠道設置,例如 getVibrationPattern()、getSound() 和 getImportance()。

2.打開通知渠道設置

Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
    intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
    intent.putExtra(Settings.EXTRA_CHANNEL_ID, myNotificationChannel.getId());
    startActivity(intent);

注意,該 intent 須要兩個提取項,分別用於指定您應用的軟件包名稱(也稱爲應用 ID)和要修改的渠道。

其實還有一個渠道分組沒講,可是用的不多就不說了。

通知的級別

通知的級別主要體如今通知的展現方式上,有的通知只在狀態欄如今一個圖標,有的通知卻會彈出來懸浮在屏幕上(例如微信),這就是經過設置通知的級別實現的。在 Android 7.1(API 級別 25)及更低版本上是經過priority這個屬性設置,在 Android 8.0(API 級別 26)及更高版本上是經過importance屬性設置。

用戶可見的重要性級別 重要性(Android 8.0 及更高版本) 優先級(Android 7.1 及更低版本)
緊急
發出提示音,並以浮動通知的形式顯示
IMPORTANCE_HIGH PRIORITY_HIGH 或 PRIORITY_MAX

發出提示音
IMPORTANCE_DEFAULT PRIORITY_DEFAULT

不發出提示音
IMPORTANCE_LOW PRIORITY_LOW

不發出提示音,且不會在狀態欄中顯示
IMPORTANCE_MIN PRIORITY_MIN

1.Android 7.1(API 級別 25)及更低版本
經過setPriority(NotificationCompat.PRIORITY_LOW)方法能夠直接設置。

2.Android 8.0(API 級別 26)及更高版本
在Android8.0中這一功能須要在通知渠道中設置

NotificationChannel channel = new NotificationChannel(channelID, channelNAME, NotificationManager.IMPORTANCE_LOW);

最後一個參數就是通知的級別,除了在建立渠道的時候設置,在渠道建立完成以後也能夠設置

NotificationChannel channel = new NotificationChannel(channelID, channelNAME, NotificationManager.IMPORTANCE_LOW);
channel.setImportance(NotificationManager.IMPORTANCE_LOW);

兼容
對比上面兩個設置方法,咱們發現把這兩個設置都加上,而且設置相同的等級就能夠兼容全部的版本。

自定義通知

使用自定義通知佈局時,請特別注意確保您的自定義佈局適用於不一樣的設備屏幕方向和分辨率。雖然對於全部界面佈局,此建議都適用,但它對通知佈局而言尤其重要,由於抽屜式通知欄中的空間很是有限。自定義通知佈局的可用高度取決於通知視圖。一般狀況下,收起後的視圖佈局的高度上限爲 64 dp,展開後的視圖佈局的高度上限爲 256 dp。
自定義通知有兩種,一種是爲內容區域建立自定義佈局,另外一種是建立徹底自定義的通知佈局。

1.爲內容區域建立自定義佈局

若是您須要自定義內容區域的佈局,能夠將 NotificationCompat.DecoratedCustomViewStyle 應用到您的通知。藉助此 API,您能夠爲一般由標題和文本內容佔據的內容區域提供自定義佈局,同時仍對通知圖標、時間戳、子文本和操做按鈕使用系統裝飾。
自定義佈局的使用方式以下:

  1. 構建基本通知(使用 NotificationCompat.Builder)
  2. 調用 setStyle(),向其傳遞一個 NotificationCompat.DecoratedMediaCustomViewStyle 實例。
  3. 將自定義佈局擴充爲 RemoteViews 的實例。
  4. 調用 setCustomContentView() 以設置收起後通知的佈局。您還能夠選擇調用 setCustomBigContentView() 來爲展開後通知設置不一樣的佈局。
String channelId = createNotificationChannel("my_channel_ID", "my_channel_NAME", NotificationManager.IMPORTANCE_MAX);
        RemoteViews notificationLayout = new RemoteViews(getPackageName(), R.layout.custom_notification_item);
        RemoteViews notificationLayoutExpanded = new RemoteViews(getPackageName(), R.layout.custom_notification_large);
        NotificationCompat.Builder notification = new NotificationCompat.Builder(this, channelId)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
                .setCustomContentView(notificationLayout)
                .setCustomBigContentView(notificationLayoutExpanded)
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setAutoCancel(true);
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
        notificationManager.notify(100, notification.build());

在這裏插入圖片描述
在這裏插入圖片描述

2.建立徹底自定義的通知佈局

若是您不但願使用標準通知圖標和標題裝飾通知,請按照上述步驟使用 setCustomBigContentView(),但不要調用 setStyle()。
要支持低於 Android 4.1(API 級別 16)的 Android 版本,您還應調用 setContent(),向其傳遞同一 RemoteViews 對象。

總結

在測試建立了渠道以後還能不能修改的時候我發現有些信息是能修改的,可是大部分是不能的,因而我去看了一下建立渠道的源碼,結果發現前面說的渠道在建立以後就不能進行修改了其實不徹底對,正確的是大部分主要的都不能修改了,有一些次要的信息仍是能修改的,看一下建立渠道時發現渠道已經存在處理的代碼:

NotificationChannel existing = r.channels.get(channel.getId());
            // Keep most of the existing settings
            if (existing != null && fromTargetApp) {
                if (existing.isDeleted()) {
                    existing.setDeleted(false);
                    needsPolicyFileChange = true;

                    // log a resurrected channel as if it's new again
                    MetricsLogger.action(getChannelLog(channel, pkg).setType(
                            com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
                }
                //發現渠道名字不一樣會更新
                if (!Objects.equals(channel.getName().toString(), existing.getName().toString())) {
                    existing.setName(channel.getName().toString());
                    needsPolicyFileChange = true;
                }
                //發現渠道描述不一樣會更新
                if (!Objects.equals(channel.getDescription(), existing.getDescription())) {
                    existing.setDescription(channel.getDescription());
                    needsPolicyFileChange = true;
                }
                //我也不知道是什麼
                if (channel.isBlockableSystem() != existing.isBlockableSystem()) {
                    existing.setBlockableSystem(channel.isBlockableSystem());
                    needsPolicyFileChange = true;
                }
                //發現組不一樣會更新
                if (channel.getGroup() != null && existing.getGroup() == null) {
                    existing.setGroup(channel.getGroup());
                    needsPolicyFileChange = true;
                }

                // Apps are allowed to downgrade channel importance if the user has not changed any
                // fields on this channel yet.
                //當用戶沒有手動修改過渠道的信息,而且要更新的通知等級小於現有的等級能夠更新
                final int previousExistingImportance = existing.getImportance();
                if (existing.getUserLockedFields() == 0 &&
                        channel.getImportance() < existing.getImportance()) {
                    existing.setImportance(channel.getImportance());
                    needsPolicyFileChange = true;
                }

                // system apps and dnd access apps can bypass dnd if the user hasn't changed any
                // fields on the channel yet
                if (existing.getUserLockedFields() == 0 && hasDndAccess) {
                    boolean bypassDnd = channel.canBypassDnd();
                    if (bypassDnd != existing.canBypassDnd()) {
                        existing.setBypassDnd(bypassDnd);
                        needsPolicyFileChange = true;

                        if (bypassDnd != mAreChannelsBypassingDnd
                                || previousExistingImportance != existing.getImportance()) {
                            updateChannelsBypassingDnd(mContext.getUserId());
                        }
                    }
                }

                updateConfig();
                return needsPolicyFileChange;
            }

經過代碼發現setName、setDescription、setGroup是能夠被修改的,setImportance也能修改可是必須當用戶沒有手動修改過渠道的信息,而且要修改的通知等級小於現有的等級能夠修改。

相關文章
相關標籤/搜索