【Android】Notification 的基本使用

文章目录

  • 【Android】Notification的基本使用
    • 权限
    • 通知的基本使用
      • 1. 获取通知管理器(用于发送、更新、取消通知)
      • 2. 创建通知渠道(Android 8.0+ 必须)
      • 3. 使用通知
        • 3.1 发送通知
        • 3.2 更新通知
        • 3.3 取消通知
    • 通知的进阶技巧
      • 通知显示样式
        • 1. BigTextStyle — 显示大段文本(长消息)
        • 2. BigPictureStyle — 显示大图
        • 3. InboxStyle — 多条汇总(像邮件列表)
        • 3. InboxStyle — 多条汇总(像邮件列表)

【Android】Notification的基本使用

权限

Android 13(API 33)新增了POST_NOTIFICATIONS权限,这是一个危险权限,危险权限在 Android 6.0+ 必须运行时动态申请。

  1. 首先在AndroidManifest.xml中声明权限。
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
  1. 在尝试发送通知前,必须先检查并请求权限。
// Android 13(API 33+)需要动态申请通知权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.POST_NOTIFICATIONS}, REQUEST_CODE);} else {showNotification();}
} else {// Android 13 以下不需要权限,直接发通知showNotification();
}
  • ContextCompat.checkSelfPermission(...)——检查当前是否已经有权限

    • 返回值是PackageManager.PERMISSION_GRANTED,说明用户之前已经允许(或系统已授予)
    • 返回值是PackageManager.PERMISSION_DENIED,说明还没授权,需要发起申请
  • ActivityCompat.requestPermissions(...) —— 发起权限请求(触发系统对话框)

    • 作用:向系统请求权限。系统会(或不会)弹出系统权限对话框,用户选择「允许/拒绝」
    • 参数:
      • this:Activity(请求结果会回调到该 Activity 的 onRequestPermissionsResult
      • String[]:要请求的权限数组(这里只请求一个)
      • REQUEST_CODE:你自己定义的请求码,用于回调时区分是哪一次请求(常量,例:private static final int REQUEST_CODE = 1001;
    • 注意:如果用户之前勾选了“不再询问(Don’t ask again)”,调用 requestPermissions 可能不会弹对话框,而会直接在回调里返回 DENIED
  1. 重写 onRequestPermissionsResult(...)方法——处理用户的选择(回调)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == REQUEST_CODE) {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 用户同意了通知权限,可以发通知showNotification();} else {// 用户拒绝了通知权限,无法发通知Toast.makeText(this, "没有通知权限", Toast.LENGTH_SHORT).show();}}
}

在Android 13(API 33)之前,通知不需要运行时申请权限(只要应用正常安装,系统默认允许通知)。

通知的基本使用

1. 获取通知管理器(用于发送、更新、取消通知)

  1. NotificationManager(系统服务类)

    // 从当前上下文(Context)获取系统服务
    NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);// API 23+ 推荐(避免强转,更安全)
    NotificationManager notificationManager = getSystemService(NotificationManager.class);// 在 Fragment 里(没有直接的 getSystemService)
    NotificationManager notificationManager = requireContext().getSystemService(NotificationManager.class);
    

    缺点:不同 Android 版本的 API 差异较大。比如 Android 8.0 开始必须使用 通知渠道(NotificationChannel),而老版本没有,需要自己写兼容逻辑。

  2. NotificationManagerCompat(兼容类,来自 AndroidX 库)

    NotificationManagerCompat manager = NotificationManagerCompat.from(context);
    

    是对 NotificationManager 的一个 封装,主要作用是 屏蔽 Android 不同版本的差异

2. 创建通知渠道(Android 8.0+ 必须)

// Android 8.0(API 26+)开始需要创建通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {CharSequence name = "Channel Name";               String description = "Channel Description";int importance = NotificationManager.IMPORTANCE_HIGH;NotificationChannel channel = new NotificationChannel("my_channel_id", name, importance);channel.setDescription(description);notificationManager.createNotificationChannel(channel);
}
  1. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { … }

    • Build.VERSION.SDK_INT 是当前设备的 API 等级(整数)。
    • Build.VERSION_CODES.O 是 Android 8.0(API 26)。
    • NotificationChannel 及通知渠道机制从 API 26 开始引入,所以这段代码只在 API ≥ 26 时执行,避免在旧设备上因类/方法不存在而崩溃。
  2. CharSequence name = "Channel Name";

    • 这是渠道的可见名称(会显示在系统的“应用通知设置 → 渠道”界面)。
    • 使用 CharSequence 而不是 String 是因为系统允许富文本/本地化。建议用字符串资源getString(R.string.xxx))以便本地化。
  3. String description = "Channel Description";

    • 渠道的描述,用户在系统设置里可以看到,说明这个渠道里的通知是什么用途,同样建议放入资源以支持多语言。
  4. int importance = NotificationManager.IMPORTANCE_DEFAULT;

    渠道的重要性(importance)决定通知的行为:是否有声音、是否在锁屏显示、是否会弹出(heads-up)等。常见取值(从低到高):

    • IMPORTANCE_NONE:不展示(等于关闭这个渠道)。
    • IMPORTANCE_MIN:最不显眼,只在通知面板很靠后的位置显示,不震动、不响声、不显示图标。
    • IMPORTANCE_LOW:不响、不震动,但会在状态栏有较低优先级展示。
    • IMPORTANCE_DEFAULT:有声音/震动(默认行为)。
    • IMPORTANCE_HIGH(或更高):会产生 Heads-up(弹出)提示,通常用于紧急或需即时注意的通知。
  5. NotificationChannel channel = new NotificationChannel("my_channel_id", name, importance);

    创建 NotificationChannel 对象。参数:

    • "my_channel_id"渠道 ID,是你在代码里标识该渠道的唯一字符串(在同一应用内应唯一)。
      • 这个 ID 后续发通知时要在 NotificationCompat.Builder 中使用:new NotificationCompat.Builder(context, "my_channel_id")
      • 一旦创建并发布给系统,渠道 ID 不可变(你不能重命名 ID)。若需不同设置应新建不同 ID。
    • name:用户可见的名称。
    • importance:重要性等级(如上)。
  6. channel.setDescription(description);

    • 给渠道设置描述(在系统设置里显示),帮助用户理解该渠道的用途。
  7. notificationManager.createNotificationChannel(channel);

    将渠道注册到系统(通过 NotificationManager)。注册后:

    • 系统会把该渠道显示在“应用通知设置”里,让用户可以单独开关或调整声音/振动/优先级等。
    • 如果相同 ID 的渠道已存在,系统不会随意覆盖用户已修改的设置(比如用户改变了重要性或声音),但应用可以通过再次调用 createNotificationChannel 更新可变字段(name、description 等)。重要性、声音等用户设置通常不会被覆盖。
    • 这方法是幂等的——多次调用不会导致重复创建(对于同 ID,系统只会保持一个渠道)。

可以在手机应用设置中找到:

3. 使用通知

3.1 发送通知
Notification notification = new NotificationCompat.Builder(this, "my_channel_id").setSmallIcon(R.drawable.ic_launcher_background)   // 小图标(必须有).setContentTitle("新消息提醒")              // 标题.setContentText("你有一条新的消息,请查收。") // 内容.setPriority(NotificationCompat.PRIORITY_HIGH) // 优先级(7.1以下).setCategory(NotificationCompat.CATEGORY_MESSAGE) // 通知类别.setWhen(System.currentTimeMillis())      // 时间戳.build();
notificationManager.notify(1, notification);

3.2 更新通知
Notification notification = new NotificationCompat.Builder(this, "my_channel_id").setSmallIcon(R.drawable.ic_qq).setContentTitle("通知已更新").setContentText("newContent").setPriority(NotificationCompat.PRIORITY_HIGH).setAutoCancel(true).build();notificationManager.notify(1, notification); // 同 id 会覆盖之前的

3.3 取消通知
notificationManager.cancel(1); // 取消指定 id 的通知

这里主要有两个方法:notify()cancel()

  1. notify —— 发送/更新通知

    重载与参数:

    • notify(int id, Notification n)
    • notify(@Nullable String tag, int id, Notification n)

    系统用 (tag, id) 作为唯一键:

    • 只传 id ⇒ 等价于 (null, id)
    • 同一 (tag, id) 再次调用会覆盖/更新已有通知(而不是再叠一条)。
    • 不同 id ⇒ 并列显示多条通知(常用于聊天多会话、下载多任务)。

    建议:id 用稳定且可复现的数(如会话ID哈希);需要“堆叠多条”时用不同 id。

    注意:

    1. 渠道(Android 8.0+):通知所属的 Channel 决定重要级别、声音、震动等;用户一旦改了渠道设置,你在代码里改 importance不会生效,除非创建新渠道 ID
    2. 权限(Android 13+):没有 POST_NOTIFICATIONS 权限时,notify 调用不会崩不会显示。可先用 NotificationManagerCompat.areNotificationsEnabled() 检测。
    3. 小图标必须有setSmallIcon(...) 缺失会导致通知不显示/崩溃(部分系统)。
    4. 更新 vs 新发:要“更新”同一条,用同一个 (tag,id);要“多条并列”,用不同 id 或不同 tag。
    5. 前台服务:前台服务的通知由 startForeground(id, notification) 管理。要更新用 notify(id, ...);要移除必须 stopForeground(true)不要直接 cancel(id) 试图偷撤)。
    6. ID 取值int 任意,但前台服务 id 需 > 0。不建议复用 0
    7. 主线程调用:可以在主线程调用,但构建通知时的重资源操作(如大图 decode)最好放到后台,避免卡顿。

    使用示例:

    // 覆盖更新同一条:固定 id
    notificationManager.notify(1001, build("下载中 30%"));
    notificationManager.notify(1001, build("下载中 60%"));// 多条并列:不同 id
    notificationManager.notify(2001, build("张三:你好"));
    notificationManager.notify(2002, build("李四:在吗"));// 使用 tag 区分业务线
    notificationManager.notify("chat-zhangsan", 1, build("张三:你好"));
    notificationManager.notify("chat-lisi",     1, build("李四:在吗"));
    
  2. cancel —— 取消/移除通知

    把已经显示(或排队)的某条通知移除。参数与 notify 一致,(tag, id) 必须匹配到同一条通知。

通知的进阶技巧

通知显示样式

Android 有一套“可扩展样式(expanded styles)”,可以让通知在下拉或通知抽屉中显示更多内容或图像。常用几种:

1. BigTextStyle — 显示大段文本(长消息)
setStyle(new NotificationCompat.BigTextStyle().bigText("这是很长的文字... \n\n\n\n可以完整显示多行内容"))

场景:长消息预览、日志摘要等。

2. BigPictureStyle — 显示大图
setStyle(new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(), R.drawable.datu)))

注意:如果同时设置了 BigPictureStyle 与 BigTextStyle,某些设备/系统版本会以图片样式为主(长文可能不会全部展开)。如果你既要图又要长文本,需设计展示优先级或把长文本放在点击后进入的详情页。

3. InboxStyle — 多条汇总(像邮件列表)
setStyle(new NotificationCompat.InboxStyle().addLine("第一条消息").addLine("第二条消息").setSummaryText("+2 条"))

设备/系统版本会以图片样式为主(长文可能不会全部展开)。如果你既要图又要长文本,需设计展示优先级或把长文本放在点击后进入的详情页。

[外链图片转存中…(img-7ViMmcqh-1756631003433)]

3. InboxStyle — 多条汇总(像邮件列表)
setStyle(new NotificationCompat.InboxStyle().addLine("第一条消息").addLine("第二条消息").setSummaryText("+2 条"))

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

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

相关文章

Web前端开发基础

1.前端概论 1.1 什么是前端&#xff1f; 概念&#xff1a;前端(Front-End)&#xff0c;也称为客户端(Client-Side)&#xff0c;指的是用户在使用网站或Web应用时直接看到并与之交互的部分。它涵盖了屏幕上的一切内容&#xff0c;从文字、图片、按钮、布局到动画效果 一个简单的…

并发编程——11 并发容器(Map、List、Set)实战及其原理分析

1 JUC包下的并发容器Java 基础集合&#xff08;如 ArrayList、LinkedList、HashMap&#xff09;非线程安全。为了解决线程安全问题&#xff0c;Java 最初提供了同步容器&#xff08;如 Vector、Hashtable、SynchronizedList&#xff09;&#xff0c;但它们通过 synchronized 实…

Circuitjs 测试点的使用

在电路中, 有时候我们想知道, 各个节点上电压的具体的值. 比如下面这个电路:电流流经两个电阻器之后, 电压在下降. 如果想知道具体节点电压的确切数值, 可以通过添加 测试点(Test Point) 实现. 点击 绘制–输出和标签–添加测试点, 之后在所需测量的节点上拖动添加一个测试点, …

Ansible Playbook 实践

Ansible Playbook 实践一、Playbook 基础规范&#xff08;一&#xff09;YAML 格式要求文件标识&#xff1a;以 --- 开头&#xff0c;明确为 YAML 文件&#xff0c;结尾可加 ...&#xff08;可选&#xff0c;用于标记文件结束&#xff09;。注释规则&#xff1a;用 # 实现注释&…

基于 Vue + Interact.js 实现可拖拽缩放柜子设计器

实现可视化设计工具已成为前端开发的重要挑战之一。本文将介绍如何使用 Vue.js 配合 Interact.js 库创建一个功能完整的橱柜设计器&#xff0c;兼容PC和移动终端。核心功能网格系统&#xff1a;基于 CSS 网格实现精准定位拖拽功能&#xff1a;实现单元格的自由移动缩放控制&…

今日科技速递 | 智能芯片突围、AI+行动深化、服贸会科技成果亮相

今日科技速递 | 智能芯片突围、AI行动深化、服贸会科技成果亮相 一、乐鑫科技涨停&#xff1a;Wi-Fi 6/7 与 AIoT 芯片双路径创新驱动 新闻回顾 2025 年 8 月 27 日&#xff0c;科创板公司 乐鑫科技&#xff08;688018&#xff09; 盘中一度涨停&#xff0c;股价达到 225 元&am…

PDF压缩如何平衡质量与体积?

在日常工作或者生活中&#xff0c;我们常常要处理PDF文档&#xff0c;很多人可能会遇到这样的困扰&#xff1f;使用WPS处理PDF时&#xff0c;部分功能需要付费&#xff0c;这给我们带来了许多不便。 它的使用方式十分简单&#xff0c;你只要双击图标&#xff0c;它就能启动&am…

Flask 之上下文详解:从原理到实战

一、引言&#xff1a;为什么 Flask 需要“上下文”&#xff1f;在 Web 开发中&#xff0c;我们经常需要访问当前请求的信息&#xff08;如 URL、表单数据&#xff09;、当前应用实例&#xff08;如配置、数据库连接&#xff09;或用户会话状态。传统做法是使用全局变量&#xf…

深入探索Vue:前端开发的强大框架

在当今的前端开发领域&#xff0c;Vue作为一款备受瞩目的JavaScript框架&#xff0c;以其简洁易用、高效灵活等特性&#xff0c;赢得了众多开发者的青睐。无论是构建小型的交互页面&#xff0c;还是开发大型的单页应用&#xff0c;Vue都能展现出卓越的性能和出色的表现。本文将…

B树与B+树的原理区别应用

在磁盘存储和内存有序的数据管理中&#xff0c;B 树与 B 树是核心的数据结构&#xff0c;二者均通过 “多路平衡” 特性减少 IO 次数&#xff0c;但在数据存储方式、查询逻辑上存在本质差异。一、B 树&#xff08;Balance Tree&#xff09;&#xff1a;多路平衡搜索树B 树是 “…

从零到一:使用anisble自动化搭建kubernetes集群

在我们云原生俱乐部的暑期学习中&#xff0c;我们了解并学习了需要关于云原生的技术&#xff0c;其中在应用层面上最重要的就是shell编程和ansible&#xff0c;而想要掌握这两项技术离不开的就是实践&#xff0c;而kubernetes是我们云原生技术栈的核心技术&#xff0c;在生产实…

【LangGraph】langgraph.prebuilt.create_react_agent() 函数:快速创建基于 ReAct(Reasoning + Acting)架构的智能代理

本文是对 langgraph.prebuilt.create_react_agent 函数的详细且全面的介绍&#xff0c;涵盖其定义、功能、设计理念、参数、返回值、使用场景、实现原理、示例代码、高级用法、注意事项、与其他方法的对比&#xff0c;以及学习建议。 1. 概述 langgraph.prebuilt.create_react…

北斗导航 | RAIM算法改进方案及性能对比分析报告

github&#xff1a;https://github.com/MichaelBeechan CSDN&#xff1a;https://blog.csdn.net/u011344545 文章目录RAIM算法改进方案及性能对比分析报告一、RAIM算法改进技术框架1.1 多假设分组算法&#xff08;MHSS&#xff09;1.2 动态噪声估计算法1.3 多源信息融合技术二、…

数据结构第8章 排序(竟成)

第 8 章 排序【考纲内容】1.排序的基本概念&#xff1b;2. 直接插入排序&#xff1b;3. 折半插入排序&#xff1b;4. 起泡排序&#xff08;Bubble Sort&#xff09;&#xff1b;5.简单选择排序&#xff1b;6. 希尔排序&#xff08;Shell Sort&#xff09;&#xff1b;7. 快速排…

【学Python自动化】 5. Python 数据结构学习笔记

一、 列表详解 1 列表方法总结方法描述等价操作rust Vec类似操作list.append(x)末尾添加元素a[len(a):] [x]vec.push(x);list.extend(iterable)扩展列表a[len(a):] iterablevec.extend([4, 5, 6]); 或者更高效&#xff1a;vec.extend_from_slice(&[4, 5, 6]);list.inser…

Python爬虫实战:研究Radar chart,构建多维度数据采集和分析系统

1. 引言 1.1 研究背景与意义 在信息爆炸的时代,互联网蕴含的海量数据已成为企业决策、学术研究和产品评估的重要依据。这些数据往往包含多个维度的特征,如电商平台的商品信息涵盖价格、销量、评价、性能参数等,社交媒体的用户数据涉及活跃度、互动量、内容偏好等。传统的单…

[灵动微电子 MM32BIN560CN MM32SPIN0280]读懂电机MCU之串口DMA

在 MM32SPIN560C 微控制器中&#xff0c;串口&#xff08;UART&#xff09;的 DMA 传输可大幅减轻 CPU 负担&#xff0c;实现数据的“自动收发”。结合《MM32SPIN560C 用户手册&#xff08;中文版&#xff09;》中 UART 和 DMA 相关章节&#xff0c;以下从“原理匹配”“配置步…

【机器学习】-torch相关知识01

学习代码时遇到的问题&#xff0c;GPT给的答案&#xff0c;如有错误请指出。 问题1 torch.empty nn.init.xavier 问题2 nn.Parameter 是什么&#xff1f; 问题3 self.add_module 问题4 torch.matmul torch.mm 文章目录问题1 torch.empty nn.init.xavier问题2 nn.Parameter 是什…

Hutool DsFactory多数据源切换

一、简单上手&#xff1a;从配置到使用全流程 DsFactory 的核心优势是零侵入配置&#xff0c;支持多种配置方式&#xff0c;不管是 properties 文件还是代码里直接定义&#xff0c;都能快速初始化数据源。先引依赖&#xff08;Maven&#xff09;&#xff1a; <dependency>…

Mysql中事务隔离级别有哪些?

Mysql中事务隔离级别有哪些&#xff1f; 读未提交&#xff1a; 一个事务可以看到另一个事务尚未提交的数据。可能导致脏读。 读已提交&#xff1a; 一个事务只能看到其他事务提交后的数据。避免了脏读&#xff0c;仍可能引发不可重复读。 可重复读&#xff1a; 可以确保一个事务…