个人开发者如何把应用送上荣耀灵动胶囊:Android 16 实时通知实战
个人开发者如何把应用送上荣耀灵动胶囊:Android 16 实时通知实战
荣耀 MagicOS 的”灵动胶囊”(屏幕顶部那颗药丸,对标 iPhone 灵动岛)看起来像是系统深度绑定的特性——12306 行程、外卖进度、打车车牌都在上面。个人开发者写的 App 还能上吗?
结论:能,而且不用联系荣耀、不用签任何生态合作协议。本文记录我把一个番茄钟 × 呼吸训练应用(“胶囊专注”)实时显示到灵动胶囊上的完整过程:调研、逆向参考开源项目、最小 Demo 验证、应用化落地,以及排障方法。
1. 先搞清楚:上胶囊有几条路
调研下来,三方应用接入灵动胶囊实际存在三条路径:
| 路径 | 门槛 | 适用 |
|---|---|---|
| YOYO建议 / 智慧服务生态合作 | 需在荣耀开发者服务平台签署合作协议,场景由荣耀筛选,无完全公开的自助 API | 12306、外卖、打车这类富场景卡片 |
| MediaSession / MediaStyle | 零门槛,按 Android 标准写 | 音乐、播客等媒体播放类 |
| Android 16 Live Updates | 零合作门槛,targetSdk 36 + 标准通知 API | 下载/任务进度、倒计时等一切”进行中的状态” |
第三条路是 Android 16(API 36)新增的 Live Updates(底层叫 promoted ongoing notifications,“可提升的常驻通知”):应用发出一条带特定标记的常驻通知,系统判定可以”提升”后,支持该特性的 ROM 会自动把它渲染成灵动岛式的 UI——荣耀叫灵动胶囊,小米、OPPO 也有各自的形态。一套标准 API,多端生效。
2. 逆向参考:Kelivo 是怎么做的
灵感来自 Kelivo(开源 Flutter LLM 客户端)。它在荣耀手机上能把 AI 生成任务显示到灵动胶囊上,设置页里有一个”实时通知 / 灵动岛”开关,描述写着”在支持的设备上使用 Android 16 实时通知”:


注意第二张图那句”系统成功展示实时通知时优先于悬浮窗”——这是一条重要的产品逻辑:胶囊显示成功就用胶囊,失败则降级为自绘悬浮窗。
它是开源的,翻源码(BackgroundRuntime.kt)找到了核心实现,去掉业务逻辑后就是这么几行:
if (Build.VERSION.SDK_INT >= 36 && canPromote()) {
val style = Notification.ProgressStyle()
.addProgressSegment(Notification.ProgressStyle.Segment(100))
.setStyledByProgress(false)
.setProgressIndeterminate(true)
Notification.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_task)
.setContentTitle(title).setContentText(content)
.setStyle(style)
.setOngoing(true) // 必须是 ongoing
.addExtras(Bundle().apply {
putBoolean("android.requestPromotedOngoing", true) // 请求提升
})
.build()
}
配套四个关键 API:
| API | 作用 |
|---|---|
Notification.ProgressStyle | API 36 新增的通知样式,进度条支持分段着色 |
extra android.requestPromotedOngoing = true | 请求系统把这条 ongoing 通知”提升”为实时通知 |
NotificationManager.canPostPromotedNotifications() | 检查本应用是否有资格(对应系统设置里每个应用独立的”实时通知”开关) |
Notification.FLAG_PROMOTED_ONGOING | 发布后检查系统是否真的提升了它 |
整个方案里没有任何荣耀私有代码——这就是个人开发者的正路。
3. 最小 Demo:一小时验证
照着 Kelivo 写了个最小验证工程:compileSdk = 36、targetSdk = 36,Manifest 声明两个权限:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- Android 16 实时通知(灵动胶囊)所需 -->
<uses-permission android:name="android.permission.POST_PROMOTED_NOTIFICATIONS" />
一个按钮触发 0→100 的模拟下载,每秒 notify() 更新进度。发布 600ms 后检查 FLAG_PROMOTED_ONGOING(系统在 notify() 之后才打这个标志,要稍等再查):
val promoted = nm.activeNotifications.any {
it.id == NOTIFICATION_ID &&
it.notification.flags and Notification.FLAG_PROMOTED_ONGOING != 0
}
装到荣耀手机上,授予通知权限、打开该应用的”实时通知”开关,胶囊立刻出现。从零到胶囊显示,一个下午足够。
两个工程外的坑提前说:
- API 36 平台要单独装:
sdkmanager "platforms;android-36"; - AGP 在 Windows 上拒绝含中文的工程路径(
Your project path contains non-ASCII characters),移到纯英文目录即可;国内网络还要给 Gradle 发行版和 Maven 仓库配镜像。
4. 应用化:胶囊专注(番茄钟 × 呼吸训练)
Demo 验证后做成真实应用,把这条 API 的能力边界全部用满。
4.1 番茄钟:胶囊原生倒计时
专注/休息阶段用系统的 chronometer 倒计时——设 setWhen(结束时间戳) + setUsesChronometer(true) + setChronometerCountDown(true),剩余时间由 SystemUI 自己跳,App 不刷新它也在走:
b.setWhen(endsAtMillis)
.setUsesChronometer(true)
.setChronometerCountDown(true)
进度条用 ProgressStyle 单色段扫过,专注段靛蓝、休息段橙色,一眼区分状态。
4.2 呼吸训练:分段彩色进度条
呼吸的节奏(吸气-屏息-呼气-屏息)天然适合 ProgressStyle 的多段彩色进度:一轮 4-7-8 呼吸(19 秒)拆成三段,按各自时长分配段长,颜色区分阶段——吸气蓝、屏息青、呼气绿。setStyledByProgress(true) 让进度扫过的部分显示段色、未到的部分变暗,节奏感直接画在了胶囊上:
val style = Notification.ProgressStyle()
pattern.phases.forEach { ph ->
style.addProgressSegment(
Notification.ProgressStyle.Segment(ph.seconds).apply { setColor(ph.color) })
}
style.setStyledByProgress(true)
style.setProgress(elapsedPctOfRound)
呼吸阶段秒数太短,chronometer 来不及用,改为每秒重建通知、文字显示”第 3/8 轮 · 吸气 4s”。每秒一次 notify() 的开销可以忽略。
4.3 保活:前台服务 + WakeLock
真实会话长达 25-45 分钟,锁屏后进程随时可能被杀。照搬 Kelivo 的保活组合:
dataSync类型的前台服务,把这条胶囊通知直接挂为前台通知(startForeground用同一个 notification id);- PARTIAL_WAKE_LOCK 保证息屏后 Handler 每秒 tick 不被打断。
Manifest 还要加 FOREGROUND_SERVICE、FOREGROUND_SERVICE_DATA_SYNC 两个权限和 android:foregroundServiceType="dataSync"。注意 Android 15+ 对 dataSync 前台服务有 6 小时上限,实现 onTimeout 兜底收尾。
4.4 通知上的操作按钮
addAction 加”暂停/跳过/结束”,走 PendingIntent.getBroadcast 到一个 manifest 里 exported="false" 的 receiver——通知按钮的上限是 3 个,正好。
5. 界面与图标:让它像”真的 App”
UI 用 Material 3 重写,但配色不跟 Material You 动态色走,固定为构成主义品牌色(正红 #E63328 + 米白 #F2EDE4 + 墨黑),深浅两套主题分别调对比度。首页是模式卡片 + 筛选芯片,运行页是大字倒计时 + 与胶囊进度条同色的进度条。
图标把 GPT 生成的构成主义 logo(圆环 + 15° 倾斜胶囊 + 红楔)重建成矢量,而不是直接贴位图:
- 前景缩放进自适应图标安全区(启动器圆形裁切不伤主体),红楔保留出血;
- 同一构图派生 Android 13+ 主题单色图标;
- 通知小图标单独勾一版纯白剪影——系统通知小图标只认 alpha 通道,彩色 logo 放上去会糊成一团。






6. 排障:胶囊没出现,查什么
App 内发布 600ms 后读 FLAG_PROMOTED_ONGOING 并显示在界面上,三态一目了然。胶囊不显示时按这个顺序查:
- 通知权限没给 —— 基础前提;
- 系统”实时通知”开关没开 —— 设置 → 通知和状态栏 → 灵动胶囊,找到对应应用(代码里可深链
Intent("android.settings.MANAGE_APP_PROMOTED_NOTIFICATIONS")直达);按包名单独授权,换包名等于重开; - API < 36 —— 老系统没有这条通道,只能普通常驻通知;
- 通知不是 ongoing,或没带
requestPromotedOngoingextra; - 媒体类通知 —— 官方明确不合资格,音乐请走 MediaSession;
- ROM 不支持 —— 该 API 需要厂商适配渲染,老 MagicOS 不认。

7. 关于上架:想好了再走
荣耀应用市场对个人开发者开放,提审后 1-3 个工作日出结果,流程本身不复杂。慢的是前置资质:软著(官方通道免费但 1-2 个月,电子版权可加急)和 APP 备案(工信部强制,需云服务商接入,1-2 周),且应用名、软著名、备案名三者必须一致。包名规则上,.honor 后缀是渠道包差异化的要求,全渠道统一包名一般可复用。个人小工具前期发酷安 / GitHub Releases 更轻,认真运营再走商店。
8. 小结
- 灵动胶囊不是厂商的”专利围墙”:Android 16 Live Updates 是公开标准,个人开发者零合作门槛可用,一次开发、多品牌 ROM 自动适配;
- 方案核心一句话:ongoing 通知 + ProgressStyle +
android.requestPromotedOngoing+POST_PROMOTED_NOTIFICATIONS权限; - 产品逻辑参考 Kelivo:胶囊成功则用胶囊,失败降级普通通知/悬浮窗,永远有退路;
- 内容形态边界:标题 + 文本 + 进度条 + 3 个按钮,富场景卡片(订单、行程)仍需厂商生态合作;
- 最容易被忽略的一步:按包名单独开启系统的实时通知开关,几乎所有人第一次都卡在这。
示例工程:LiveCapsuleDemo(最小验证)与 CapsuleFocus(完整应用)均为零第三方依赖的 Kotlin 实现,需要源码可以在评论区喊我。
