本文最后更新于:1 个月前

通知是指 Android 在应用的界面之外显示的消息,旨在向用户提供提醒、来自他人的通信信息或应用中的其他实时信息。

通知刨析

通知

  1. setSmallIcon()
  2. 应用名称
  3. 时间戳:由系统提供,但可以通过 setWhen() 将其替换掉或者通过 setShowWhen(false) 将其隐藏。
  4. setLargeIcon()
  5. setContentTitle()
  6. setContentText()

创建通知

添加支持库

implementation "com.android.support:support-compat:28.0.0"

创建基本通知

设置通知内容

  • 见上通知刨析
  • setPriority() 设置通知优先级。优先级确定通知在 Android 7.1 和更低版本上的干扰程度。
var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle(textTitle)
        .setContentText(textContent)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)

创建渠道并设置重要性

createNotificationChannel() 传递 NotificationChannel 的实例在系统中注册应用的通知渠道。

private fun createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is new and not in the support library
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val name = getString(R.string.channel_name)
        val descriptionText = getString(R.string.channel_description)
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
            description = descriptionText
        }
        // Register the channel with the system
        val notificationManager: NotificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(channel)
    }
}

设置通知的点按操作

指定通过 PendingIntent 对象定义的内容 Intent,并将其传递给 setContentIntent()

// Create an explicit intent for an Activity in your app
val intent = Intent(this, AlertDetails::class.java).apply {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, 0)

val builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        // Set the intent that will fire when the user taps the notification
        .setContentIntent(pendingIntent)
        .setAutoCancel(true) // 点按通知后自动移除通知

setFlags() 方法可帮助保留用户在通过通知打开应用后的预期导航体验。

  • 专用于响应通知的 Activity。启动一个新任务,而不是添加到应用的现有任务和返回堆栈。
  • 应用的常规应用流程中存在的 Activity。启动 Activity 时应创建返回堆栈,以便保留用户对返回和向上按钮的预期。

显示通知

NotificationManagerCompat.notify() 方法参数为:通知 ID 和 NotificationCompat.Builder.build()

创建折叠式通知

  1. 创建视图布局
  2. RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_name);
  3. notification.bigContentView = remoteViews; or notification.contentView = remoteViews;

添加操作按钮

addAction() 传递给 PendingIntent 方法。

val snoozeIntent = Intent(this, MyBroadcastReceiver::class.java).apply {
    action = ACTION_SNOOZE
    putExtra(EXTRA_NOTIFICATION_ID, 0)
}
val snoozePendingIntent: PendingIntent =
    PendingIntent.getBroadcast(this, 0, snoozeIntent, 0)
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .addAction(R.drawable.ic_snooze, getString(R.string.snooze),
                snoozePendingIntent)

添加直接回复操作

添加进度条

如果可以估算操作在任何时间点的完成进度,可以通过调用 setProgress(mamx, progress, false)。移除进度条 setProgress(0, 0, false)

如果需要显示不确定性进度条,可以调用 setProgress(0, 0, true)。移除进度条同样使用 setProgress(0, 0, false)

设置系统范围的类别

  • setCategory()
    CATEGORY_ALARMCATEGORY_REMINDERCATEGORY_EVENTCATEGORY_CALL

显示紧急信息

如果应用的目标平台是 Android 10(API29)或更高版本,必须在应用清单文件中请求 USE_FULL_SCREEN_INTENT 权限,以便系统启动与时效性通知关联的全屏 Activity。

val fullScreenIntent = Intent(this, ImportantActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
    fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setFullScreenIntent(fullScreenPendingIntent, true)

设置锁定屏幕的公开范围

setVisibility()

  • VISIBILITY_PUBLIC 显示通知的完整内容。
  • VISIBILITY_SECRET 不在锁定屏幕上显示该通知的任何部分。
  • VISIBILITY_PRIVATE 显示基本信息,但隐藏通知的完整内容。当设置为此级别时,可以通过 setPublicVersion() 方法提供通知内容的备用版本。

更新和移除通知

  • NotificationManagerCompat.notify() 更新通知,传入参数为之前使用的具有同一 ID 的通知,如果之前的通知已被关闭,系统会创建一个新通知。调用 setOnlyAlertOnce() 方法会使得通知只在首次出现时打断用户。
  • cancel(ID)cancelAll()setTimeoutAfter()

创建展开式通知

  • NotificationCompat.BigPictureStyle 添加大图片,如需使该图片仅在通知收起时显示为缩略图,调用 setLargeIcon() 并向其传递图片,同时调用 BigPictureStyle.bigLargeIcon(null),这样大图标就会在通知展开时消失。

  • NotificationCompat.BigTextStyle 添加一大段文本

  • NotificationCOmpat.InboxStyle 创建收件箱样式的通知。如需添加新行,最多可调用 addLine() 6 次,若超过 6 次,仅显示前 6 行。

    var notification = NotificationCompat.Builder(context, CHANNEL_ID)
            .setSmallIcon(R.drawable.new_mail)
            .setContentTitle("5 New mails from " + sender.toString())
            .setContentText(subject)
            .setLargeIcon(aBitmap)
            .setStyle(NotificationCompat.InboxStyle()
                    .addLine(messageSnippet1)
                    .addLine(messageSnippet2))
            .build()
  • 在通知中显示对话

  • 使用媒体控件创建通知

从通知启动 Activity

设置常规 Activity PendingIntent

使用 TaskStackBuilder 设置 PendingIntent

  1. 定义应用的 Activity 层次结构
    通过应用清单文件为每个 <activity> 元素添加 android:parentActivityName 属性来定义 Activity 的自然层次结构。

  2. 构建包含返回堆栈的 PendingIntent
    创建 TaskStackBuilder 的实例并调用 addNextIntentWithParentStack(),向其传递需要启动的 Activity 的 Intent。只要为每个 Activity 定义了父 Activity,就可以调用 getPendingIntent() 来接收包含整个返回堆栈的 PendingIntent

    // Create an Intent for the activity you want to start
    val resultIntent = Intent(this, ResultActivity::class.java)
    // Create the TaskStackBuilder
    val resultPendingIntent: PendingIntent? = TaskStackBuilder.create(this).run {
        // Add the intent, which inflates the back stack
        addNextIntentWithParentStack(resultIntent)
        // Get the PendingIntent containing the entire back stack
        getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
    }

设置特殊 Activity PendingIntent

  1. 在清单中将以下属性添加到 <activity> 元素。

    • android:taskAffinity=""
      结合 FLAG_ACTIVITY_NEW_TASK 标记使用,将此属性设置为空,可确保这类 Activity 不会进入应用的默认任务。
    • android:excludeFromRecents="true"
      用于从“最近”中排除新任务,以免用户意外返回它。
  2. 构建并发出通知
    a. 创建可启动 ActivityIntent
    b. 通过使用 FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_CLEAR_TASK 标记调用 setFlags(),将 Activity 设置为在新的空任务中启动。
    c. 通过调用 getActivity() 创建 PendingIntent

    val notifyIntent = Intent(this, ResultActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
    }
    val notifyPendingIntent = PendingIntent.getActivity(
            this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT
    )
  3. PendingIntent 传递到通知中。

    val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
        setContentIntent(notifyPendingIntent)
        ...
    }
    with(NotificationManagerCompat.from(this)) {
        notify(NOTIFICATION_ID, builder.build())
    }

创建一组通知

  • 调用 setGroup() 方法,传入参数为一个唯一标识符字符串。
  • setSortKey() 更改通知顺序,默认根据发布时间排序
  • setGroupAlertBehavior() 通知组的提醒应由其他通知处理。如果只希望通知组摘要发出提醒,那么通知组中的所有子级都应具有通知组提醒行为 GROUP_ALERT_SUMMARY。其他选项包括 GROUP_ALERT_ALLGROUP_ALERT_CHILDREN
  • setGroupSummary(true) 设置通知组摘要。

创建和管理通知渠道

从 Android 8.0(API 级别 26)开始,所有通知都必须分配到相应的渠道。

创建通知渠道

  1. 构建一个具有唯一渠道 ID、用户可见名称和重要性级别的 NotificationChannel 对象。
  2. (可选)使用 setDescription() 指定用户在系统设置中看到的说明。
  3. 注册通知渠道,方法是将该渠道传递给 createNotificationChannel()

设置重要性级别

渠道重要性会影响在渠道中发布的所有通知的干扰级别,包括从 IMPORTANCE_NONE(0)IMPORTANCE_HIGH(4) 5 个重要性级别。

读取通知渠道设置

  1. 通过调用 getNotificationChannel()getNotificationChannels() 来获取 NotificationChannel 对象。
  2. 查询特定的渠道设置,例如 getVibrationPattern()getSound()getImportance()

打开通知渠道设置

创建通知渠道后,无法以编程方式更改通知渠道的视觉和听觉行为,只有用户可以通过系统设置更改渠道行为。为了让用户轻松访问这些通知设置,应在应用的设置界面中添加一个用于打开这些系统设置的项。

val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS).apply {
    putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
    putExtra(Settings.EXTRA_CHANNEL_ID, myNotificationChannel.getId())
}
startActivity(intent)

删除通知渠道

可以通过调用 deleteNotificationChannel() 删除通知渠道。

创建通知渠道分组

创建新渠道分组

// The id of the group.
val groupId = "my_group_01"
// The user-visible name of the group.
val groupName = getString(R.string.group_name)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannelGroup(NotificationChannelGroup(groupId, groupName))

创建分组后,可以调用 setGroup()NotificationChannel 对象与该分组相关联。

修改通知标志

创建自定义通知


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

《Android进阶之光》 上一篇
Android中的单位 下一篇