欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android Notification(Android 8.0)

程序员文章站 2022-05-28 20:17:33
...

概述:

Android O(也就是SDK26版本) 引入了 通知渠道(Notification Channels)以提供统一的系统来帮助用户管理通知,如果是针对 android O 为目标平台时,必须实现一个或者多个通知渠道,以向用户显示通知。若并不以 Android O 为目标平台,当应用运行在 android O 设备上时,其行为将与运行在 Android 7.0 上时相同。
Android O 的用户可以使用一致的系统 UI 管理大多数与通知有关的设置。所有发布至通知渠道的通知都具有相同的行为。当用户修改任何下列特性的行为时,修改将作用于通知渠道:

  • 重要性
  • 声音
  • 振动
  • 在锁屏上显示
  • 替换免打扰模式

官方文档:https://developer.android.google.cn/training/notify-user/build-notification

一、Android系统通知基本操作

谷歌原生8.0系统显示如下:
Android Notification(Android 8.0)
如果向左滑动通知,则会出现两个开关,一个是设置该应用的具体通知规范,另一个可以设置让该应用的通知推迟一段时间推送。
Android Notification(Android 8.0)

设置具体通知规范:
Android Notification(Android 8.0)
Android Notification(Android 8.0)

设置通知休眠时间:
Android Notification(Android 8.0)

1.1 通知优先级和重要性

Android O 弃用了为单个通知设置优先级的功能。创建通知渠道时可以设置建议重要性级别。为通知渠道指定的重要性级别适用于发布至该渠道的所有通知消息。可以配置五个级别中的一个,这些级别代表着通知渠道可以打断用户的程度,范围是 IMPORTANCE_NONE(0)至 IMPORTANCE_HIGH(4)。默认重要性级别为 3:在所有位置显示,发出提示音,但不会对用户产生视觉干扰。创建通知渠道后,只有系统可以修改其重要性。用户可以在设置中找到。
Android Notification(Android 8.0)
Android Notification(Android 8.0)
Android Notification(Android 8.0)

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系统上有效果,在华为,小米手机没有任何变化。
Android Notification(Android 8.0)

二、通知进阶

2.1 带有操作按钮的通知:

通知最多可以提供三个操作按钮,允许用户快速响应,例如暂停提醒或甚至回复短信。
Android Notification(Android 8.0)

    /**
     * 带有操作按钮的通知
     */
    @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();
    }

Android Notification(Android 8.0)

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);
    }

显示效果如下:Android Notification(Android 8.0)