MST

星途 面试题库

面试题:Kotlin下优化Android通知与动态权限适配

在Kotlin的Android应用中,需要处理多种类型的通知,并且针对不同Android版本(如Android 6.0及以上)动态适配权限,同时要确保通知的展示和交互在不同设备上的稳定性和一致性。请阐述详细的设计思路、关键技术点,并提供核心代码示例。
38.1万 热度难度
编程语言Kotlin

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 权限处理
    • 对于Android 6.0及以上版本,在使用通知相关功能前,需动态申请POST_NOTIFICATIONS权限。检查权限是否已授予,若未授予则发起权限请求。
    • onRequestPermissionsResult方法中处理权限请求结果。
  2. 通知类型处理
    • 定义不同类型通知的模板,如普通通知、进度通知、带有动作按钮的通知等。
    • 根据业务需求选择合适的通知模板进行创建和展示。
  3. 兼容性与稳定性
    • 使用NotificationCompat.Builder类来创建通知,以确保在不同Android版本上的兼容性。
    • 测试在不同设备和Android版本上通知的展示和交互效果,确保一致性。

关键技术点

  1. 权限管理Settings.ACTION_APPLICATION_DETAILS_SETTINGS用于引导用户到应用设置页面手动开启通知权限。NotificationManagerCompatareNotificationsEnabled方法可检查通知是否开启。
  2. 通知构建NotificationCompat.Builder类提供了丰富的方法来设置通知的各种属性,如标题、内容、小图标等。NotificationChannel类用于Android 8.0及以上版本创建通知渠道。
  3. 通知交互:可通过PendingIntent设置通知的点击行为,如启动Activity或Service。添加动作按钮可使用NotificationCompat.Action类。

核心代码示例

  1. 权限请求
private const val REQUEST_CODE = 101
private fun requestNotificationPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        val notificationManager = NotificationManagerCompat.from(this)
        if (!notificationManager.areNotificationsEnabled()) {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.POST_NOTIFICATIONS), REQUEST_CODE)
        }
    }
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == REQUEST_CODE) {
        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 权限授予,可进行通知相关操作
        } else {
            // 权限未授予,可引导用户到设置页面开启
            val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
                data = Uri.fromParts("package", packageName, null)
            }
            startActivity(intent)
        }
    }
}
  1. 创建并展示通知
private fun createAndShowNotification() {
    val notificationManager = NotificationManagerCompat.from(this)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channelId = "my_channel_id"
        val channelName = "My Channel"
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(channelId, channelName, importance)
        notificationManager.createNotificationChannel(channel)
    }

    val intent = Intent(this, MainActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
    }
    val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)

    val builder = NotificationCompat.Builder(this, "my_channel_id")
       .setSmallIcon(R.drawable.ic_notification)
       .setContentTitle("Notification Title")
       .setContentText("Notification Content")
       .setPriority(NotificationCompat.PRIORITY_DEFAULT)
       .setContentIntent(pendingIntent)
       .setAutoCancel(true)

    notificationManager.notify(1, builder.build())
}