Android 中使用通知(Kotlin 版)

1. 前置条件

  • Android Studio:确保使用最新版本(2023.3.1+)
  • 目标 API:最低 API 21,兼容 Android 8.0(渠道)和 13+(权限)
  • 依赖库:使用 WorkManagerNotificationCompat

2. 完整实现步骤

2.1 添加权限和依赖

AndroidManifest.xml
<!-- 通知权限 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- Android 13+ 必须 -->
<uses-permission android:name="android.permission.INTERNET" /> <!-- 若需网络请求 --><application><!-- 添加你的主 Activity --><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>
</application>
build.gradle (Module)
dependencies {// WorkManager 用于后台任务implementation "androidx.work:work-runtime-ktx:2.7.1"// 通知兼容库implementation "androidx.core:core-ktx:1.12.0"
}

2.2 创建通知渠道(Android 8.0+ 必需)

NotificationHelper.kt
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Buildobject NotificationHelper {const val CHANNEL_ID = "dynamic_messages_channel"const val NOTIFICATION_ID = 101 // 用于更新同一通知fun createNotificationChannel(context: Context) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {// 避免重复创建渠道val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManagerif (notificationManager.getNotificationChannel(CHANNEL_ID) != null) return// 配置渠道属性val name = "动态消息"val importance = NotificationManager.IMPORTANCE_HIGHval channel = NotificationChannel(CHANNEL_ID, name, importance).apply {description = "用于接收实时动态消息的推送"enableLights(true)lightColor = android.graphics.Color.RED}notificationManager.createNotificationChannel(channel)}}
}

2.3 构建动态通知

NotificationUtils.kt
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.example.myapp.R // 替换为你的包名object NotificationUtils {fun showDynamicNotification(context: Context,title: String,message: String) {// 创建点击跳转逻辑(示例跳转到 MainActivity)val intent = Intent(context, MainActivity::class.java).apply {flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK}val pendingIntent = PendingIntent.getActivity(context,0,intent,PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)// 构建通知val builder = NotificationCompat.Builder(context, NotificationHelper.CHANNEL_ID).setSmallIcon(R.drawable.ic_notification) // 必须的图标(需在 res/drawable 添加).setContentTitle(title).setContentText(message).setPriority(NotificationCompat.PRIORITY_HIGH).setContentIntent(pendingIntent).setAutoCancel(true) // 点击后自动消失.setStyle(NotificationCompat.BigTextStyle().bigText(message)) // 长文本支持// 发送通知with(NotificationManagerCompat.from(context)) {if (NotificationManagerCompat.from(context).areNotificationsEnabled()) {notify(NotificationHelper.NOTIFICATION_ID, builder.build())}}}// 更新通知(使用相同 ID)fun updateNotification(context: Context, newTitle: String, newMessage: String) {val builder = NotificationCompat.Builder(context, NotificationHelper.CHANNEL_ID).setSmallIcon(R.drawable.ic_notification).setContentTitle(newTitle).setContentText(newMessage)NotificationManagerCompat.from(context).notify(NotificationHelper.NOTIFICATION_ID, builder.build())}
}

2.4 后台任务调度(WorkManager)

NotificationWorker.kt
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import kotlinx.coroutines.delayclass NotificationWorker(context: Context,params: WorkerParameters
) : CoroutineWorker(context, params) {override suspend fun doWork(): Result {// 模拟网络请求延迟delay(3000)// 获取动态数据(此处为模拟数据,实际需替换为真实逻辑)val title = "您有新的消息!"val content = "当前时间:${System.currentTimeMillis()}"// 显示通知NotificationUtils.showDynamicNotification(applicationContext, title, content)return Result.success()}
}
调度任务(在 MainActivity 中)
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import java.util.concurrent.TimeUnitclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 初始化通知渠道NotificationHelper.createNotificationChannel(this)// 请求通知权限(Android 13+)requestNotificationPermission()// 启动周期性后台任务(每15分钟一次)val workRequest = PeriodicWorkRequestBuilder<NotificationWorker>(15, TimeUnit.MINUTES // 注意:最短间隔为15分钟).build()WorkManager.getInstance(this).enqueue(workRequest)}private fun requestNotificationPermission() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {if (checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) !=PackageManager.PERMISSION_GRANTED) {requestPermissions(arrayOf(android.Manifest.permission.POST_NOTIFICATIONS),REQUEST_CODE_NOTIFICATION)}}}companion object {private const val REQUEST_CODE_NOTIFICATION = 1001}
}

2.5 处理权限请求结果

MainActivity 中重写 onRequestPermissionsResult

override fun onRequestPermissionsResult(requestCode: Int,permissions: Array<String>,grantResults: IntArray
) {super.onRequestPermissionsResult(requestCode, permissions, grantResults)when (requestCode) {REQUEST_CODE_NOTIFICATION -> {if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 用户已授权} else {// 处理拒绝逻辑(例如显示提示)}}}
}

3. 扩展优化建议

3.1 结合网络请求

使用 Retrofit + Kotlin Coroutines 获取真实数据:

// 在 NotificationWorker 中替换模拟数据
val response = apiService.fetchMessages()
if (response.isSuccessful) {val message = response.body()?.latestMessagemessage?.let {NotificationUtils.showDynamicNotification(context, it.title, it.content)}
}

3.2 通知分组(Android 7.0+)

val builder = NotificationCompat.Builder(...).setGroup("messages_group").setGroupSummary(true) // 分组摘要

3.3 通知操作按钮

// 添加“标记已读”操作
val readIntent = Intent(context, MarkReadReceiver::class.java)
val readPendingIntent = PendingIntent.getBroadcast(...)
builder.addAction(NotificationCompat.Action.Builder(R.drawable.ic_check,"标记已读",readPendingIntent).build()
)

4. 常见问题解决

  1. 通知不显示

    • 检查是否在 Android 13+ 设备上授予了权限
    • 确保通知渠道已正确创建
    • 验证 setSmallIcon 使用了有效的资源 ID
  2. 后台任务不触发

    • 确保 WorkManager 依赖已添加
    • 检查设备是否处于 Doze 模式(测试时可暂时禁用)
  3. 通知点击无响应

    • 确认 PendingIntentFLAG_IMMUTABLE 正确使用
    • 检查目标 Activity 是否在 Manifest 中注册

可进一步结合 Firebase Cloud Messaging (FCM) 实现服务端消息推送,或添加更复杂的交互逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/83436.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用大模型预测急性结石性疾病技术方案

目录 1. 数据预处理与特征工程伪代码 - 数据清洗与特征处理数据预处理流程图2. 大模型构建与训练伪代码 - 模型训练模型训练流程图3. 术前预测系统伪代码 - 术前风险评估术前预测流程图4. 术中实时调整系统伪代码 - 术中风险预警术中调整流程图5. 术后护理系统伪代码 - 并发症预…

每日Prompt:生成自拍照

提示词 帮我生成一张图片&#xff1a;图片风格为「人像摄影」&#xff0c;请你画一张及其平凡无奇的iPhone对镜自拍照&#xff0c;主角是穿着JK风格cos服的可爱女孩&#xff0c;在自己精心布置的可按风格的房间内的落地镜前用后置摄像头随手一拍的快照。照片开启了闪光灯&…

动态规划-64.最小路径和-力扣(LetCode)

一、题目解析 从左上角到右下角使得数字总和最小且只能向下或向右移动 二、算法原理 1.状态表示 我们需要求到达[i,j]位置时数字总和的最小值&#xff0c;所以dp[i][j]表示&#xff1a;到达[i,j]位置时&#xff0c;路径数字总和的最小值。 2.状态转移方程 到达[i,j]之前要先…

LeetCode LCR 010 和为 K 的子数组 (Java)

两种解法详解&#xff1a;暴力枚举与前缀和哈希表寻找和为k的子数组 在解决数组中和为k的连续子数组个数的问题时&#xff0c;我们可以采用不同的方法。本文将详细解析两种常见的解法&#xff1a;暴力枚举法和前缀和结合哈希表的方法&#xff0c;分析它们的思路、优缺点及适用…

OpenVLA (2) 机器人环境和环境数据

文章目录 [TOC](文章目录) 前言1 BridgeData V21.1 概述1.2 硬件环境 2 数据集2.1 场景与结构2.2 数据结构2.2.1 images02.2.2 obs_dict.pkl2.2.3 policy_out.pkl 3 close question3.1 英伟达环境3.2 LIBERO 环境更适合仿真3.3 4090 运行问题 前言 按照笔者之前的行业经验, 数…

深度学习(第3章——亚像素卷积和可形变卷积)

前言&#xff1a; 本章介绍了计算机识别超分领域和目标检测领域中常常使用的两种卷积变体&#xff0c;亚像素卷积&#xff08;Subpixel Convolution&#xff09;和可形变卷积&#xff08;Deformable Convolution&#xff09;&#xff0c;并给出对应pytorch的使用。 亚像素卷积…

大模型在腰椎间盘突出症预测与治疗方案制定中的应用研究

目录 一、引言 1.1 研究背景 1.2 研究目的与意义 二、腰椎间盘突出症概述 2.1 定义与病因 2.2 症状与诊断方法 2.3 治疗方法概述 三、大模型技术原理与应用基础 3.1 大模型的基本原理 3.2 大模型在医疗领域的应用现状 3.3 用于腰椎间盘突出症预测的可行性分析 四、…

Vue3学习(组合式API——ref模版引用与defineExpose编译宏函数)

目录 一、ref模版引用。 &#xff08;1&#xff09;基本介绍。 &#xff08;2&#xff09;核心基本步骤。(以获取DOM、组件为例) &#xff08;3&#xff09;案例&#xff1a;获取dom对象演示。 <1>需求&#xff1a;点击按钮&#xff0c;让输入框聚焦。 &#xff08;4&…

公链开发及其配套设施:钱包与区块链浏览器

公链开发及其配套设施&#xff1a;钱包与区块链浏览器的技术架构与生态实践 ——2025年区块链基础设施建设的核心逻辑与创新突破 一、公链开发&#xff1a;构建去中心化世界的基石 1. 技术架构设计的三重挑战 公链作为开放的区块链网络&#xff0c;需在性能、安全性与去中心…

Kotlin 作用域函数(let、run、with、apply、also)对比

Kotlin 的 作用域函数&#xff08;Scope Functions&#xff09; 是简化代码逻辑的重要工具&#xff0c;它们通过临时作用域为对象提供更简洁的操作方式。以下是 let、run、with、apply、also 的对比分析&#xff1a; 一、核心区别对比表 函数上下文对象引用返回值是否扩展函数…

14、Python时间表示:Unix时间戳、毫秒微秒精度与time模块实战

适合人群&#xff1a;零基础自学者 | 编程小白快速入门 阅读时长&#xff1a;约5分钟 文章目录 一、问题&#xff1a;计算机中的时间的表示、Unix时间点&#xff1f;1、例子1&#xff1a;计算机的“生日”&#xff1a;Unix时间点2、答案&#xff1a;&#xff08;1&#xff09;U…

AI日报 - 2024年5月17日

&#x1f31f; 今日概览 (60秒速览) ▎&#x1f916; 大模型前沿 | OpenAI推出自主编码代理Codex&#xff1b;Google DeepMind发布Gemini驱动的编码代理AlphaEvolve&#xff0c;能设计先进算法&#xff1b;Meta旗舰AI模型Llama 4 Behemoth发布推迟。 Codex能并行处理多任务&…

DriveMM:用于自动驾驶的一体化大型多模态模型——论文阅读

《DriveMM: All-in-One Large Multimodal Model for Autonomous Driving》2024年12月发表&#xff0c;来自中山大学深圳分校和美团的论文。 大型多模态模型&#xff08;LMM&#xff09;通过整合大型语言模型&#xff0c;在自动驾驶&#xff08;AD&#xff09;中表现出卓越的理解…

C++_STL_map与set

1. 关联式容器 在初阶阶段&#xff0c;我们已经接触过STL中的部分容器&#xff0c;比如&#xff1a;vector、list、deque、 forward_list(C11)等&#xff0c;这些容器统称为序列式容器&#xff0c;因为其底层为线性序列的数据结构&#xff0c;里面 存储的是元素本身。那什么是…

【嵌入式开发-RGB 全彩 LED】

嵌入式开发-RGB 全彩 LED ■ RGB 全彩 LED简介■ 电路设计■ ■ RGB 全彩 LED简介 RGB 全彩 LED 模块显示不同的颜色。 ■ 电路设计 全彩 LED 使用 PA5、 蓝色&#xff08;B&#xff09; TIM2_CHN3 PA1、 绿色&#xff08;G&#xff09;TIM2_CHN2 PA2、 红色&#xff08;R&am…

计算机网络:手机和基站之间的通信原理是什么?

手机与基站之间的通信是无线通信技术的核心应用之一,涉及复杂的物理层传输、协议交互和网络管理机制。以下从技术原理、通信流程和关键技术三个层面深入解析这一过程: 一、蜂窝网络基础架构 1. 蜂窝结构设计 基本原理:将服务区域划分为多个六边形“蜂窝小区”,每个小区由*…

【Docker】Docker安装RabbitMQ

目录 1.拉取镜像 2. 创建挂载目录 3.创建和启动 4.登录管理端 1.拉取镜像 推荐使用带 Web 管理界面的官方镜像&#xff08;management&#xff09; # 拉取docker镜像 docker pull rabbitmq:management响应内容&#xff1a; 2. 创建挂载目录 创建挂载目录和日志目录 #rabb…

交叉编译源码的方式移植ffmpeg-rockchip

获取ffmpeg源码 git submodule add -f https://github.com/FFmpeg/FFmpeg.git thirdparty/FFmpeg 瑞芯微ffmpeg-rk git clone https://github.com/jjm2473/ffmpeg-rk/tree/enc# 参考的一位博主的说法 使用 ffmpeg-rochip 的好处 传统的使用硬件编解码的开发思路是&#xf…

9.0 C# 调用solidworks介绍1

一、C# 与 SolidWorks 联合开发概述 SolidWorks 提供了完整的 API(应用程序接口),允许开发者使用 C# 等编程语言进行二次开发,实现自动化设计、定制功能等。 主要技术要点包括: 1. API 结构:SolidWorks API 是基于 COM 的接口,包含数百个对象和数千个方法…

AD 多层线路及装配图PDF的输出

装配图的输出&#xff1a; 1.点开‘智能PDF’ 2. 设置显示顶层&#xff1a; 设置显示底层&#xff1a; 多层线路的输出 同样使用‘智能PDF’