Подтвердить что ты не робот

Как подавить уведомление о блокировке экрана в Android 5 (Lollipop), но разрешить его в области уведомлений?

После обновления до Android 5.0 Lollipop он начал показывать автоматически текущее уведомление на экране блокировки.

Иногда пользователи не хотят видеть их всех, поэтому они спрашивают разработчиков, как разрешить уведомление в области статуса, но скрывать их на экране блокировки.

Единственный способ, которым я нашел, - заставить пользователей использовать блокировку экрана (например, Жест или ПИН) и программно setVisibility() до VISIBILITY_SECRET. Но не все они хотят использовать блокировку экрана.

Есть ли какой-либо флаг (или комбинация флагов), говорящий об уведомлении: не быть видимым на экране блокировки, но быть видимым в области уведомлений?

4b9b3361

Ответ 1

Использовать видимость и приоритет

Как описано в этом ответе, вы можете использовать VISIBILITY_SECRET для подавить уведомление на экране блокировки, когда у пользователя есть защищенная блокировка клавиатуры (а не просто прокрутка или отсутствие блокировки клавиатуры) и подавление чувствительных уведомлений.

Чтобы охватить остальные случаи, вы можете программно скрыть уведомление с экрана блокировки и строки состояния, установив приоритет уведомления PRIORITY_MIN всякий раз, когда блокировка клавиатуры присутствует, а затем reset приоритет всякий раз, когда блокировка клавиатуры отсутствует.

Недостатки

  • Использование эмулятора Android 5, похоже, приводит к тому, что уведомление на короткое время появляется на экране блокировки, но затем исчезает.
  • Больше не работает с Android Developer Developer 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, notification);
    }
};

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

Ответ 2

Кажется, что VISIBILITY_SECRET делает самый чистый подход. Согласно документации:

может быть сделано уведомление VISIBILITY_SECRET, которое будет подавлять его значок и тикер до тех пор, пока пользователь не обойдет блокирующий экран.

Для источника (NotificationData в проекте AOSP SystemUI) 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 - это лучшее, что можно сделать в настоящее время.

Ответ 3

Вы можете установить приоритет уведомления PRIORITY_MIN. Это должно скрыть уведомление на экране блокировки. Он также скрывает значок из строки состояния (не уверен, что вы этого хотите), но само уведомление все еще отображается в области уведомлений.

Ответ 4

Я создал "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 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.

Вам нужно помнить только о регистрации и отмене регистрации получателя.