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,后面用来取消通知的。所以随便填一个数字即可,效果如下。

可以看到,小图标是灰色的。当然了,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,延时一秒,再震动一次,当然,它需要向申请权限

.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"?>        

而,R.layout_cus_notify_large 中,给其中一个 TextView设置红色,不设置 style,看看效果:


避免在 RemoteViews 上设置背景颜色,可能会导致文办颜色无法读取的问题

4.2 创建完全的自定义通知背景

如果你不想用系统的时间戳,通知图标等。可以去掉 setStyle(),只添加 setCustomContentView 和 setCustomBigContentView 即可。

要支持低于 Android 4.1(API 级别 16)的 Android 版本,您还应调用 setContent(),向其传递同一 RemoteViews 对象。

如需获取更多使用通知的示例代码,请参阅 Android 通知示例。

更多相关文章

  1. Android布局优化的几种方法
  2. Android的第一个项目HelloWorld(疯狂Android讲义)
  3. listView及ScrollView等PadingTop显示问题:android:clipToPaddin
  4. Android中的通知—Notification .
  5. Android之解决多语言适配部分TextView内容左对齐和内容一行不排
  6. 浅谈Android五大布局(一)——LinearLayout、FrameLayout和Absoult
  7. android 自定义图形之层叠样式 [layer-list] 的使用
  8. Android相对布局和线性布局
  9. Android中的文件存储数据方式 .

随机推荐

  1. Android(安卓)中文API(86)――ResourceCurs
  2. Android,一个函数实现支付宝...
  3. Android(安卓)Screen Monitor
  4. 面试 | Android(安卓)View、布局、动画、
  5. Android(安卓)Studio教程-创建第一个项目
  6. Android(安卓)Keystore System介绍
  7. Android设置反代理
  8. Android属性allowBackup安全风险浅析
  9. 基于Eclipse的Android(安卓)SDK开发环境
  10. android 限制EditText输入数字的范围大小