it-swarm.com.ru

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

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

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

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

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

17
Tomáš Hubálek

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

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

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

Недостатки

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

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

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

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

6
Jim Vitek

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

4
Floern

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

Вы только должны помнить, чтобы зарегистрировать и отменить регистрацию получателя соответственно.

0
ItWillDo