如何在Android 5(Lollipop)的锁定屏幕上禁止通知,但是让它在通知区域?

时间:2014-11-20 08:47:20

标签: android notifications android-notifications android-5.0-lollipop

升级到Android 5.0 Lollipop后,它开始在锁定屏幕上自动显示持续通知。

有时用户不想看到所有这些内容,因此他们会询问开发人员如何在状态区域中发布通知,但将其隐藏在锁定屏幕上。

我找到的唯一方法是强制用户使用屏幕锁定(例如手势或PIN)并以编程方式setVisibility()强制使用VISIBILITY_SECRET。但并非所有人都想使用屏幕锁定。

是否有任何标志(或标志组合)说明通知:在锁定屏幕上不可见但在通知区域中可见?

4 个答案:

答案 0 :(得分:14)

使用可见性和优先级

this answer所述,当用户拥有安全键盘锁(不仅是滑动或没有键盘锁)并且抑制了敏感通知时,您可以使用VISIBILITY_SECRET来取消锁定屏幕上的通知。< / p>

为了涵盖其他情况,您可以通过在键盘保护时将通知的优先级设置为PRIORITY_MIN,以编程方式隐藏锁定屏幕和状态栏中的通知 存在,然后在没有键盘锁时重置优先级。

缺点

  • 使用Android 5模拟器,这似乎导致通知非常短暂地出现在锁定屏幕上,但随后消失。
  • 当用户自notification priorities are deprecated以来没有安全锁定屏幕(例如,仅刷卡)时,不再像Android O开发者预览版2那样工作。

实施例

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);
            .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));

答案 1 :(得分:6)

似乎VISIBILITY_SECRET做了最干净的方法。根据文件:

  

可以发出通知VISIBILITY_SECRET,它将禁止其图标和滚动条,直到用户绕过锁屏。

根据源(SystemUI AOSP项目中的NotificationData),VISIBILITY_SECRET是唯一的方法:

boolean 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是目前最好的。

答案 2 :(得分:4)

您可以将通知的优先级设置为PRIORITY_MIN。这应该隐藏锁定屏幕上的通知。它还会隐藏状态栏中的图标(不确定您是否需要),但通知本身仍然可以在通知区域中看到。

答案 3 :(得分:0)

我为我正在进行的通知创建了一个'LockscreenIntentReceiver',如下所示:


    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上运行。

你只需要记住注册&amp;取消注册接收器。