1. 程式人生 > >Android Notification(Android 8.0)

Android Notification(Android 8.0)

概述:

Android O(也就是SDK26版本) 引入了 通知渠道(Notification Channels)以提供統一的系統來幫助使用者管理通知,如果是針對 android O 為目標平臺時,必須實現一個或者多個通知渠道,以向用戶顯示通知。若並不以 Android O 為目標平臺,當應用執行在 android O 裝置上時,其行為將與執行在 Android 7.0 上時相同。
Android O 的使用者可以使用一致的系統 UI 管理大多數與通知有關的設定。所有釋出至通知渠道的通知都具有相同的行為。當用戶修改任何下列特性的行為時,修改將作用於通知渠道:

  • 重要性
  • 聲音
  • 振動
  • 在鎖屏上顯示
  • 替換免打擾模式

一、Android系統通知基本操作

谷歌原生8.0系統顯示如下:
這裡寫圖片描述
如果向左滑動通知,則會出現兩個開關,一個是設定該應用的具體通知規範,另一個可以設定讓該應用的通知推遲一段時間推送。
這裡寫圖片描述

設定具體通知規範:
這裡寫圖片描述
這裡寫圖片描述

設定通知休眠時間:
這裡寫圖片描述

1.1 通知優先順序和重要性

Android O 棄用了為單個通知設定優先順序的功能。建立通知渠道時可以設定建議重要性級別。為通知渠道指定的重要性級別適用於釋出至該渠道的所有通知訊息。可以配置五個級別中的一個,這些級別代表著通知渠道可以打斷使用者的程度,範圍是 IMPORTANCE_NONE(0)至 IMPORTANCE_HIGH(4)。預設重要性級別為 3:在所有位置顯示,發出提示音,但不會對使用者產生視覺干擾。建立通知渠道後,只有系統可以修改其重要性。使用者可以在設定中找到。
這裡寫圖片描述


這裡寫圖片描述
這裡寫圖片描述

1.2 建立通知渠道

以下步驟建立通知渠道::
1. 構建一個在軟體包內具有唯一 ID 的通知渠道物件。
2. 為該通知渠道物件配置所需的任何初始設定(例如提示音以及對使用者可見的可選說明)。
3. 將通知渠道物件提交到通知管理器。
注意:如果試圖使用初始值建立的通知渠道已存在,不會執行任何操作,因此啟動應用時可以放心地執行以上步驟序列。以下示例程式碼演示的是如何建立具有低重要性級別和自定義振動模式的通知渠道。

    /**
     * 建立通知渠道
     * @param channel_id 渠道id
     * @param
channel_name 渠道名稱 * @param channel_desc 渠道描述 * @param importance 渠道優先順序 * @param group_id 渠道組,若沒有渠道組,則傳null */
@RequiresApi(api = 26) private void createNotificationChannel(String channel_id, String channel_name,String channel_desc,int importance,String group_id){ NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); //配置通知渠道id,渠道名稱(使用者可以看到),渠道優先順序 NotificationChannel mChannel = new NotificationChannel(channel_id, channel_name,importance); //配置通知渠道的描述 mChannel.setDescription(channel_desc); //配置通知出現時的閃燈(如果 android 裝置支援的話) mChannel.enableLights(true); mChannel.setLightColor(Color.RED); //配置通知出現時的震動(如果 android 裝置支援的話) mChannel.enableVibration(true); mChannel.setVibrationPattern(new long[]{100, 200, 100, 200}); //配置渠道組 if(group_id!=null){ mChannel.setGroup(group_id);//設定渠道組 } //在NotificationManager中建立該通知渠道 manager.createNotificationChannel(mChannel); }

可以通過呼叫 createNotificationChannels(List < NotificationChannel > channels)
一次性建立多個通知渠道。

1.3 建立通知渠道組

如果應用支援多個帳戶,則可為每個帳戶建立一個通知渠道組。通知渠道組用於對一款應用內的多個同名通知渠道進行管理。例如,一款社交網路應用可能提供面向個人帳戶以及企業帳戶的支援。在此情境下,每個帳戶可能都需要多個功能和名稱相同的通知渠道。
一個包括 2 個通知渠道的個人帳戶:
• 帖子新增評論的通知。
• 聯絡人推薦帖子的通知。
一個包括 2 個通知渠道的企業帳戶:
• 帖子新增評論的通知。
• 聯絡人推薦帖子的通知。
在本例中,將與每個使用者帳戶相關的通知渠道組織成專用組可確保使用者能在 Settings 中輕鬆地進行區分。每個通知渠道組都必須在軟體包內具有唯一 ID,並具有使用者可見的名稱。下面這段程式碼演示瞭如何建立兩個通知渠道組。

    // 通知渠道組的id.
    private String group_id = "my_group_01";
    //使用者可見的通知渠道組名稱
    private String group_name = "My Notification Group 01";
    private String group01_id = "my_group_02";
    //使用者可見的通知渠道組名稱
    private String group_name01 = "My Notification Group 02";

    @RequiresApi(api = 26)
    private void createNotificationChannelGroup() {
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.createNotificationChannelGroup(new NotificationChannelGroup(group_id, group_name));
        manager.createNotificationChannelGroup(new NotificationChannelGroup(group01_id, group_name01));
    }

新建渠道組後,便可呼叫 setGroup()將某個新渠道關聯到該組。注意,只能在將渠道提交給通知管理器之前修改通知渠道與組之間的關聯。

1.4 建立通知

要建立通知,請呼叫 Notification.Builder.build(),它返回的 Notification物件包含的指定值。要發出通知,請通過呼叫 manager.notify(id, notification),將 Notification物件傳遞給系統。
建立的通知Notification物件必須包含以下內容:

  • 小圖示,由 setSmallIcon()設定
  • 標題,由 setContentTitle()設定
  • 詳細文字,由 setContentText()設定
  • 有效的通知渠道 ID,由 setChannelId()設定

如果 應用是以 Android O 為目標平臺並且在不指定有效通知渠道的情況下發布通知,那麼通知將無法釋出,系統會記錄錯誤。

注:可以在 Android O 中啟用一個新設定,當針對 Android O 的應用試圖在沒有通知渠道的情況下發布時,以 toast 形式顯示螢幕警告。要為執行 Android O 的開發裝置啟用該設定,請轉到 Settings > Developer options,然後開啟 Show notification channel warnings。

1.5 向渠道釋出通知

下面這段程式碼說明如何向通知渠道釋出簡單通知。請注意,程式碼利用渠道的 ID 將通知與通知渠道關聯起來。

            createNotificationChannelGroup();//建立渠道組
            createNotificationChannel(CHANNEL_ID,CHANNEL_NAME,"渠道描述",NotificationManager.IMPORTANCE_LOW,group_id);
            notification = new Notification.Builder(getApplicationContext(), CHANNEL_ID)
                    .setContentTitle(Title)
                    .setContentText(Text)
                    .setWhen(System.currentTimeMillis())
                    .setSmallIcon(R.drawable.logo)
                    //.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.logo))
                    .setContentIntent(intent)
                    .setAutoCancel(true)
                    //.setColorized(true)//啟用通知的背景顏色
                    //.setColor(Color.RED)//設定通知的背景顏色
                    .build();
             manager.notify(id, notification);

注意:從Android 8.1(API級別27)開始,應用程式無法每秒發出超過一次的通知。如果應用在一秒鐘內釋出了多個通知,則它們都會按預期顯示,但每秒只有第一個通知發出聲音。

1.6 讀取通知渠道設定

使用者可以修改通知渠道的設定,包括振動和提示音等行為。開發者可以呼叫以下兩個方法來發現使用者對通知渠道應用的設定:

  • 要檢索單個通知渠道,可以呼叫 getNotificationChannel()。
  • 要檢索歸屬的應用的所有通知渠道,可以呼叫 getNotificationChannels()。

1.7 更新通知渠道設定

一旦建立了通知渠道,其設定和行為就由使用者掌控。可以再次呼叫 createNotificationChannel()以重新命名現有通知渠道,或更新其說明。以下示例程式碼說明如何通過建立啟動 Activity 的 Intent 將使用者重定向到通知渠道的設定。在本例中,Intent 要求提供擴充套件資料,包括通知渠道的 ID 和應用的軟體包名稱。

    /**
     * 跳轉到通知渠道設定
     * @param channel_id
     */
    @RequiresApi(api = 26)
    private void goNotifySetting(String channel_id) {
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        if (manager.getNotificationChannel(channel_id) == null) {
            Toast.makeText(this, "請先建立一條通知", Toast.LENGTH_SHORT).show();
            return;
        }

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

1.8 刪除通知渠道

可以通過呼叫 deleteNotificationChannel()
來刪除通知渠道。作為一個垃圾資訊預防機制,通知設定中將顯示已刪除渠道的數量。可以通過以下任一方法清除開發裝置上的測試渠道:重新安裝應用;清除與應用副本關聯的資料。以下示例程式碼演示瞭如何刪除通知渠道。

    /**
     * 根據id刪除指定通知渠道
     */
    @RequiresApi(api = 26)
    private void deleteNotificationChannel(String channel_id) {
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.deleteNotificationChannel(channel_id);
    }

1.9 設定啟用背景顏色:

您可以設定和啟用通知的背景顏色。只能在使用者必須一眼就能看到的持續任務的通知中使用此功能。例如,您可以為與駕車路線或正在進行的通話有關的通知設定背景顏色。您還可以使用 Notification.Builder.setColor() 設定所需的背景顏色。這樣做將允許您使用 Notification.Builder.setColorized() 啟用通知的背景顏色設定。

                    .setColorized(true)//啟用通知的背景顏色
                    .setColor(Color.RED)//設定通知的背景顏色

顯示效果:僅在原生android系統上有效果,在華為,小米手機沒有任何變化。
這裡寫圖片描述

二、通知進階

2.1 帶有操作按鈕的通知:

通知最多可以提供三個操作按鈕,允許使用者快速響應,例如暫停提醒或甚至回覆簡訊。
這裡寫圖片描述

    /**
     * 帶有操作按鈕的通知
     */
    @RequiresApi(api = 26)
    private void showOperateButtonNotification(){
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Notification notification;

        Intent intent=new Intent(this, MainActivity.class);
        intent.setAction(TEST_ACTION_01);
        intent.putExtra(EXTRA_NOTIFICATION_ID_01,NOTIFICATION_ID_01);
        PendingIntent pendingIntent=PendingIntent.getActivity(this,0,intent,0);

        createNotificationChannelGroup();//建立渠道組
        createNotificationChannel(CHANNEL_ID,CHANNEL_NAME,"渠道描述",NotificationManager.IMPORTANCE_HIGH,group_id);
        notification = new Notification.Builder(getApplicationContext(), CHANNEL_ID)
                .setContentTitle("通知測試")
                .setContentText("帶有操作按鈕的通知")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.drawable.logo)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.logo))
                //.setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .addAction(R.mipmap.ic_launcher,"確認",pendingIntent)
                .addAction(R.mipmap.ic_launcher,"取消",pendingIntent)
                .addAction(R.mipmap.ic_launcher,"忽略",pendingIntent)
                .build();
        manager.notify(NOTIFICATION_ID_01, notification);
    }

2.2 帶有確定進度條的通知

通知可以包括動畫進度指示器,向用戶顯示正在進行的操作的狀態。
如果可以隨時估計操作的完成程度,可以呼叫使用進度條的“確定”形式
setProgress(max, progress, false)。
第一個引數是“完整”值(例如100);
第二個是當前完成的數量,
最後一個false 表明這是一個確定的進度條。
更新進度值:

mNotificationBuilder03.setProgress(max, progress, false);
manager.notify(NOTIFICATION_ID_03, mNotificationBuilder03.build());

關閉進度條:

mNotificationBuilder03.setProgress(max, progress, false);
manager.notify(NOTIFICATION_ID_03, mNotificationBuilder03.build());

Demo程式碼:

    /**
     * 帶有確定進度條的通知
     */
    @RequiresApi(api = 26)
    private void showProgressNotification02(){
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        //建立並打包PendingIntent
        Intent intent=new Intent(this, MainActivity.class);
        intent.setAction(TEST_ACTION_03);
        intent.putExtra(EXTRA_NOTIFICATION_ID_03,NOTIFICATION_ID_03);
        PendingIntent pendingIntent=PendingIntent.getActivity(this,0,intent,0);

        createNotificationChannelGroup();//建立渠道組
        createNotificationChannel(CHANNEL_ID,CHANNEL_NAME,"渠道描述",NotificationManager.IMPORTANCE_HIGH,group_id);

        mNotificationBuilder03 = new Notification.Builder(getApplicationContext(), CHANNEL_ID)
                .setContentTitle("帶有進度條的通知")
                .setContentText("正在等待下載")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.drawable.logo)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.logo))
                .setContentIntent(pendingIntent)
                .setProgress(100,0,false)
                .setAutoCancel(true)
                .addAction(R.mipmap.ic_launcher,"關閉",pendingIntent);

        mNotificationManager.notify(NOTIFICATION_ID_03, mNotificationBuilder03.build());

        new Thread(new Runnable() {
            @Override
            public void run() {
                int i=0;
                while (i<100){
                    i++;
                    try {
                        sleep(50);
                        mNotificationBuilder03.setProgress(100,i,false);
                        mNotificationBuilder03.setContentText(String.format("已下載%d%%",i));
                        mNotificationManager.notify(NOTIFICATION_ID_03, mNotificationBuilder03.build());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                try {
                    //此處要間隔一段時間再去更新,間隔時間過短的話會導致後面的Notification更新失效
                    sleep(100);
                    mNotificationBuilder03.setProgress(0,0,false);
                    mNotificationBuilder03.setContentText("下載完畢");
                    mNotificationManager.notify(NOTIFICATION_ID_03, mNotificationBuilder03.build());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

這裡寫圖片描述

2.3 帶有等待進度條的通知

要顯示不確定的進度條,可以進行如下設定,不確定的進度條與上面的確定的進度條具有相同樣式,除了進度條是一個不表示完成的連續動畫。

mNotificationBuilder03.setProgress(0, 0,true);
manager.notify(NOTIFICATION_ID_03, mNotificationBuilder03.build());

關閉進度條:

mNotificationBuilder03.setProgress(max, progress, false);
manager.notify(NOTIFICATION_ID_03, mNotificationBuilder03.build());

Demo程式碼:

    private String TEST_ACTION_02="NotificationDemoActivity02";
    private String EXTRA_NOTIFICATION_ID_02="NotificationDemoActivity_02";
    private int NOTIFICATION_ID_02=1122;

    /**
     * 帶有等待進度條的通知
     */
    @RequiresApi(api = 26)
    private void showProgressNotification01(){
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Notification notification;

        Intent intent=new Intent(this, MainActivity.class);
        intent.setAction(TEST_ACTION_02);
        intent.putExtra(EXTRA_NOTIFICATION_ID_02,NOTIFICATION_ID_02);
        PendingIntent pendingIntent=PendingIntent.getActivity(this,0,intent,0);

        createNotificationChannelGroup();//建立渠道組
        createNotificationChannel(CHANNEL_ID,CHANNEL_NAME,"渠道描述",NotificationManager.IMPORTANCE_HIGH,group_id);
        notification = new Notification.Builder(getApplicationContext(), CHANNEL_ID)
                .setContentTitle("通知測試")
                .setContentText("帶有等待進度條的通知")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.drawable.logo)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.logo))
                .setContentIntent(pendingIntent)
                .setProgress(0,0,true)
                .setAutoCancel(true)
                .addAction(R.mipmap.ic_launcher,"關閉",pendingIntent)
                .build();
        manager.notify(NOTIFICATION_ID_02, notification);
    }

顯示效果如下:這裡寫圖片描述