如何区分锁屏与MyActivity的层级关系并实现对应框架逻辑?
Hey there, let's break down how to solve this problem properly at the framework level. Your temporary solution using a custom system property tied to FLAG_SHOW_WHEN_LOCKED works, but there are more reliable, real-time ways to directly check if MyActivity is under or above the lock screen without relying on manual property updates.
Core Idea: Check Lock Screen State + Window Hierarchy
Since the lock screen isn't an Activity, we need to look at two key things in the framework:
- Whether the lock screen is currently active
- The position of MyActivity's window relative to the lock screen window in the system's window hierarchy
Method 1: Use KeyguardManager + Activity Window Flags/Layers
In components like PhoneWindowManager (where volume key events are typically intercepted), you can combine KeyguardManager checks with Activity window state to make the right decision:
// Inside PhoneWindowManager's interceptKeyBeforeQueueing method (or similar framework component) KeyguardManager keyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); boolean isKeyguardLocked = keyguardManager.isKeyguardLocked(); if (isKeyguardLocked) { // Locate MyActivity's ActivityRecord from the top activity stack ActivityManagerService ams = ActivityManagerService.getService(); List<ActivityRecord> topActivities = ams.getStackSupervisor().getTopActivities(); boolean isMyActivityAboveLockScreen = false; for (ActivityRecord activityRecord : topActivities) { if ("com.yourpackage.MyActivity".equals(activityRecord.getComponentName().getClassName())) { WindowState myActivityWindow = activityRecord.getWindow(); if (myActivityWindow != null) { // Check if the window is configured to show above lock screen, or has a higher layer int windowFlags = myActivityWindow.getFlags(); int windowType = myActivityWindow.getAttrs().type; // Lock screen windows use TYPE_KEYGUARD (pre-Android 12) or TYPE_KEYGUARD_SCRIM (Android 12+) boolean hasShowAboveFlag = (windowFlags & WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) != 0; boolean hasHigherLayer = windowType >= WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM; isMyActivityAboveLockScreen = hasShowAboveFlag || hasHigherLayer; break; } } } // Only launch MyActivity if it's under the lock screen if (!isMyActivityAboveLockScreen) { Intent launchIntent = new Intent(mContext, MyActivity.class); launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(launchIntent); } }
Method 2: Directly Compare Window Layers with Lock Screen Window
You can also fetch the lock screen's window directly from WindowManagerService and compare its layer with MyActivity's window layer (higher layer values mean the window is drawn on top):
// Inside framework code with access to WindowManagerService WindowManagerService wms = WindowManagerService.getInstance(); WindowState lockScreenWindow = null; WindowState myActivityWindow = null; // Find the lock screen window for (WindowState window : wms.getWindows()) { int windowType = window.getAttrs().type; if (windowType == WindowManager.LayoutParams.TYPE_KEYGUARD || windowType == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM) { lockScreenWindow = window; break; } } // Find MyActivity's window for (WindowState window : wms.getWindows()) { ActivityRecord activityRecord = window.getActivityRecord(); if (activityRecord != null && "com.yourpackage.MyActivity".equals(activityRecord.getComponentName().getClassName())) { myActivityWindow = window; break; } } // Make decision based on layer comparison if (lockScreenWindow != null && myActivityWindow != null) { boolean isMyActivityUnderLockScreen = myActivityWindow.getLayer() < lockScreenWindow.getLayer(); if (isMyActivityUnderLockScreen) { // Launch MyActivity Intent launchIntent = new Intent(mContext, MyActivity.class); launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(launchIntent); } }
Why This Is Better Than Your Temporary Solution
Your custom system property approach works, but it has a limitation: if MyActivity dynamically adds/removes FLAG_SHOW_WHEN_LOCKED at runtime, you'd have to remember to update the system property every time. The methods above check the real-time state of the window hierarchy, so they're always accurate.
内容的提问来源于stack exchange,提问作者William

