簡體   English   中英

如何在 Android 5 (Lollipop) 中抑制鎖定屏幕上的通知但讓它在通知區域中?

[英]How to suppress notification on lock screen in Android 5 (Lollipop) but let it in notification area?

升級到 Android 5.0 Lollipop 后,它開始在鎖定屏幕上自動顯示正在進行的通知。

有時用戶不想看到所有這些,所以他們會問開發人員如何在狀態區域中設置通知但在鎖定屏幕上隱藏它們。

我發現的唯一方法是強制用戶使用屏幕鎖定(例如手勢或 PIN)並以編程方式setVisibility()VISIBILITY_SECRET 但並非所有人都想使用屏幕鎖定。

是否有任何標志(或標志組合)對通知說:在鎖定屏幕上不可見,但在通知區域中可見?

使用可見性和優先級

正如這個答案所涵蓋的那樣,當用戶有安全的鍵盤鎖(不僅僅是滑動或沒有鍵盤鎖)並且敏感通知被抑制時,您可以使用VISIBILITY_SECRET來抑制鎖定屏幕上的通知。

為了涵蓋其余情況,您可以通過將通知的優先級設置為PRIORITY_MIN每當鍵盤鎖存在時以編程方式隱藏鎖定屏幕和狀態欄中的通知,然后在鍵盤鎖不存在時重置優先級。

缺點

  • 使用 Android 5 模擬器,這似乎會導致通知非常短暫地出現在鎖定屏幕上,然后消失。
  • 由於通知優先級已棄用,當用戶沒有安全鎖定屏幕(例如僅滑動)時,不再從 Android O 開始工作。

例子

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

似乎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 是目前可以做到的最好的。

您可以將通知的優先級設置為PRIORITY_MIN 這應該隱藏鎖定屏幕上的通知。 它還會從狀態欄隱藏圖標(不確定是否需要),但通知本身在通知區域中仍然可見。

我為我的持續通知創建了一個“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 上運行。

您只需要記住相應地注冊和取消注冊接收器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM