在升级到Android 5.0 Lollipop之后,它开始在锁屏界面自动显示正在进行的通知。
有时用户不想看到所有这些通知,因此他们会询问开发人员如何让通知在状态栏中保留但在锁屏界面中隐藏。
我找到的唯一方法是强制用户使用屏幕锁(例如手势或PIN),并编程使用setVisibility()设置为VISIBILITY_SECRET。但并非所有用户都想使用屏幕锁。
是否有任何标志(或标志组合)可以告诉通知:不要在锁屏界面上可见,但在通知区域中可见?
在升级到Android 5.0 Lollipop之后,它开始在锁屏界面自动显示正在进行的通知。
有时用户不想看到所有这些通知,因此他们会询问开发人员如何让通知在状态栏中保留但在锁屏界面中隐藏。
我找到的唯一方法是强制用户使用屏幕锁(例如手势或PIN),并编程使用setVisibility()设置为VISIBILITY_SECRET。但并非所有用户都想使用屏幕锁。
是否有任何标志(或标志组合)可以告诉通知:不要在锁屏界面上可见,但在通知区域中可见?
正如这个答案所述,您可以使用VISIBILITY_SECRET
来在用户有安全密钥保护(不仅仅是滑动或没有密钥保护)且已禁止显示敏感通知时,在锁定屏幕上禁止通知。
为了覆盖其余情况,您可以通过将通知的优先级设置为PRIORITY_MIN
来在出现键盘保护时从锁定屏幕和状态栏中以编程方式隐藏通知,然后在键盘保护消失时重置优先级。
final BroadcastReceiver notificationUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager =
(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context, YOUR_NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.your_icon)
.setVisibility(NotificationCompat.VISIBILITY_SECRET);
KeyguardManager keyguardManager =
(KeyguardManager)context.getSystemService(Context.KEYGUARD_SERVICE);
if (keyguardManager.isKeyguardLocked())
builder.setPriority(NotificationCompat.PRIORITY_MIN);
notificationManager.notify(YOUR_NOTIFICATION_ID, builder.build());
}
};
//For when the screen might have been locked
context.registerReceiver(notificationUpdateReceiver,
new IntentFilter(Intent.ACTION_SCREEN_OFF));
//Just in case the screen didn't get a chance to finish turning off but still locked
context.registerReceiver(notificationUpdateReceiver,
new IntentFilter(Intent.ACTION_SCREEN_ON));
//For when the user unlocks the device
context.registerReceiver(notificationUpdateReceiver,
new IntentFilter(Intent.ACTION_USER_PRESENT));
//For when the user changes users
context.registerReceiver(notificationUpdateReceiver,
new IntentFilter(Intent.ACTION_USER_BACKGROUND));
context.registerReceiver(notificationUpdateReceiver,
new IntentFilter(Intent.ACTION_USER_FOREGROUND));
setLockScreenVisibility()
的说明:“仅由系统和通知排序器可修改。” - Jeffrey Blattmanboolean shouldFilterOut(StatusBarNotification sbn) {
if (!(mEnvironment.isDeviceProvisioned() ||
showNotificationEvenIfUnprovisioned(sbn))) {
return true;
}
if (!mEnvironment.isNotificationForCurrentProfiles(sbn)) {
return true;
}
if (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET &&
mEnvironment.shouldHideSensitiveContents(sbn.getUserId())) {
return true;
}
return false;
}
似乎还有一种被过滤掉的通知类型是在存在摘要的组中的子通知。因此,除非您有多个正当理由需要使用摘要,否则当前最好的方法就是使用VISIBILITY_SECRET。
private class LockscreenIntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Log.d(TAG, "LockscreenIntentReceiver: ACTION_SCREEN_OFF");
disableNotification();
} else if (action.equals(Intent.ACTION_USER_PRESENT)){
Log.d(TAG, "LockscreenIntentReceiver: ACTION_USER_PRESENT");
// NOTE: Swipe unlocks don't have an official Intent/API in android for detection yet,
// and if we set ungoing control without a delay, it will get negated before it's created
// when pressing the lock/unlock button too fast consequently.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (NotificationService.this.isNotificationAllowed()) {
enableNotification((Context)NotificationService.this);
}
}
}, 800);
}
} catch (Exception e) {
Log.e(TAG, "LockscreenIntentReceiver exception: " + e.toString());
}
}
}
这段代码主要是在用户锁定手机时基本上移除正在进行的通知(移除会非常短暂地可见)。一旦用户解锁手机,正在进行的通知将在延迟时间(这里是 800 毫秒)后恢复。 enableNotification() 是一个方法,它将创建通知,并调用 startForeground()。目前已验证可在 Android 7.1.1 上运行。
您只需记得相应地注册和取消注册接收器即可。