【高密级】Alive Status(灵动岛)技术接入文档
📌 需求概述
- 灵动的智能的车辆状态变化,以 Alive Status 的方式告诉用户
- 后台运行的任务,以最轻量的方式显示最核心的状态,并提供不离开用户当前任务的快捷操作
基础配置
Alive Status 基于通知接口实现,先参考 通知的介绍及使用 配置必需的权限,并了解一下通知的常规使用。
引入 HyperX
按照文档 HyperX Core 引入 HyperX Core 组件。
灵动岛类型
按照文档 通知扩展 API 设置灵动岛类型和显示方式。
显示内容
4.1 迷你岛(状态栏)
- 图标:使用 Notification.Builder#setLargeIcon 传入。
- eg:
setLargeIcon(Icon.createWithResource(context, R.drawable.xxx))
- eg:
- 边框颜色:使用 Notification.Builder#setColor 设置,不传入则按默认背景显示,色值不要带透明度。
- 进度条样式:
- 进度使用 Notification.Builder#setProgress。
- 进度条颜色使用 Notification.Builder#setColor。
- 第二段进度:Notification.Builder#setSecondProgress。
- 第二段进度颜色:Notification.Builder#setSecondColor。
- 点击行为(按顺序处理):
- 变成通知:只要通知渠道的 importance 设置成 IMPORTANCE_HIGH,点击会变成通知。
- 打开应用界面:如果通知渠道的 importance 设置成 IMPORTANCE_DEFAULT,使用 Notification.Builder#setContentIntent 设置页面,则打开页面。
- 无响应:以上条件皆不满足,则无响应。
4.2 小岛(状态栏)
- 左侧图标:使用 Notification.Builder#setLargeIcon 传入。
- eg:
setLargeIcon(Icon.createWithResource(context, R.drawable.xxx))
- eg:
- 文本:使用 Notification.Builder#setSubText 传入。
- 边框/进度条颜色:使用 Notification.Builder#setColor 设置,不传入则按默认背景显示,色值不要带透明度。
- 自定义布局:使用 Notification.Builder#setCustomContentView。
- 进度条样式:
- 进度使用 Notification.Builder#setProgress。
- 进度条颜色使用 Notification.Builder#setColor。
- 第二段进度:Notification.Builder#setSecondProgress。
- 第二段进度颜色:Notification.Builder#setSecondColor。
- 计时器样式:
- 计时器类型:Notification.Builder#setTimerType。
- 正计时:
HyperNotificationCompat.ALIVE_TIMER_TYPE_COUNT_UP - 正计时暂停:
HyperNotificationCompat.ALIVE_TIMER_TYPE_COUNT_UP_PAUSE - 倒计时:
HyperNotificationCompat.ALIVE_TIMER_TYPE_COUNT_DOWN - 倒计时暂停:
HyperNotificationCompat.ALIVE_TIMER_TYPE_COUNT_DOWN_PAUSE
- 正计时:
- 计时起点:Notification.Builder#setTimerWhen。
- 计时进度(倒计时使用):Notification.Builder#setTimerTotal。
- 计时器类型:Notification.Builder#setTimerType。
- 点击行为(按顺序处理):
- 变成通知:只要通知渠道的 importance 设置成 IMPORTANCE_HIGH,点击会变成通知。
- 打开应用界面:如果通知渠道的 importance 设置成 IMPORTANCE_DEFAULT,使用 Notification.Builder#setContentIntent 设置页面,则打开页面。
- 无响应:以上条件皆不满足,则无响应。
- 如果要只显示小岛,通知渠道的 importance 设置成 IMPORTANCE_DEFAULT 即可。
4.3 中岛(通知)
- 自定义布局:使用 Notification.Builder#setCustomHeadsUpContentView。
- 不提供标准模板,不要使用 setContentTitle、setContentText 等接口去设置。
- 卡片最大宽度 632dp,可以使用 match_parent 填满宽度,也可以使用 wrap_content 根据内容自适应宽度,也可以自定义宽度,但不能超过卡片最大宽度。高度按内容自适应。
边框颜色:使用Notification.Builder#setColor设置,不传入则按默认背景显示,色值不要带透明度。- 进度条样式:
- 进度使用 Notification.Builder#setProgress。
- 进度条颜色使用 Notification.Builder#setColor。
- 第二段进度:Notification.Builder#setSecondProgress。
- 第二段进度颜色:Notification.Builder#setSecondColor。
- 光效动画是否顺时针旋转,默认 true:Notification.Builder#setClockwise。
- 点击行为:
- 打开应用界面:使用 Notification.Builder#setContentIntent 设置。
- 无响应:以上未设置则无响应。
4.4 巨岛(PHUD)
-
方式一:自定义布局:使用 Notification.Builder#setCustomBigContentView。此方法对实现复杂 UI 和动效有约束。
-
方式二:使用通知扩展 API 中的 1.11 状态变化回调,业务监听灵动岛的状态变化,调用
PHUDNotificationManager显示和消失。接入方式:-
如果是 Bp 编译需要额外引入 SDK:
static_libs: [ "phud-card-dynamic", "phud-scene-kit", "phud-card-common", ] -
添加权限(android.permission.INTERACT_ACROSS_USERS 是 privileged permission):
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" tools:ignore="ProtectedPermissions" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" tools:ignore="ProtectedPermissions" /> -
示例代码:
// 获取单例 PHUDNotificationManager phudNotificationManager = PHUDNotificationManager.getInstance(context); // 显示巨岛 phudNotificationManager.show(view); // 移除巨岛 phudNotificationManager.remove(view);
-
必传内容(研发必看!!!)
为了方便产品埋点分析,要求业务方必须传入如下字段。
5.1 岛名字
业务需要按照 通知扩展 API 中 setOneTrack() 传递埋点字段,字段内容按文档 Alive Status 业务-岛-setOneTrack 查询字典 规范使用,如果没有的可以联系 牛航 确认。
5.2 时间戳
为了统计每个功能灵动岛存在的时长,要求业务通过 android.app.Notification.Builder#setWhen 接口传入时间戳。
该字段要求传入第一次发送灵动岛的当前时间,后续更新灵动岛请务必仍然使用这个第一次发送的时间。单位 ms。
提示音
首次出现在通知/状态栏及强调时可发出音效,默认为通知提示音,如需定制提示音或静音,通过通知渠道 NotificationChannel#setSound 设置。
其它配置
- Notification.Builder#setOnlyAlertOnce
- true:当灵动岛进入状态栏时,更新通知不会变成浮动通知。
- false(默认):当灵动岛进入状态栏时,更新通知会变成浮动通知。
Notification.Builder#setOngoing(无论什么类型的中岛都不能左右滑动消失了)true:持续活动类中岛如需要左右滑动不消失,需要配置为 true。false:默认值,左右滑动可消失。
- Notification.Builder#setFullScreenIntent(PendingIntent intent, boolean highPriority)
- intent:通知默认显示 8 秒消失,如果需要通知显示后不自动消失,可以将通知点击事件的 PendingIntent 传入这个字段,如果没有点击跳转行为,可以传入一个空实现,但传入 null 一样会自动消失。另外点击卡片后也会消失。
- highPriority:true/false 皆可,无影响。
- 需要加权限:
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
- Notification.Builder#setDeleteIntent:用户取消通知时会收到回调。
动效
灵动岛在通知和状态栏之间切换动画、卡片内部标准模板的动画由 SystemUI 内部实现。
业务如需自定义动画效果,通过 RemoteViews 自定义布局,并采用如下可实现的方案,这里提供博客供参考:
- 帧动画和动态图片:Android小技巧:在通知RemoteViews中显示动画
- 首次加载或点击更新时动效方案,可实现 View 动画:Android-桌面小组件RemoteViews播放动画_remoteview 小部件加载gif-CSDN博客
调试与测试
9.1 前提
车机上的通知需要满足以下条件才能显示,请确保都满足:
- 电源模式需处于 ACC 或 RUN,可以通过 mock 修改:
adb root
adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle --mock_from_car 0x61407207 -i 2最后一个数字是 2 或 3 皆可。
也给大家提供一个脚本,方便台架上直接使用:
📎 [附件: mock 电源模式 shell 脚本](token: GAGhboQywodcn0xhcRRc0mfNnXc,下载 403,未保存到本地)
- 确保在”设置 - 系统 - 应用管理 - 右上角三个点 - 权限管理 - 通知”里你的应用的通知开关是打开的状态。
另外请使用 user-debug 或 user-root 包,并保证日志级别至少是 debug,方便排查问题时输出有效日志。
如果还未出现按 通知的介绍及使用 10.1 节排查一下。
9.2 日志
通知通用的日志请参考 通知的介绍及使用 第 9 节。
灵动岛相关日志:
TAG: MiCarNotificationListener
# 进入状态栏
postStatusBarNotification: [userId|pkg|id|tag|uid], isSeen=[true/false]
# 从状态栏移除
removeStatusBarNotification: [userId|pkg|id|tag|uid]
# PHUD 显示
postPHUDNotification: [userId|pkg|id|tag|uid]
# PHUD 移除
removePHUDNotification: [userId|pkg|id|tag|uid]TAG:CarHeadsUpNotificationManager
# 状态栏点击显示通知
Force show as HUN
# 仅在状态栏显示
Unable to show as HUN: only show in status bar模板代码
val chargeRemoteView =
RemoteViews(packageName, R.layout.remote_view_alive_status_charge)
val channelId = "CHANNEL_HIGH"
val category = HyperNotificationCompat.CATEGORY_CAR_ALIVE_ACTIVE_0
//CATEGORY_CAR_ALIVE_ACTIVE_0 需要参考 PRD:https://xiaomi.f.mioffice.cn/docx/doxk4DW5CQL62kfHL0et3nNfbXh
// 内接入"接入业务"的优先级来确定,引用参考"灵动岛"类型:https://xiaomi.f.mioffice.cn/wiki/IHlPwIj3HiGeEek2UQikTAyq4Tb
chargeRemoteView.setProgressBar(R.id.remote_progress,100, sbCharge.progress, false);
val builder = Notification.Builder(requireContext(), channelId)
.setCategory(category)
// 这行必须要有,否则通知无法传递到systemui
.setSmallIcon(R.drawable.ic_charge)
// 设置小岛图标
.setLargeIcon(Icon.createWithResource(requireContext(), R.drawable.ic_charge))
// 设置小岛文字和边框颜色
.setSubText("1h 23min").setColor(Color.parseColor("#11A658"))
// 设置中岛view
.setCustomHeadsUpContentView(chargeRemoteView)
.setOnlyAlertOnce(true)
.setProgress(sbCharge.max, sbCharge.progress, false)
.setAliveShowType(HyperNotificationCompat.ALIVE_SHOW_TYPE_DEFAULT)
NotificationManagerCompat.from(requireContext())
// tag参考5.1配置
.notify("tag", chargeNotificationId, builder.build())超高负载监听接入(必看!!!)
❗ 当负载处于 SYS_LOAD_LEVEL_CRITICAL 时,灵动岛各业务线需要进行动效降级,暂停所有动画
接入参考:XCD MiCarPerfservice系统负载状态通知设计,任何问题咨询 陆晓鸽
详细可查看:灵动岛-系统超高(Critical)负载降级方案
高频更新场景接入(研发必看!!!)
对于高频更新灵动岛通知的场景(例如 1 秒发多次),因为原生通知服务有发送频率限制,可能会丢弃部分数据,所以不能保证 UI 更新的实时性。
如果需要保证 UI 更新的准确性,需要另外接入实时数据更新的 API,参考 灵动岛IAliveDataService方案设计及接入说明
📥 抓取自飞书 wiki 空间 7541192071952990209,obj_token: DD7LdX3Quog6FuxulhWcYDbQnhg