通知的介绍及使用

0. 重要提醒

📌 XCD(Android U)新增发送通知权限,未申请权限将无法发送通知,详情见 2.1 节。 📌 遇到通知不显示的问题,可直达 10.1 节。 📌 灵动岛接入参考:【高密级】Alive Status(灵动岛)技术接入文档 📌 通知扩展的 API:通知扩展 API

概述

MiCar 基于原生 Automotive OS 的通知进行了 UI 和部分逻辑的改造,具体业务介绍如下。

1.1 浮动通知

浮动通知位于 HMI 的顶部中间部分,用于展示系统报警与通知,如下图所示。其支持上滑消失,左右滑取消通知,我们可以将其类比为 MIUI 手机上的通知。注意,其区别于具有强交互属性的 dialog(弹窗)。

1.2 通知中心

点击状态栏的通知图标,可以打开通知中心页面,用户在非驾驶状态下可查看非紧急消息以及历史消息的需求,并可查看消息后根据消息提示完成对应操作,包括左右滑动清除通知,一键清除所有通知等操作,如下图所示。

创建通知

下面来介绍如何创建并发送一个基本的通知。

2.1 请求权限

Android 13(T) 及以上版本需要添加权限:

<manifest ...>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <application ...>
        ...
    </application>
</manifest>

Target sdk 在 API 33 以上需要动态申请,或者添加到系统权限白名单。

系统权限白名单位置:

  • DCD:device/micar/common/dcd/default-mi-car-permissions.xml
  • XCD:device/micar/common/system/default-mi-car-permissions.xml

更多参考:通知运行时权限

2.2 创建通知渠道

在 Android O 及以上版本是需要创建通知渠道的,示例代码如下:

NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "渠道名",
        NotificationManager.IMPORTANCE_HIGH);
channel.setSound(uri, audioAttributes); // 如需要可以修改通知提示音,传入 null 会静音
NotificationManagerCompat.from(context).createNotificationChannel(channel);

注意事项:

  1. 渠道 ID 应用自己定义,保证应用内唯一就好。
  2. 如果要显示浮动通知,渠道重要性一定要设置 IMPORTANCE_HIGH 及以上,否则仅会在通知中心显示。
  3. 一旦创建通知渠道后,您将无法更改通知渠道的行为(例如原来有提示音改成静音),除非清理所有数据或删除重建渠道或换一个渠道 id。

更多参考:创建和管理通知渠道

2.3 设置通知内容

您需要使用 NotificationCompat.Builder 对象设置通知内容和渠道。示例代码如下:

NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
        .setCategory(Notification.CATEGORY_CAR_WARNING)
        .setSmallIcon(R.mipmap.ic_launcher) // 必填,一般用 APP 图标
        .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.ic_car)) // 左侧大图标
        .setContentTitle("标题文本")
        .setContentText("正文文本");

样式如图所示:

其中:

  1. NotificationCompat.Builder 构造函数要求提供渠道 ID。
  2. 有特殊类型需求可以通过 setCategory() 设置一个通知类别,具体要用哪些类别及相关介绍见第 3 节。
  3. 必须通过 setSmallIcon() 设置一个小图标(Google SDK 要求),建议使用 APP 图标,但在通知卡片上不会展示出来。
  4. 可以通过 setLargeIcon() 设置左侧的大图标,如果不设置,默认展示应用图标。图片大小可以设定为 90x90dp 或更大。

NotificationCompat.Builder.setLargeIcon(Bitmap icon) 方法只有一个传入 Bitmap 的形式,这样是无法支持图片动态日夜间切换的,如果需要支持日夜间切换,请使用 Notification.Builder 的 setLargeIcon(Icon icon) 方式构建通知,其中 icon 可使用 Icon.createWithResource() 方法使用图片资源 id。

2.4 设置通知的点按操作

通知也可以响应点按操作,通常是在应用中打开与通知对应的 activity。为此,请指定使用

PendingIntent 对象定义的内容 intent,并将其传递给 setContentIntent()。除了 Activity,还可以实现 BroadcastReceiver 或 Service 执行后台操作。

以下代码段展示了如何创建基本 intent,以便在用户点按通知时打开 activity:

// Create an explicit intent for an Activity in your app.
Intent intent = new Intent(this, AlertDetails.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
 
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        // Set the intent that fires when the user taps the notification.
        .setContentIntent(pendingIntent)
        .setAutoCancel(true);

注意:

  1. 关于 PendingIntent 的使用注意事项可参考文章:https://juejin.cn/post/7122767360976486413,这里写的比较全面,可以避开很多坑。
  2. 如果需要在用户点按通知时自动移除通知,需要调用 setAutoCancel(true)。

2.5 添加操作按钮

一个通知最多可以提供三个操作按钮,让用户能够快速响应。如需添加操作按钮,请实现 PendingIntent 并传递给 addAction() 方法。示例代码:

NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
        .setCategory(Notification.CATEGORY_CAR_WARNING)
        .setSmallIcon(R.mipmap.ic_launcher)
        .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.ic_update))
        .setContentTitle("系统更新") 
        .setContentText("新系统已下载完成,可以更新")
        .addAction(0, "下载更新", pendingIntent1)
        .addAction(0, "稍后", pendingIntent2);

样式如图所示:

注意:

  1. addAction() 方法的第一个参数代表按钮的图标,不需要的话传入 0 就好。
  2. addAction() 方法的第三个参数最好不要传 null,否则将点击没有任何响应。

2.6 显示通知

如需显示通知,请调用 NotificationManagerCompat.notify() 方法,并将通知的唯一 ID 和

NotificationCompat.Builder.build() 的结果传递给它。示例代码:

NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(tag, notificationId, builder.build());

如果是 user 0 的进程,请调用 NotificationManager.notifyAsUser() 方法转到以当前 user 身份执行,示例代码:

NotificationManager notificationManager = (NotificationManager) context.getSystemService(
        Context.NOTIFICATION_SERVICE);
notificationManager.notifyAsUser(tag, notificationId, builder.build(), UserHandle.CURRENT);

请记得保存您传递到 NotificationManagerCompat.notify() 的通知 tag 和 id,因为如果之后您想要更新或移除通知,将需要使用这个 tag 和 id。通知 tag id 由您自己定义,保证应用内唯一就好。

请确保您的应用属于系统特权应用或使用平台密钥签名的应用,否则可能无法触发浮动通知。

以上是创建通知的基本操作,更多通知功能 API 相关使用请参考官方文档:https://developer.android.com/training/notify-user/build-notification?hl=zh-cn

通知类别

目前系统通知类别主要有:智驾提示(即将废弃)、系统状态变更(包含自定义布局)、电话通知和系统应用通知。另外 Alive Status 还有持续活动 P0/P1 类灵动岛和提醒类灵动岛。

业务方尽量不要使用除这些以外的类别,下面是具体介绍。如果您不能确定您的通知属于哪个类别,可联系产品 @李科男 确认。

目前支持 Category 类型特性快速预览表:

Category类型特性
Notification.CATEGORY_CAR_EMERGENCY(“car_emergency”)该类型已由智驾进行管理,三方应用不允许发送此类型,不进入通知中心。
Notification.CATEGORY_CAR_WARNING(“car_warning”)出现 8s 后主动消失,不进入通知中心
Notification.CATEGORY_CALL通话结束后自动消失,不进入通知中心
Notification.CATEGORY_CAR_INFORMATION(“car_information”)8s 后主动消失,消失后进入通知中心。
HyperNotificationCompat.CATEGORY_CAR_ALIVE_ACTIVE_0持续活动 P0 类通知,消失后进入状态栏
HyperNotificationCompat.CATEGORY_CAR_ALIVE_ACTIVE_1持续活动 P1 类通知,消失后进入状态栏
HyperNotificationCompat.CATEGORY_CAR_ALIVE_REMIND提醒类灵动岛通知,自动消失时不进入状态栏,上滑或被打断进入状态栏

下面是对 category 类型的具体详细介绍:

3.1 智驾提示

图示:

使用场景:智能驾驶相关提示。

特点:不自动消失,由智驾控制消失逻辑。滑动可消失,不进入通知中心。

类型定义:Notification.CATEGORY_CAR_EMERGENCY(“car_emergency”)。

Tips:如果因无法直接调用 Notification 定义的类型而编译报错,可直接使用字符串。使用”car_emergency”需要添加权限:

<uses-permission android:name="android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS" />

该类型已由智驾进行管理,三方应用不允许发送此类型。

3.2 系统状态变更与自定义布局通知

3.2.1 系统状态变更

图示:

使用场景:系统提示状态变更时使用的通知。

特点:出现 8s 后主动消失,不进入通知中心。

类型定义:Notification.CATEGORY_CAR_WARNING(“car_warning”)。

Tips:如果因无法直接调用 Notification 定义的类型而编译报错,可直接使用字符串。使用”car_warning”需要添加权限:

<uses-permission android:name="android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS" />

3.2.2 自定义布局通知

图示:

使用场景:标准通知布局样式无法满足需求时,可以使用。

特点:用户无操作 8s 后主动消失,不进入通知中心。

类型定义:Notification.CATEGORY_CAR_WARNING(“car_warning”)。

Tips:如果因无法直接调用 Notification 定义的类型而编译报错,可直接使用字符串。使用”car_warning”需要添加权限:

<uses-permission android:name="android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS" />

此类型须采用自定义通知实现,调用 setCustomHeadsUpContentView() 方法以设置浮动通知的布局,RemoteViews 支持的类型及使用可参考网址。示例代码:

NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
        .setCategory(Notification.CATEGORY_CAR_WARNING)
        .setSmallIcon(R.drawable.ic_warning)
        .setCustomHeadsUpContentView(remoteViews);

目前宽度是固定的 624dp,高度可变。

3.3 电话通知

图示:

使用场景:电话相关。

特点:通话结束后自动消失,不进入通知中心。

类型定义:Notification.CATEGORY_CALL。

3.4 系统及系统应用通知

图示:

使用场景:系统以及系统应用的通知。

特点:8s 后主动消失,消失后进入通知中心。

类型定义:Notification.CATEGORY_CAR_INFORMATION(“car_information”)。

Tips:如果因无法直接调用 Notification 定义的类型而编译报错,可直接使用字符串。使用”car_information”需要添加权限:

<uses-permission android:name="android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS" />

3.5 灵动岛类型

参考 https://gerrit.auto.mioffice.cn/c/cockpit/core/platform/frameworks/hyperx/+/144733/1/core/core/README-NOTIFICATION.md#14

3.6 互斥逻辑

当前界面正在展示以上某一类通知时,这时要弹出其它类型通知,互斥逻辑如下表所示:

存在出现后台活动类 P0后台活动类 P1提醒类灵动岛系统状态变更电话通知系统及系统应用通知智驾提示(即将废弃)
后台活动类 P0后打断前,前一个进状态栏后打断前,前一个进状态栏后打断前,前一个进状态栏后打断前,前一个消失后打断前,前一个消失后打断前,前一个进通知中心后打断前,前一个消失
后台活动类 P1显示 1,2 进状态栏后打断前,前一个进状态栏后打断前,前一个进状态栏后打断前,前一个消失后打断前,前一个消失后打断前,前一个进通知中心后打断前,前一个消失
提醒类灵动岛后打断前,前一个进状态栏后打断前,前一个进状态栏后打断前,前一个进状态栏后打断前,前一个消失后打断前,前一个消失后打断前,前一个进通知中心后打断前,前一个消失
系统状态变更后打断前,前一个进状态栏后打断前,前一个进状态栏后打断前,前一个进状态栏后打断前,前一个消失后打断前,前一个消失后打断前,前一个进通知中心后打断前,前一个消失
电话通知后打断前,前一个进状态栏后打断前,前一个进状态栏后打断前,前一个进状态栏后打断前,前一个消失后打断前,前一个消失后打断前,前一个进通知中心后打断前,前一个消失
系统及系统应用通知等 1 结束再显示 6后打断前,前一个进状态栏后打断前,前一个进状态栏后打断前,前一个消失等 5 结束再显示 6后打断前,前一个进通知中心等 7 结束再显示 6
智驾提示(即将废弃)后打断前,前一个进状态栏后打断前,前一个进状态栏后打断前,前一个进状态栏后打断前,前一个消失后打断前,前一个消失后打断前,前一个进通知中心后打断前,前一个消失

除上述分类之外的其它分类通知,皆按“系统及系统应用通知”仲裁逻辑处理。

更新通知

如需在发出此通知后对其进行更新,请再次调用 NotificationManagerCompat.notify(),并将之前使用的具有同一 ID 的通知传递给该方法。如果之前的通知已被取消,则系统会创建一个新通知。

您可以选择性调用 setOnlyAlertOnce(),这样通知只会在通知首次显示时弹出浮动通知,以后更新时就不再进行显示。

另外,如果频繁地更新通知,可能有部分通知被丢弃,官方说明如下:https://developer.android.com/develop/ui/views/notifications?hl=zh-cn#limits

移除通知

如需在发出此通知后对其进行移除,请调用 NotificationManagerCompat.cancel(),并将之前使用的具有同一 ID 的通知传递给该方法。

前台服务通知

应用在启用前台服务时默认会发一个通知出来,业务方在构建常规的通知后会出现在通知中心里,并且是一个常驻的通知。为了不影响用户的体验,对用户产生困扰,针对我们系统的应用需要将其隐藏起来。

Android 原生的逻辑是低优先级的系统级应用的前台服务通知是不予展示的,因此业务方只需在构建通知时创建通知渠道(NotificationChannel)的时候将优先级指定为 NotificationManager.IMPORTANCE_LOW 即可,如图:

通知 & 报警中心

7.1 通知中心

通知中心打开方式:

可以通过隐式 Intent 打开,

Action 定义:“com.android.car.notification.NOTIFICATION_CENTER”

包名:“com.android.systemui”

示例代码:

Intent intent = new Intent();
intent.setAction("com.android.car.notification.NOTIFICATION_CENTER");
intent.setPackage("com.android.systemui");
context.startActivity(intent);

7.2 报警中心

报警中心打开方式:

可以通过隐式 Intent 打开,

Action 定义:“com.android.car.notification.EMERGENCY_CENTER”

包名:“com.android.systemui”

📌 以上所有图示并非最终效果,以视觉稿为主,地址: E4U:https://www.figma.com/file/vnm6w4wKPTBKWGVPq8TkNi/%E9%80%9A%E7%9F%A5%EF%BC%88%E5%AF%B9%E5%A4%96%EF%BC%89 MIUI 1.1:https://www.figma.com/file/VmmjnUFZ9UZb5dt9Oiknhq/%E9%80%9A%E7%9F%A51.1?node-id=1238%3A139973&mode=dev

全局通知提示音开关

public static final String NOTIFICATION_SOUNDS_ENABLED = "mi_notification_sounds_enabled";
Settings.System.getInt(cr, NOTIFICATION_SOUNDS_ENABLED, 1)

值定义:

  • key:mi_notification_sounds_enabled
  • value:0 - 关闭,1 - 开启(默认)

通知相关日志

9.1 framework 日志

以下是 framework 部分打印的日志,可以通过 bugreport 或者 adb logcat -b events 查到。

9.1.1 发送通知

这个日志仅代表业务方调用发送通知的 API 了,不代表一定会弹出:

notification_enqueue: [uid,pid,pkg,id,tag,userid,(notification),status]

其中:

  • notification 代表通知实体信息,日志中以 key-value 形式展示,比较详细,这里不做展开。
  • status 代表通知的发送状态,如图:

9.1.2 取消通知

notification_canceled: [userId|pkg|id|tag|uid,reason,lifespan,freshness,exposure,rank,count,listener]

其中:

  • reason 代表取消通知的原因,所有的原因如下:
/** Notification was canceled by the status bar reporting a notification click. */
public static final int REASON_CLICK = 1;
/** Notification was canceled by the status bar reporting a user dismissal. */
public static final int REASON_CANCEL = 2;
/** Notification was canceled by the status bar reporting a user dismiss all. */
public static final int REASON_CANCEL_ALL = 3;
/** Notification was canceled by the status bar reporting an inflation error. */
public static final int REASON_ERROR = 4;
/** Notification was canceled by the package manager modifying the package. */
public static final int REASON_PACKAGE_CHANGED = 5;
/** Notification was canceled by the owning user context being stopped. */
public static final int REASON_USER_STOPPED = 6;
/** Notification was canceled by the user banning the package. */
public static final int REASON_PACKAGE_BANNED = 7;
/** Notification was canceled by the app canceling this specific notification. */
public static final int REASON_APP_CANCEL = 8;
/** Notification was canceled by the app cancelling all its notifications. */
public static final int REASON_APP_CANCEL_ALL = 9;
/** Notification was canceled by a listener reporting a user dismissal. */
public static final int REASON_LISTENER_CANCEL = 10;
/** Notification was canceled by a listener reporting a user dismiss all. */
public static final int REASON_LISTENER_CANCEL_ALL = 11;
/** Notification was canceled because it was a member of a canceled group. */
public static final int REASON_GROUP_SUMMARY_CANCELED = 12;
/** Notification was canceled because it was an invisible member of a group. */
public static final int REASON_GROUP_OPTIMIZATION = 13;
/** Notification was canceled by the device administrator suspending the package. */
public static final int REASON_PACKAGE_SUSPENDED = 14;
/** Notification was canceled by the owning managed profile being turned off. */
public static final int REASON_PROFILE_TURNED_OFF = 15;
/** Autobundled summary notification was canceled because its group was unbundled */
public static final int REASON_UNAUTOBUNDLED = 16;
/** Notification was canceled by the user banning the channel. */
public static final int REASON_CHANNEL_BANNED = 17;
/** Notification was snoozed. */
public static final int REASON_SNOOZED = 18;
/** Notification was canceled due to timeout */
public static final int REASON_TIMEOUT = 19;
/** Notification was canceled due to the backing channel being deleted */
public static final int REASON_CHANNEL_REMOVED = 20;
/** Notification was canceled due to the app's storage being cleared */
public static final int REASON_CLEAR_DATA = 21;
  • lifespan 代表该通知从第一次发送到现在的毫秒数,忽略中间通知更新的时间。
  • freshness 代表该通知从最近更新的时间(没有更新就是发送时间)到现在的毫秒数。
  • exposure 代表该通知自最近一次可见性事件以来的毫秒数,如果从未发生过,则为 0。
  • rank 代表通知的等级,没有设定就是 -1。
  • listener 代表触发取消通知的监听器的类名,如果没有(例如业务方主动取消的)则为 NULL。

9.1.3 点击通知

notification_clicked: [userId|pkg|id|tag|uid,lifespan,freshness,exposure,rank,count]

其中:

  • lifespan 代表该通知从第一次发送到现在的毫秒数,忽略中间通知更新的时间。
  • freshness 代表该通知从最近更新的时间(没有更新就是发送时间)到现在的毫秒数。
  • exposure 代表该通知自最近一次可见性事件以来的毫秒数,如果从未发生过,则为 0。
  • rank 代表通知的等级,没有设定就是 -1。

9.1.4 点击通知按钮

notification_action_clicked: [userId|pkg|id|tag|uid,action_index,lifespan,freshness,exposure,rank,count]

其中:

  • action_index 代表按钮的索引,从 0 开始。
  • lifespan 代表该通知从第一次发送到现在的毫秒数,忽略中间通知更新的时间。
  • freshness 代表该通知从最近更新的时间(没有更新就是发送时间)到现在的毫秒数。
  • exposure 代表该通知自最近一次可见性事件以来的毫秒数,如果从未发生过,则为 0。
  • rank 代表通知的等级,没有设定就是 -1。

9.1.5 通知开关被关闭

以下日志在 logcat 就可以输出,但需要在开发者选项里把日志级别开到 verbose 并重启。

# 应用的通知开关被关闭了
E NotificationService: Suppressing notification from package [packageName] by user request.

9.2 SystemUI 日志

以下是 SystemUI 部分的 logcat 日志,其中标题就是日志的 TAG。

9.2.1 CarNotificationListener

# 发送通知
onNotificationPosted: key=[userId|pkg|id|tag|uid] channel=[CHANNEL_ID] flags=[flags] category=[category]
# 不是当前用户发的通知
Notification is not for current user: [StatusBarNotification]
Notification user: [userId]
Current user: [userId]
# 通知是否弹出?在下面 CarHeadsUpNotificationManager 判断后打印
Is [userId|pkg|id|tag|uid] shown as HUN?: [true/false]
# 移除通知
onNotiRemove: [userId|pkg|id|tag|uid] channel=[CHANNEL_ID] flags=[flags] category=[category]
# 当前处于禁用通知场景
Forbidden scene is [scene]
# 禁用通知场景发生变化
onNotificationForbiddenChanged: scene = [sceneId], isForbidden = [true/false]
# 进入了通知中心
postNotificationCenter: [userId|pkg|id|tag|uid]

9.2.2 CarHeadsUpNotificationManager

# 判断是否可以弹出通知
Unable to show as HUN: Notification center is showed # 通知中心正在显示
Unable to show as HUN: Forbidden scene is 0xXX # 其它禁用通知的业务场景正在显示
Unable to show as HUN: Keyguard is locked # 正在锁屏,电源是 OFF 或 AWAKE
Unable to show as HUN: OEM has disabled navigation HUN
Unable to show as HUN: Grouping notification
Unable to show as HUN: Messaging notification is muted by user
Unable to show as HUN: importance is not sufficient # importance < IMPORTANCE_HIGH
application is system privileged or signed with platform key # 系统签名应用
Unable to show as HUN: add to pending list # 当前有髙优通知在显示,当前通知加入待显示队列
Show as HUN # 显示浮动通知
# 非系统应用可能输出下面日志
Show as HUN: car messaging type notification
category not set for: [packageName]
Notification category: [category]
# 浮动通知消失
Dismiss for HUN: [userId|pkg|id|tag|uid]
# 禁用通知场景变更
onNotificationForbiddenChanged: scene = 0xXX, isForbidden = true/false

9.2.3 MiCarBeeper

# 相同应用在 1s 内弹出通知,不发声音
Package recently made noise: [packageName]
# 播放提示音
playing sound: [uri]

9.3 dump 日志

除了 logcat 查看实时的通知日志,也可以通过 dump 查询历史通知日志:

adb shell dumpsys notification

Bugreport 中也有部分通知的 dump 信息,搜索关键字“DUMP OF SERVICE CRITICAL notification”可以查询一些关键的通知信息,但并不包含全部的通知;搜索“DUMP OF SERVICE notification”可以查询通知额外的信息,例如通知渠道等等。

Q&A

10.1 浮动通知不显示

浮动通知不显示了怎么办?

大家经常遇到这样的问题,但影响的原因实在太多了,建议大家先仔细自查一下。

10.1.1 代码问题

首先排查一下自己的代码问题:

  1. 通知渠道是否有设置 IMPORTANCE_HIGH 及以上的重要性设置?是否修改过渠道的 importance 属性,如果修改过需要调用 NotificationManagerCompat.deleteNotificationChannel 方法删除一下旧通知渠道再创建,或者创建一个新的渠道 id(之前创建过的渠道谷歌禁止再次修改)。
  2. 在 Android U 及以上版本,是否添加权限 android.permission.POST_NOTIFICATIONS ?有添加过白名单或动态申请吗?白名单位置在 2.1 节。
  3. 您的应用是否属于系统特权应用或使用平台密钥签名的应用?
  4. 使用与 Car 相关的类别是否有添加 android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS 权限?
  5. user0 进程下是否调用 NotificationManager.notifyAsUser() 方法?

10.1.2 运行环境问题

如果确保了以上代码没有问题,看看是不是当前的车机环境存在以下问题:

  1. 确认一下电源模式是不是 OFF 或 AWAKE 状态,这两种模式下通知不会展示(因为与离车显示冲突),可以通过以下命令 mock 修改当前电源模式状态为 ACC 或 RUN:
adb root
adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle --mock_from_car 0x61407207 -i 2

最后一个数字是 2 或 3 皆可。

  1. 看下自己的应用的通知开关是不是关了?位置在“设置 - 系统 - 应用管理 - 右上角三个点 - 权限管理 - 通知”。

如果以上条件都满足了,可以看下第 9 节,查看相关日志是否有相关线索。

参考文档