文章

使用通知Notification

Android8.0开始引入了通知渠道的概念,每条通知都要属于一个对应的渠道,每个应用程序都可以自由的创建当前应用拥有哪些通知渠道,但这些通知渠道的控制权是掌握在用户手上的,用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否震动或者是否要关闭这个渠道的通知。

对于每个应用来说,通知渠道的划分是非常讲究的,因为一旦创建后就不能再修改了,如果一开始给A通知渠道设置了低优先级,后续即使更新软件把A通知渠道改成高优先级也不会生效。因此开发者需要仔细分析自己的应用程序一共有哪些类型的通知,然后再去创建相应的通知渠道。

创建通知首先需要一个NotificationManager对通知进行管理,可以通过调用ContextgetSystemService()方法获取,它接收一个字符串参数用于确定获取哪个系统服务,这里传入Context.NOTIFICATION_SERVICE即可获取。

NotificationManager的完整实例如下:

val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

接下来要使用NotificationChannel类构建一个通知渠道,并调用NotificationManagercreateNotificationChannel()方法完成创建。由于NotificationChannel和createNotificationChannel()都是Android8.0中新增的API,所以还需要进行版本判断:

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    val channel = NotificationChannel(channelId,channelName,importance)
    manager.createNotificationChannel(channel)
}

创建一个通知渠道至少需要渠道ID渠道名称重要等级三个参数,其中ID可以随便定义,只要保证全局唯一即可。渠道名称是给用户看的,用于表达这个渠道的用途。通知等级主要有IMPORTANCE_HIGHIMPORTANCE_DEFAULTIMPORTANCE_LOWIMPORTANCE_MIN这几种,对应重要程度从高到低。不过用户也可以随时手动更改某个通知渠道重要等级,只有IMPORTANCE_HIGH高等级可以在用户手机上弹出通知弹窗。

一、通知的基本用法

通知可以在ActivityBroadcastReceiverService中创建,相比BroadcastReceivcer和Service,在Activity中创建通知的场景还是比较少的,因为一般只有应用进入后台才需要使用通知。

需要使用NotificationCompat类的build()构造器来构造一个Notification对象,使用AndroidX的NotificationCompat类可以保证软件在所有Android系统版本上运行。

class MainActivity : AppCompatActivity() {
    override fun onCreate(...) {
        ...
        val manager = getSystemService(Context.NOTIFICATION_SERVICE)
                as NotificationManager
        // 判断客户机版本是否大于等于Androud8.0
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // 创建通知渠道
            val channel = NotificationChannel("normal","Normal",
                    NotificationManager.IMPORTANCE_DEFAULT)
            manager.createNotificationChannel(channel)
        }
        btn.setOnClickListener {
            val notification = NotificationCompat.Builder(this,"normal")
                .setContentTitle("这是通知标题")
                .setContentText("这是通知内容")
                // 设置通知栏小图标
                .setSmallIcon(R.drawable.small_icon)
                // 设置下拉通知大图标
                .setLargeIcon(BitmapFactory.decodeResource(resources,
                    R.drawable.large_icon))
                .build()
            // 手机显示通知,第一个参数是id,保证唯一性
            manager.notify(1, notification)
        }
    } 
}

1.PendingIntent——给通知指明意图

PendingIntent和Intent有些类似,都可以启动Activity、Service以及发送广播,不同的是Intent倾向于立即执行某个动作,而PendingIntent倾向于在某个合适的时机执行某个动作,比如点击通知启动Activity。

PendingIntent提供了三个静态方法用于获取实例,可以根据需求选择getActivity()、getBroadcase()、getService(),这三个方法接收的参数是相同的,第一个参数是Context第二个参数一般用不到,传入0即可第三个参数是一个Intent对象,用于构建出PendingIntent的“意图”第四个参数用于确定PendingIntent的行为,有FLAG_ONE_SHOTFLAG_NO_CREATEFLAG_CANCEL_CURRENTFLAG_UPDATE_CURRENT四个值可选,通常传入0即可

NotificationCompat.Builder还可以连缀一个setContentIntent()方法,用于传入PendingIntent对象。

override fun onCreate(...) {
    ...
    btn.setOnClickListener {
        // 构建PendingIntent“意图”Intent
        val intent = Intent(this,NotificationActivity::class.java)
        // 用getActivity()构建PendingIntent
        val pi = PendingIntent.getActivity(this, 0, intent, 0)
        val notification = NotificationCompat.Builder(this,"normal")
           ...
           // 设置通知“意图”
           .setContentIntent(pi)
           .build()
        manager.notify(1, notification)
    }
}

2.取消通知在状态栏中显示

第一种方法是,用户点击通知后自动取消。

val notification = NotificationCompat.Builder(this,"normal")
    ...
    // 点击通知后自动取消
    .setAutoCancel(true)
    .buile()

第二种方法是,用代码显式取消

val manager = getSystemService(Context.NOTIFICATION_SERVICE)
                as NotificationManager
btn.setOnClickListener {
    // 1是创建通知(manager.notify())时传入的id
    manager.cancel(1)
}

二、通知的进阶技巧

挑一些常用的API进行学习。先来看看setStyle()方法,这个方法允许我们构建出富文本通知内容,也就是说通知不光可以有文字和图标。setStyle()方法接收一个NotificationCompat.Style方法,这个参数就是用来构建具体的富文本信息的,如长文字、图片等。

1.长文本显示

如果文本过长还是建议在Activity中显示更合理。

val notification = NotificationCompat.Builder(this,"normal")
    ...
    .setStyle(NotificationCompat.BigTextStyle().bigText(
        "Learn how to build notifications, send and sync data" + 
        "and use voice actions. Get the official Android" + 
        "IDE and developer tools build apps for Android."))
    .build()

2.大图片显示

val notification = NotificationCompat.Builder(this,"normal")
    ...
    .setStyle(NotificationCompat.BigPictureStyle().bigPicture(
        BitmapFactory.decodeResource(resources, 
            R.drawable.big_image)))
    .build()
License:  CC BY 4.0