如何在锁屏上方显示Activity?自制闹钟APP技术求助
Hey there! I’ve tackled this exact scenario for Android alarm apps before, so let’s walk through the most reliable approaches to get your Activity showing over the lock screen.
1. Use WindowManager Flags (Direct Activity Overlay)
This is the straightforward method for making your Activity appear on top of the lock screen. You’ll need to set specific window flags in your Activity’s onCreate() method, along with the right permissions.
First, add these permissions to your AndroidManifest.xml:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
Then, in your Alarm Activity’s onCreate() (before calling setContentView()), set the window flags:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Configure window to show over lock screen window.apply { addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD) addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) // For Android 10+, use this flag instead of SHOW_WHEN_LOCKED in some cases if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY) } else { setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT) } } setContentView(R.layout.activity_alarm) }
Note: On Android 6.0+, you’ll need to request the SYSTEM_ALERT_WINDOW permission dynamically (it’s a special permission, not part of standard runtime permissions). Redirect users to the app’s settings screen to enable it with:
if (!Settings.canDrawOverlays(this)) { val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:$packageName")) startActivityForResult(intent, OVERLAY_PERMISSION_REQUEST_CODE) }
2. Use Fullscreen Intent (Official Recommended Approach)
Android’s Fullscreen Intent is built exactly for high-priority use cases like alarms—this is what most stock alarm apps rely on. It’s more reliable across devices and Android versions, as it leverages the notification system’s native behavior.
Step 1: Schedule the Alarm with AlarmManager
First, set up your alarm using AlarmManager for precise triggering:
val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager val alarmIntent = Intent(this, AlarmReceiver::class.java) val pendingIntent = PendingIntent.getBroadcast( this, ALARM_REQUEST_CODE, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // For Android 12+, use setExactAndAllowWhileIdle to bypass doze mode if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { alarmManager.setExactAndAllowWhileIdle( AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent ) } else { alarmManager.setExact( AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent ) }
Step 2: Launch Fullscreen Intent via Broadcast Receiver
In your AlarmReceiver, build a notification that triggers your alarm Activity as a fullscreen intent:
class AlarmReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { context ?: return // Create intent to launch your alarm Activity val fullscreenIntent = Intent(context, AlarmActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK } val fullscreenPendingIntent = PendingIntent.getActivity( context, FULLSCREEN_REQUEST_CODE, fullscreenIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // Build high-priority alarm notification val notificationBuilder = NotificationCompat.Builder(context, ALARM_CHANNEL_ID) .setSmallIcon(R.drawable.ic_alarm) .setContentTitle("Alarm Triggered") .setContentText("Time to wake up!") .setPriority(NotificationCompat.PRIORITY_HIGH) .setCategory(NotificationCompat.CATEGORY_ALARM) .setFullScreenIntent(fullscreenPendingIntent, true) // Show the notification val notificationManager = NotificationManagerCompat.from(context) notificationManager.notify(ALARM_NOTIFICATION_ID, notificationBuilder.build()) } }
Step 3: Create a Notification Channel (Android 8.0+)
For Android 8.0 and above, you must create a notification channel for alarms:
private fun createAlarmChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( ALARM_CHANNEL_ID, "Alarms", NotificationManager.IMPORTANCE_HIGH ).apply { description = "Channel for alarm notifications" setSound(null, null) // Optional: Disable default sound if your Activity plays its own } val notificationManager = getSystemService(NotificationManager::class.java) notificationManager.createNotificationChannel(channel) } }
Key Notes:
- Add the
REQUEST_SCHEDULE_EXACT_ALARMpermission to your manifest for Android 12+ (required for precise alarm scheduling). - Fullscreen intents automatically handle lock screen visibility—you don’t need extra window flags for the Activity, though adding
FLAG_TURN_SCREEN_ONcan still help wake the device.
3. Handle Custom ROM Restrictions
Some Android OEMs (like Xiaomi, Samsung, Huawei) have strict security rules that might block your Activity from showing over the lock screen. To work around this:
- Guide users to enable "Display over other apps" in your app’s system settings.
- Suggest disabling battery optimization for your app (alarms can get suppressed if the app is in doze mode).
- Test on multiple devices to catch OEM-specific quirks.
Final Recommendation
Start with the Fullscreen Intent approach—it’s the most robust and aligns with Android’s design guidelines. The WindowManager method works too, but it’s more prone to being blocked by system permissions or OEM restrictions.
内容的提问来源于stack exchange,提问作者HypnoZ

