SystemUI 悬浮通知
Posted 虫师魁拔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SystemUI 悬浮通知相关的知识,希望对你有一定的参考价值。
通知概览https://developer.android.google.cn/guide/topics/ui/notifiers/notifications
一、悬浮通知创建
简单通知创建代码
public void showAlarmNotification()
//IMPORTANCE_HIGH 重要通知,弹出悬浮通知
NotificationChannel channel = new NotificationChannel("123", "测试 channel_name", NotificationManager.IMPORTANCE_HIGH);
//led灯
channel.enableLights(true);
//锁屏显示通知
channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
//led灯颜色
channel.setLightColor(Color.BLUE);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.baidu.com"));
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
// Get the layouts to use in the custom notification
RemoteViews notificationLayout = new RemoteViews(getPackageName(), R.layout.notification_layout);
notificationLayout.setTextViewText(R.id.text, "contentView");
RemoteViews notificationLayoutExpanded = new RemoteViews(getPackageName(), R.layout.notification_layout_big);
notificationLayoutExpanded.setTextViewText(R.id.text, "bigContentView");
// Apply the layouts to the notification
Notification customNotification = new NotificationCompat.Builder(this, "123")
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle("imageTitle")
.setContentText("imageDescription")
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_android_black_24dp))
.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(BitmapFactory.decodeResource(getResources(),R.drawable.ic_android_black_24dp))
.bigLargeIcon(null))
.setFullScreenIntent(pendingIntent, false)
.build();
notificationManager.notify(0, customNotification);
悬浮通知,就是在创建 NotificationChannel 时指定等级为 IMPORTANCE_HIGH 。系统对通知定义等级六级:
// 效果等于无通知 public static final int IMPORTANCE_NONE = 0; // 通知被折叠起来,不在状态栏显示 public static final int IMPORTANCE_MIN = 1; // 在状态栏显示,但是没有提示音等 public static final int IMPORTANCE_LOW = 2; // 在状态栏显示,有提示音等,但没有弹出悬浮框 public static final int IMPORTANCE_DEFAULT = 3; // 在状态栏显示,有提示音等,有弹出悬浮框 public static final int IMPORTANCE_HIGH = 4; // 效果等同于 IMPORTANCE_HIGH public static final int IMPORTANCE_MAX = 5;
二、悬浮通知上滑后再次创建不弹出问题
调试时候会遇到,点击APP希望弹出悬浮通知时,没有弹出场景。这个可能是在之前一分钟内,有过弹出悬浮通知,且被我们自己上滑取消。如此,接下来一分钟内,不再弹出通知。
这是系统的默认设计,系统在用户手动上滑时,会认为用户此时有其他活动,弹出的通知栏可能干扰了用户,所以用户上滑隐藏通知,故短时间内可能我们不应该再弹出相同通道的通知。
这部分控制在 NotificationInterruptStateProviderImpl.java 中
public boolean shouldHeadsUp(NotificationEntry entry)
if (mStatusBarStateController.isDozing())
return shouldHeadsUpWhenDozing(entry);
else
return shouldHeadsUpWhenAwake(entry);
... ...
private boolean shouldHeadsUpWhenAwake(NotificationEntry entry)
StatusBarNotification sbn = entry.getSbn();
// 与 Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED 值相关
if (!mUseHeadsUp)
if (DEBUG_HEADS_UP)
Log.d(TAG, "No heads up: no huns");
return false;
if (!canAlertCommon(entry))
return false;
if (!canAlertAwakeCommon(entry))
return false;
if (isSnoozedPackage(sbn))
if (DEBUG_HEADS_UP)
Log.d(TAG, "No alerting: snoozed package: " + sbn.getKey());
return false;
... ...
private boolean isSnoozedPackage(StatusBarNotification sbn)
return mHeadsUpManager.isSnoozed(sbn.getPackageName());
shouldHeadsUp
此函数判断是否有悬浮通知,正常状态下执行。
shouldHeadsUpWhenAwake
在这里对即将执行的应用通知的各种状态进行检查。上滑后,会触发通知进入 Snooze 状态,会被return false ,判断不可弹出悬浮框。判断条件如下:
isSnoozedPackage(sbn) -> mHeadsUpManager.isSnoozed(sbn.getPackageName())
mHeadsUpManager 对象类 HeadsUpManager.java 主要用于管理悬浮通知状态的,管理
/**
* 判断通知是否处于 Snoozes 状态
*/
public boolean isSnoozed(@NonNull String packageName)
final String key = snoozeKey(packageName, mUser);
Long snoozedUntil = mSnoozedPackages.get(key);
if (snoozedUntil != null)
if (snoozedUntil > mClock.currentTimeMillis())
if (Log.isLoggable(TAG, Log.VERBOSE))
Log.v(TAG, key + " snoozed");
return true;
mSnoozedPackages.remove(packageName);
return false;
/**
* 增加 Snoozes 状态通知
*/
public void snooze()
for (String key : mAlertEntries.keySet())
AlertEntry entry = getHeadsUpEntry(key);
String packageName = entry.mEntry.getSbn().getPackageName();
mSnoozedPackages.put(snoozeKey(packageName, mUser),
mClock.currentTimeMillis() + mSnoozeLengthMs);
通知上滑会执行 snooze() ,将当前通知包名添加到 mSnoozedPackages 中。后续该包名通知发出时,isSnoozed 中检查 mSnoozedPackages 是否存在此发出通知应用的包名。存在时,判断 snoozedUntil 是否已经到达当前时间。
snoozedUntil == mClock.currentTimeMillis() + mSnoozeLengthMs
mSnoozeLengthMs 默认是1分钟,所以一般设备上,通知上滑1分钟后,才有悬浮通知效果。
int defaultSnoozeLengthMs = resources.getInteger(R.integer.heads_up_default_snooze_length_ms);
mSnoozeLengthMs = Settings.Global.getInt(context.getContentResolver(), SETTING_HEADS_UP_SNOOZE_LENGTH_MS, defaultSnoozeLengthMs);
修改 mSnoozeLengthMs 默认值,只要修改 heads_up_default_snooze_length_ms 即可,或者动态修改,修改 SETTING_HEADS_UP_SNOOZE_LENGTH_MS 属性。
以上是关于SystemUI 悬浮通知的主要内容,如果未能解决你的问题,请参考以下文章
Notifications通知到SystemUI(“Notifications 通知”拆解)
Android 10.0 原生SystemUI下拉通知栏UI背景设置为圆角背景的定制
系统方向学习8--Android 10.0 SystemUI 状态栏屏蔽弹出的 提醒式通知