Android 通知


概述

通知是 Android 系统中比较有特色的一个功能,当某个应用程序希望向用户发送提示信息,而该应用程序又不在前台运行时,就可以借助通知来实现。发出一条通知以后,手机最上方的状态栏会显示一个通知的图标,下拉状态栏后可以看到通知的详细内容


创建通知渠道

设计通知必须以不打扰到用户为前提,否则效果会适得其反。对于应用程序发送的通知,用户并非都会感兴趣。以微博为例,我只希望收到我所关注的人的微博更新通知,但并不想让微博一天到晚给我推送一些明星的花边新闻。于是,Android 8.0 系统引入了通知渠道这个概念

通知渠道,顾名思义,就是每条通知都要属于一个对应的渠道。每个应用程序都可以自由地创建当前应用拥有哪些通知渠道,但这些通知渠道的控制权是掌握在用户手上的。用户可以自由选择这些通知渠道的重要程度,并自行决定是否关闭这个渠道的通知

对于应用来说,通知渠道的划分是非常考究的,因为通知渠道一旦创建之后就不能再修改了


通知的使用

了解完通知渠道以后,我们来通过一个实例学习一下通知的使用方法

通知的用法很灵活,既可以在 Activity 里创建,也可以在 BroadcasterReceiver 里创建,当然还可以在 Service 里创建。在 Activity 里创建通知的场景比较少,一般只有当程序进入后台的时候才需要使用通知

假设现在有一个按钮,用于发出一条通知,代码如下:

class MainActivity : AppCompatActivity() {
    
    

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // 首先需要一个 NotificationManager 对通知进行管理,可以通过 Context 的 getSystemService() 方法获取
        // getSystemService() 方法一个字符串用于确定获取系统的哪个服务,这里传入 Context.NOTIFICATION_SERVICE
        val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        // 使用 NotificationChannel 类构建一个通知渠道,并调用 createNotificationChannel() 方法完成创建
        // 由于 NotificationChannel 类和 createNotificationChannel() 方法都是 Android 8.0 系统中新增的 API
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    
    
            // 创建一个通知渠道需要三个参数:
            // 1. 渠道ID:可以随便定义,保证全局唯一性即可
            // 2. 渠道名称:给用户看的,需要清楚的表达这个渠道的用途
            // 3. 通知的重要等级:不同的重要等级决定通知的不同行为
            val channel = NotificationChannel("normal", "Normal", NotificationManager.IMPORTANCE_DEFAULT)
            manager.createNotificationChannel(channel)
        }
        button.setOnClickListener {
    
    
            // 创建通知,注意构造函数传入的渠道ID必须和前面一致
            val notification = NotificationCompat.Builder(this, "normal")
            // 指定通知的标题内容
                    .setContentTitle("This is content title")
            // 指定通知的正文内容
                    .setContentText("This is content text")
            // 设置通知的小图标
                    .setSmallIcon(R.drawable.small_icon)
            // 设置通知的大图标
            .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.large_icon))
            // 设置点击通知后自动消失
            		.setAutoChannel(true)
                    .build()
            // 显示通知
            // 1. 第一个参数是id,保证为每个通知指定的id都是唯一的
            // 2. 第二个参数是Notification对象
            manager.notify(1, notification)
        }
}

至此,点击按钮,就会发出一条通知了。但当我们点击这条通知时,却发现没有任何效果。这是因为,要想实现通知的点击效果,还需要在代码中进行相关设置,这就涉及一个新的概念 —— PendingIntent

PendingIntent 从名字上看起来和 Intent 有些类似,都可以指明某一个意图,都可以用于启动 Activity、启动 Service 以及发送广播。不同的是,Intent 倾向于立即执行某个动作,而 PendingIntent 倾向于在某个合适的时机执行某个动作,所以也可以把 PendingIntent 简单地理解为延迟执行的 Intent

NotificationCompact.Builder 还可以连缀一个 setContentIntent() 方法,接收的参数正是一个 PendingIntent 对象,当用户点击这条通知时,就会执行相应的逻辑

class MainActivity : AppCompatActivity() {
    
    

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    
    
            val channel = NotificationChannel("normal", "Normal", NotificationManager.IMPORTANCE_DEFAULT)
            manager.createNotificationChannel(channel)
        }
        button.setOnClickListener {
    
    
            // 先使用 Intent 表达出想要启动 NotificationActivity 的意图,再传入 PendingIntent 的 getActivity() 方法里
            val intent = Intent(this, NotificationActivity::class.java)
            // 参数说明如下:
            // 1. 第一个参数是Context,不用多解释
            // 2. 第二个参数一般用不到,传入0即可
            // 3. 第三个参数是Intent对象
            // 4. 第四个参数用于确定PendingIntent的行为
            val pi = PendingIntent.getActivity(this, 0, intent, 0)
            val notification = NotificationCompat.Builder(this, "normal")
                    .setContentTitle("This is content title")
                    .setContentText("This is content text")
                    .setSmallIcon(R.drawable.small_icon)
                    .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.large_icon))
                    .setContentIntent(pi)
                    .build()
            manager.notify(1, notification)
        }
    }
}

Guess you like

Origin blog.csdn.net/CSDN_handsome/article/details/121578855