安卓消息推送通知栏功能实现与服务器集成Demo项目
本文还有配套的精品资源,点击获取
简介:在安卓应用开发中,消息推送是实现实时通知的关键功能,广泛用于系统提醒、社交消息和运营活动等场景。本资源“安卓消息推送通知栏相关-消息推送最新demo服务器.rar”提供了一套完整的消息推送实现示例,涵盖客户端通知栏展示与服务器端消息发送逻辑。项目基于Android平台的NotificationManager、NotificationChannel(适配Android O+)、NotificationCompat构建通知,并结合PendingIntent实现点击响应。同时支持与主流推送服务(如FCM)集成,涉及HTTP/HTTPS、MQTT等通信协议,帮助开发者快速搭建稳定的消息推送系统。附带的源码说明文件和扩展资源链接进一步提升了学习效率,适合有一定基础的开发者进行二次开发与优化。
Android消息推送系统深度解析:从底层机制到全链路实战
在智能家居设备日益复杂的今天,确保无线连接的稳定性已成为一大设计挑战。而当我们把目光转向移动应用生态时,会发现另一个更微妙却同样关键的技术战场—— 消息推送系统 。这看似简单的“叮咚”一声提醒背后,隐藏着一套精密协作的工程体系,它不仅关乎用户体验的流畅度,更是维系用户活跃度的生命线。
你有没有想过,为什么有些App即便被杀掉后台,依然能准时弹出通知?而另一些应用却总是在关键时刻“失联”?这其中的秘密,就藏在安卓系统的推送架构里。让我们从一个真实场景切入:小明正在地铁上刷短视频,突然收到一条银行交易提醒,“您尾号8888的账户支出299元”。这条信息是如何穿越重重网络屏障,在毫秒级时间内精准抵达他的手机,并以特定样式呈现出来的呢?
答案是: 这不是单一技术的胜利,而是云通道、系统服务、权限模型与交互设计共同编织的一张实时通信网 。本文将带你深入这场“数字快递”的幕后运作,彻底拆解Android消息推送的每一个齿轮如何咬合转动。
想象一下,如果你是一个刚接手推送模块的开发者,面对的第一个问题可能就是:“我该用轮询还是长连接?”
传统轮询就像个勤快但低效的邮差,每隔几分钟就跑去服务器问一句:“有我的信吗?”虽然实现简单,但它每小时唤醒CPU数十次,电量消耗惊人,用户体验自然大打折扣。
而现代方案选择了另一种哲学—— 统一通道 + 智能分发 。以FCM(Firebase Cloud Messaging)为代表的云推送服务,本质上是一个“国家级邮政枢纽”。所有App不再各自建站招人,而是统一接入这个高效中枢。Google通过预置在系统层的常驻连接,为全球数亿设备维持一条轻量级心跳通道。当你的服务器想要发送消息时,只需把包裹交给FCM,剩下的路由、投递、签收都由这套成熟基础设施完成。
但这套理想化的全球体系到了国内却遇到了“水土不服”——由于GMS缺失,华为、小米、OPPO等厂商纷纷自建推送通道。于是开发者被迫进入“多端适配地狱”:既要对接FCM,又要集成HMS Push、MiPush、OPPO Push……仿佛每个品牌都在修自己的铁路,轨距还不一样 😅。
幸运的是,我们手头有一个名为 消息推送最新demo服务器.rar 的实验包,里面藏着通往真相的钥匙。打开它的配置文件,你会发现一段典型的HTTP POST请求:
{
"to": "device_token",
"notification": {
"title": "新消息",
"body": "您有一条未读通知"
}
}
别小看这几行JSON,它们正是整个推送链条的起点。当你调用这个接口后,数据会先到达FCM网关,经过身份验证和格式校验,再通过那条神秘的TCP长连接,最终触发客户端的 onMessageReceived() 回调。紧接着,系统调用 NotificationManager 构建可视化提醒,形成完整的端到端闭环。
🎯 一句话总结当前状态 :我们已经站在了通知展示的最后一公里,前方就是
NotificationManager这座控制中心的大门。
NotificationManager:安卓通知系统的神经中枢
如果说FCM是快递干线物流,那么 NotificationManager 就是你家门口的智能信箱管理员。它不仅要决定信件是否放进箱子,还要控制灯亮不亮、响铃不响铃、能不能被孩子偷偷翻出来……这一切的背后,是一套高度结构化的权限与行为管理体系。
它到底是谁?在哪里工作?
NotificationManager 并非普通类那么简单。它是Android系统服务的一员,运行于独立的 system_server 进程中,由名为 NotificationManagerService 的核心组件驱动。这意味着每一次通知操作,其实都是跨进程通信(IPC)的结果。
来看这张揭示其真实身份的流程图:
graph TD
A[App Process] -->|getSystemService| B(NotificationManager)
B -->|Binder IPC| C[system_server]
C --> D[NotificationManagerService]
D --> E[StatusBarManagerService]
D --> F[Notification Ranker]
D --> G[Notification Listener Manager]
E --> H[Status Bar UI]
G --> I[Third-party Monitoring Apps]
看到了吗?你调用的 notify() 方法,最终会流转到 StatusBarManagerService 去绘制UI;系统还会根据用户设置、设备状态和优先级算法(Ranker),动态调整通知排序;而对于像“微信自动回复助手”这类第三方工具,则需要通过 NotificationListenerService 申请监听权限才能获取内容。
特别值得注意的是,从 Android 13(API 33)开始,Google 引入了运行时权限 POST_NOTIFICATIONS 。也就是说,即使你在Manifest里声明了权限,也必须主动向用户申请授权才能发通知!此举进一步强化了用户的控制权,但也给开发者带来了新的合规挑战。
如何正确获取这个“管理员”?
标准方式只有一个:通过上下文获取系统服务实例。
// Java 示例
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager == null) {
Log.e("Notification", "Failed to get NotificationManager instance");
return;
}
// Kotlin 示例
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE)
as NotificationManager
notificationManager ?: run {
Log.e("Notification", "Unable to retrieve NotificationManager")
return
}
虽然 getSystemService() 几乎不会返回null(因为NOTIFICATION_SERVICE是必选服务),但在某些定制ROM或测试环境中仍建议做空值判断,增强健壮性。
不过,仅仅拿到实例还不够。真正的挑战在于—— 如何让它听话地按照你的意图行事而不翻车?
这就引出了下一个关键点:初始化必须前置处理通知渠道(Channel)。因为在 Android 8.0 之后,没有渠道的通知就像没有邮编的信件,直接被退回。
下面是一个推荐的封装模式:
public class NotificationHelper {
private static final String CHANNEL_ID = "default_channel";
private NotificationManager manager;
private Context context;
public NotificationHelper(Context context) {
this.context = context.getApplicationContext(); // 防止内存泄漏
this.manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
createDefaultChannel(); // 确保渠道存在
}
@TargetApi(Build.VERSION_CODES.O)
private void createDefaultChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Default Channel";
String description = "Used for general notifications";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
channel.enableLights(true);
channel.setLightColor(Color.BLUE);
channel.enableVibration(true);
manager.createNotificationChannel(channel);
}
}
}
✨ 亮点解析 :
- 使用 getApplicationContext() 避免Activity引用导致的内存泄露;
- 渠道创建放在构造函数中,确保早于任何通知发送;
- 所有API调用都有版本判断保护,兼容旧系统;
- 推荐封装为单例工具类,供全局复用。
权限检查不能少:POST_NOTIFICATIONS的现实影响
很多开发者第一次在 Android 13 设备上调试时都会懵:“我都配置好了,为什么通知不出?” 答案往往就在权限上。
首先,在 AndroidManifest.xml 中声明:
然后在代码中动态申请:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
when {
ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED -> {
sendNotification()
}
shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS) -> {
showExplanationDialog { requestPermission() }
}
else -> {
requestPermission()
}
}
} else {
sendNotification()
}
private fun requestPermission() {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
REQUEST_CODE_POST_NOTIFICATIONS
)
}
这里有几个细节值得玩味:
- shouldShowRequestPermissionRationale() 可以判断用户是否曾拒绝过权限,从而决定是否弹窗解释用途;
- 即使获得了 POST_NOTIFICATIONS ,仍需调用 areNotificationsEnabled() 检查用户是否在系统设置中完全关闭了通知开关;
- 如果发现被禁用,可以引导用户跳转至设置页:
if (!manager.areNotificationsEnabled()) {
Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
context.startActivity(intent);
}
🔔 经验之谈 :我在某电商项目中就遇到过这种情况——测试机一切正常,上线后大量用户反馈“收不到订单提醒”。排查才发现,他们在安装时直接点了“不允许”,后续也没有手动开启。后来我们在冷启动时增加了友好提示,转化率提升了近40%!
发送与取消通知:不只是调个API那么简单
现在我们终于拿到了“信箱管理员”的钥匙,接下来要做的就是投递第一封信。但别急,这里面也有不少门道。
notify(id, notification):你以为只是显示,其实暗藏更新逻辑
核心方法很简单:
public void sendSimpleNotification(int id) {
Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("新消息")
.setContentText("您有一条未读消息")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.build();
notificationManager.notify(id, notification);
}
但注意那个 id 参数!它不仅是标识符,更是去重的关键。系统依据ID进行管理:如果相同ID的通知已存在,则更新其内容;否则新建一条。
所以聪明的做法是按业务类型划分ID区间:
| ID 范围 | 用途 |
|---|---|
| 0 – 999 | 即时消息通知 |
| 1000 – 1999 | 系统提醒(订单、支付) |
| 2000 – 2999 | 下载任务进度 |
| 3000 – 3999 | 定位与导航事件 |
这样既能避免冲突,又能快速定位问题。
另外, notify() 是非阻塞的,调用后立即返回,实际渲染由系统异步处理。适合用于频繁更新的场景,比如下载进度条。
取消通知:cancel vs cancelAll,选择的艺术
有两种主要方式:
// 取消特定通知
notificationManager.cancel(NOTIFICATION_ID_MESSAGE);
// 清空所有通知
notificationManager.cancelAll();
选择哪个取决于业务逻辑:
- 用户点击通知进入聊天界面 → 应 cancel() 清除该条;
- “清除所有通知”按钮 → 调用 cancelAll() ;
- 正在录音或播放音乐 → 即使清空也不能消失,要用 setOngoing(true) 标记为常驻通知。
⚠️ 特别提醒:
cancelAll()不会影响标记为setOngoing(true)的通知,这类只能通过再次调用cancel()显式移除。
ID管理进阶:类型+主键哈希,打造永不重复的唯一ID
对于复杂应用,简单的数字ID不够用了。我们需要一种更具语义性的生成策略:
public int generateNotificationId(String type, long businessId) {
int typeId = type.hashCode() % 1000; // 类型标识
int bizId = (int) (businessId % 1_000_000); // 业务主键截断
return typeId * 1_000_000 + bizId;
}
// 示例:消息来自用户ID=123456789
int id = generateNotificationId("message", 123456789); // 得到唯一ID
这个算法保证了同一实体始终使用相同ID,从而实现内容更新而非新增。支持最大约 1000 种类型 × 百万级主键的映射空间,足够大多数场景使用。
配合SharedPreferences还能实现防抖机制:
private void updateLastNotificationTime(int id, long time) {
SharedPreferences sp = context.getSharedPreferences("notifs", Context.MODE_PRIVATE);
sp.edit().putLong("last_notify_" + id, time).apply();
}
private boolean shouldSuppressDuplicate(int id, long thresholdMs) {
long last = context.getSharedPreferences("notifs", Context.MODE_PRIVATE)
.getLong("last_notify_" + id, 0);
return SystemClock.elapsedRealtime() - last < thresholdMs;
}
比如设定阈值为3秒,防止短时间内重复推送相同内容,简直是防“轰炸式营销”的利器 🛡️。
通知渠道(NotificationChannel):用户主权时代的到来
还记得以前那些动不动就弹窗、响铃、震动的应用吗?它们的时代已经结束了。自 Android 8.0 起,Google 推行“用户主导通知体验”的理念,引入了 通知渠道(NotificationChannel) 机制。
这意味着什么?意味着你不能再“一揽子”开启所有通知行为。每一个通知类别都必须单独注册渠道,并接受用户的最终裁决。
为什么要这么麻烦?
因为在过去,用户只有两个选项:允许所有通知 or 完全禁止。一旦某个App滥用通知,用户往往会选择极端措施——关闭全部通知,结果连重要提醒也错过了。
而现在,他们可以做到:
- 允许“好友消息”播放声音并弹出横幅;
- 将“系统公告”设为静音但保留在通知栏;
- 完全屏蔽“促销活动”类通知。
这种精细化控制极大提升了自主性,也倒逼开发者必须认真分类设计。
来看看这个决策流程:
flowchart TD
A[用户安装应用] --> B{是否允许通知?}
B -->|否| C[无任何通知]
B -->|是| D[系统列出所有通知渠道]
D --> E[用户逐个配置每个渠道]
E --> F[应用只能按用户设定发送对应通知]
F --> G[用户可随时返回设置修改]
看到了吗?整个链条中, 用户才是最终决策者 。这也意味着我们必须做好降级处理与反馈提示。
渠道的重要性等级:决定命运的核心参数
在 Android 8.0 之前,优先级由 setPriority() 控制;现在取而代之的是 importance 级别,它直接影响以下行为:
- 是否发出声音;
- 是否启用震动;
- 是否点亮屏幕;
- 是否在锁屏上可见;
- 是否以横幅形式弹出;
- 是否绕过免打扰模式。
以下是各等级对比表:
| Importance Level | 值 | 行为特征 | 适用场景 |
|---|---|---|---|
| IMPORTANCE_NONE | 0 | 无声音、无震动、不弹出 | 后台同步、统计上报 |
| IMPORTANCE_MIN | 1 | 静默通知,仅出现在折叠面板 | 文件下载完成 |
| IMPORTANCE_LOW | 2 | 可选震动,无声音,小图标展示 | 日程提醒、普通更新 |
| IMPORTANCE_DEFAULT | 3 | 默认铃声 + 可选震动,支持横幅 | 普通消息提醒 |
| IMPORTANCE_HIGH | 4 | 强提醒:声音、震动、横幅弹出 | 即时通讯、来电提醒 |
| IMPORTANCE_CRITICAL | 5 | 最高优先级,可打断免打扰模式 | 紧急报警、安全警告 |
⚠️ 注意: 一旦渠道创建完成,其 importance 值不可更改 。若需调整,必须删除原渠道并重建(ID相同视为同一渠道)。因此首次创建时必须谨慎评估!
举个例子:社交App应为“私聊消息”创建 HIGH 级别渠道,而“群组@全体成员”则设为 DEFAULT ,避免过度打扰。
创建渠道的最佳实践
完整示例如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "chat_message_channel";
String channelName = "聊天消息";
String description = "接收来自好友的实时文字消息";
NotificationChannel channel = new NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_HIGH
);
channel.setDescription(description);
Uri soundUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.message_tone);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
channel.setSound(soundUri, audioAttributes);
channel.enableVibration(true);
channel.setVibrationPattern(new long[]{0, 100, 200, 300});
channel.enableLights(true);
channel.setLightColor(Color.BLUE);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
🔍 逐行解读 :
- 必须加版本判断,防止低版本崩溃;
- setSound() 一定要绑定 AudioAttributes ,否则可能无声;
- setVibrationPattern() 数组表示 [延迟, 第一次震动, 延迟, 第二次震动…];
- setLockscreenVisibility() 控制锁屏时是否显示敏感内容;
- 推荐在 Application.onCreate() 中批量注册所有渠道,确保早于任何通知发送。
渠道ID命名规范:让维护变得轻松
渠道ID是系统识别的唯一依据,必须满足:
- 全局唯一;
- 不可变(发布后不能改);
- 语义清晰;
- 支持国际化。
推荐格式: [功能域]_[子类型]_[行为特征]
示例:
- message_direct_high
- update_app_reminder_low
- alarm_emergency_critical
避免中文、空格或特殊字符。建议定义常量类集中管理:
public class NotificationChannelIds {
public static final String CHAT_MESSAGE = "chat_message";
public static final String GROUP_ANNOUNCEMENT = "group_announce";
public static final String DOWNLOAD_COMPLETE = "download_done";
public static final String PROMOTIONAL = "promo_marketing";
}
这样既便于引用,也有利于后期维护与多语言适配。
NotificationBuilder:打造专业级通知体验
有了渠道,接下来就要精心设计通知本身了。 NotificationCompat.Builder 是构建通知的核心类,它提供了丰富的API来定义外观、行为与交互。
基础属性设置:标题、内容、图标
Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("新消息提醒")
.setContentText("您有一条未读的系统通知,请及时查看。")
.setSubText("来自系统服务")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.build();
📌 注意事项:
- smallIcon 必须为纯白alpha图层,否则深色主题下看不见;
- contentTitle 不超过两行, contentText 控制在200字符内;
- subText 添加辅助信息,如发送人或时间;
- 从 Android 12 起, setPriority() 已被废弃,应完全依赖渠道重要性。
图标加载优化:避免OOM的小技巧
largeIcon(Bitmap) 接收位图对象,但直接传大图易引发内存溢出。应采用压缩策略:
Bitmap largeBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.avatar_user);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(largeBitmap, 64, 64, true);
new NotificationCompat.Builder(context, CHANNEL_ID)
.setLargeIcon(scaledBitmap)
.build();
如果是网络图片,推荐用 Glide/Picasso 异步加载转换。
还可以制作圆形头像提升视觉一致性:
Resources res = context.getResources();
Bitmap srcBitmap = BitmapFactory.decodeResource(res, R.drawable.avatar);
RoundedBitmapDrawable roundDrawable = RoundedBitmapDrawableFactory.create(res, srcBitmap);
roundDrawable.setCircular(true);
高级样式扩展:BigTextStyle、InboxStyle、MediaStyle
BigTextStyle:长文本展开效果
适用于新闻摘要、邮件预览:
String longMessage = "这是一段非常长的消息内容……最多支持约500个字符。";
new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_mail)
.setContentTitle("收到一封新邮件")
.setContentText("点击查看完整内容")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(longMessage)
.setSummaryText("from: service@example.com"))
.build();
InboxStyle:多条目汇总展示
适合聚合多个事件:
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle()
.addLine("• 支付宝账单已出,请查收")
.addLine("• 会议邀请:明天上午10点")
.addLine("• 密码即将过期,请尽快修改")
.setSummaryText("+3 条未读");
new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_inbox)
.setContentTitle("今日提醒汇总")
.setStyle(inboxStyle)
.build();
MediaStyle:音频播放控制集成
音乐类App必备:
Intent playIntent = new Intent(context, MediaPlayerService.class);
playIntent.setAction(ACTION_PLAY);
PendingIntent pendingPlay = PendingIntent.getService(context, 0, playIntent, FLAG_IMMUTABLE);
new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_music)
.setContentTitle("夜曲")
.setContentText("周杰伦 · 专辑《十一月的萧邦》")
.setStyle(new NotificationCompat.MediaStyle()
.setMediaSession(sessionToken)
.setShowActionsInCompactView(0, 1))
.addAction(createAction(R.drawable.ic_prev, "上一曲", ACTION_PREV))
.addAction(createAction(R.drawable.ic_play, "播放", ACTION_PLAY))
.addAction(createAction(R.drawable.ic_next, "下一曲", ACTION_NEXT))
.build();
🔐 自 Android 12 起,所有
PendingIntent必须显式声明是否可变(mutable),否则抛异常。
PendingIntent:打通通知交互的最后一环
通知不仅仅是看的,更是用来操作的。 PendingIntent 就是实现点击跳转、快捷回复等功能的核心机制。
它是什么?怎么工作?
简单说, PendingIntent 是一个“未来可执行的意图句柄”。你可以把它理解为一张支票:你现在开出,别人(系统)在未来某个时刻兑现。
它有三种类型:
| 类型 | 方法 | 用途 |
|------|------|------|
| Activity | getActivity() | 跳转页面 |
| BroadcastReceiver | getBroadcast() | 触发本地逻辑 |
| Service | getService() | 启动后台任务 |
示例:
// 跳转主页面
Intent activityIntent = new Intent(context, MainActivity.class);
activityIntent.putExtra("from_notification", true);
PendingIntent pi = PendingIntent.getActivity(
context,
0,
activityIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);
⚠️ Android 12+ 必须显式声明
FLAG_IMMUTABLE或FLAG_MUTABLE,否则报错。
安全防护:防止Intent注入攻击
常见风险包括:
- 使用隐式Intent导致任意应用响应;
- Extras中传入可执行代码;
- 请求码重复导致覆盖。
应对策略:
// ✅ 正确做法:显式Intent + ComponentName
Intent intent = new Intent();
intent.setComponent(new ComponentName(context, NotificationReceiver.class));
intent.putExtra("data", safeValue);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, FLAG_IMMUTABLE);
目标组件也应做二次校验:
if ("notification".equals(intent.getStringExtra("source"))) {
long msgId = intent.getLongExtra("message_id", -1);
if (msgId > 0) {
loadMessage(msgId);
nm.cancel(intent.getIntExtra("notify_id", 0));
} else {
finish();
}
} else {
finish();
}
FCM集成:构建全球化推送能力
最后回到开头提到的FCM。它是目前最稳定高效的跨平台推送方案。
架构原理
三方模型:
[App Server] --HTTPS--> [FCM Server] --TCP--> [Client App]
每个设备都有唯一的 registration token ,用于精准投递。
客户端集成步骤
- 下载
google-services.json放入app/目录; - 添加Gradle插件;
- 继承
FirebaseMessagingService重写回调;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
if (remoteMessage.getNotification() != null) {
showNotification(remoteMessage.getNotification());
}
if (remoteMessage.getData().size() > 0) {
handleDataMessage(remoteMessage.getData());
}
}
@Override
public void onNewToken(@NonNull String token) {
sendTokenToServer(token);
}
}
服务端发送消息
使用 HTTP v1 API:
curl -H "Authorization: Bearer ya29.c.ElqGB..."
-H "Content-Type: application/json"
-d @message.json
https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send
payload 示例:
{
"message": {
"token": "fcm_token_here",
"notification": {
"title": "订单已发货",
"body": "您的商品正在派送途中"
},
"data": {
"order_id": "ORD123456",
"action": "open_order_detail"
}
}
}
总结与展望
这种高度集成的设计思路,正引领着智能应用向更可靠、更高效的方向演进。无论是从底层的 NotificationManager 控制,还是上层的 FCM 全链路打通,每一个环节都在追求极致的用户体验与资源利用率平衡。
未来的推送系统可能会更加智能化:基于用户行为预测最佳发送时机,结合AI生成个性化文案,甚至利用边缘计算实现毫秒级本地化响应。但无论如何演变, 以用户为中心、尊重选择权、保障安全性 这三大原则永远不会改变。
而我们作为开发者,要做的就是在这条不断进化的技术轨道上,持续打磨每一行代码,让每一次“叮咚”都成为有价值的信息传递,而不是恼人的噪音污染 💡🚀。
本文还有配套的精品资源,点击获取
简介:在安卓应用开发中,消息推送是实现实时通知的关键功能,广泛用于系统提醒、社交消息和运营活动等场景。本资源“安卓消息推送通知栏相关-消息推送最新demo服务器.rar”提供了一套完整的消息推送实现示例,涵盖客户端通知栏展示与服务器端消息发送逻辑。项目基于Android平台的NotificationManager、NotificationChannel(适配Android O+)、NotificationCompat构建通知,并结合PendingIntent实现点击响应。同时支持与主流推送服务(如FCM)集成,涉及HTTP/HTTPS、MQTT等通信协议,帮助开发者快速搭建稳定的消息推送系统。附带的源码说明文件和扩展资源链接进一步提升了学习效率,适合有一定基础的开发者进行二次开发与优化。
本文还有配套的精品资源,点击获取







