通知是 android 系统存在至今为止被变更最为频繁的 api 之一,android 4.1、4.4、5.0、7.0、8.0 都对通知做过比较大的改动。到了 8.0 通知功能趋于稳定,至今没有做过更大的改动,今天就来讲讲通知。
为了能让用户自主选择关注应用的哪些通知,Android 8.0系统引入了通知渠道。每条通知对应一个渠道,用户就可自由选择开启哪些通知。通知渠道一旦创建之后就不能再修改了。
首先需要一个NotificationManager对通知进行管理,通过调用Context的getSystemService()方法获取,此方法接受一个字符串参数,传入Context.NOTIFICATION_SERVICE就可以获得NotificationManager的实例了。如下:
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
然后需要使用NotificationChannel类来构建通知渠道,并调用NotificationManager的createNotificationChannel()方法完成创建。而这个类和这个方法都是Android 8.0系统新增的,所以需要进行版本判断:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel("1", "tongzhi", NotificationManager.IMPORTANCE_DEFAULT)
manager.createNotificationChannel(channel)
}
创建一个通知渠道至少需要三个参数,如上三个参数分别是渠道ID、渠道名称、重要等级。渠道ID需保证全局唯一,渠道名称是给用户看到,重要等级主要有IMPORTANCE_HIGH、IMPORTANCE_DEFAULT、IMPORTANCE_LOW、IMPORTANCE_MIN这几种。
设置最高等级弹出的通知就会是横幅,类似于QQ好友发来消息通知
通知的基本用法
通知可以在Acitivity、BroadcastReceiver、Service里创建,但是在Activity里面用的比较少,毕竟只有当应用进入后台是才需要用到通知。但是用法是一样的。
首先需要一个Builder构造器来创建Notification对象,为了能让程序能在Android系统各种版本上都能运行,可以使用AndroidX库中提供的NotificationCompat类来创建Notification对象,如下:
val notification = NotificationCompat.Builder(this, "1")
.setContentTitle("title")
.setContentText("text")
.setSmallIcon(R.drawable.ic_launcher_background)
.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.ic_launcher_background))
.build()
Builder的构造函数中接收两个参数,第一个是context,第二个是渠道ID。然后连缀一系列的设置方法丰富我们的通知。setSmallIcon()方法用于设置通知的小图标,注意,只能使用纯alpha图层的图片进行设置。
现在只需要调用NotificationManager的notify()方法就可以让通知显示出来了。
manager.notify(1,notification)
第一个参数是id,为每个通知指定的id都是不用的。
现在运行程序后就可以去应用信息的通知管理里面看到刚才创建的通知了。
PendingIntent
通知有了,但是目前还缺少点击事件,这个时候就涉及到了PendingIntent,它和Intent类似,不过它更倾向于在某个合适的时机执行某个动作。
使用它也很简单,主要提供了几个静态方法用于获取PendingIntent的实例——getActivity()方法、getBroadcast()方法,getService()方法。这几个方法接收的参数是一样,第一个是context,第二个是一般传入0,第三个是一个Intent对象,可以通过这个对象构建出PendingIntnet的意图,第四个是确定PendingIntent的行为,有FLAG_ONE_SHOT、FLAG_NO_CREATE、FLAG_CANCEL_CURRENT和FLAG_UPDATE_CURRENT这4种值可选,通常传入0。
比如现在来实现点击通知进入另一个Activity,代码如下:
val intent = Intent(this, SecondActivity::class.java)
val pi = PendingIntent.getActivity(this, 0, intent, 0)
val notification = NotificationCompat.Builder(this, "1")
.setContentTitle("title")
.setContentText("text")
.setSmallIcon(R.drawable.ic_launcher_background)
.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.ic_launcher_background))
.setContentIntent(pi)
.build()
manager.notify(1,notification)
先用Intent表达意图,再将Intent对象传入PendingIntent的getActivity()方法中,最后在通知中使用setContentIntent()方法传入参数即可。
取消通知图标
不过目前点击通知后,系统栏上的通知图标还没有消失,有两种方式:
第一种是在NotificationCompat.Builder中连缀一个setAutoCancel()方法:
val notification = NotificationCompat.Builder(this, "1")
...
.setAutoCancel(true)
.build()
第二种是显式地调用NotificationManager的cancel()方法将它取消,前往SecondActivity:
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.cancel(1)
}
}
这里传入的1就是之前那个通知的id。
通知的进阶技巧
NotificationCompat.Builder中提供了非常丰富的API,其中setStyle()方法允许我们构建出富文本的通知内容,它接收一个NotificationCompat.Style参数,这个参数就是用来构建具体的富文本信息的,如长文字、图片等。
一般情况下,如果通知文本内容很长是会被省略号给忽略掉的。如果想要通知中显示长文本,就通过setStyle()方法,如下:
val notification = NotificationCompat.Builder(this, "1")
.setContentTitle("title")
.setStyle(NotificationCompat.BigTextStyle().bigText("content"))
...
.build()
这里需要用setStyle()代替setContentText()方法。BigTextStyle是封装长文字信息的,用bigText方法传入文字即可。
如果是在通知里面显示一张大图:
val notification = NotificationCompat.Builder(this, "1")
.setContentTitle("title")
.setStyle(NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(resources,
androidx.loader.R.drawable.notification_icon_background)))
...
.build()
通过BitmapFactory的decodeResource()方法将图片解析成Bitmap对象,再传入bigPicture()方法中就可以了。
网友评论