Android:如何让第二屏幕在服务运行期间持续常亮?
解决双屏应用第二屏幕电源键按下后黑屏的问题
问题场景
我开发了一个双屏测试应用,核心目标:
- 在第二屏幕展示独立内容
- 服务运行期间让第二屏幕持续常亮
通过DISPLAY_SERVICE和WindowManager已经实现双屏显示,ForegroundService后台运行也正常,但按下手机电源键后,第二屏幕会跟着黑屏。尝试过设置WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON和使用PARTIAL_WAKE_LOCK,都没解决问题。
附当前MyService代码:
package com.example.myapplication import android.app.Presentation import android.app.Service import android.content.Context import android.content.Intent import android.hardware.display.DisplayManager import android.os.Bundle import android.os.IBinder import android.os.PowerManager import android.os.PowerManager.WakeLock import android.view.Display import android.view.WindowManager import androidx.core.app.NotificationCompat class MyService : Service() { private var wakeLock: WakeLock? = null private var presentation: MyPresentation? = null; override fun onBind(intent: Intent): IBinder? { return null } override fun onCreate() { super.onCreate() val powerManager = getSystemService(POWER_SERVICE) as PowerManager wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::MyWakeLockTag") wakeLock?.acquire(10*60*1000L /*10 minutes*/) } private fun start() { var notification = NotificationCompat.Builder(this, "running_channel") .setContentTitle("Running") .setContentTitle("Hello:") .setSmallIcon(R.drawable.ic_launcher_foreground) .setOngoing(true) .build() val dm = applicationContext.getSystemService(DISPLAY_SERVICE) as DisplayManager val dispArray = dm.displays if (dispArray.size > 1) { presentation = MyPresentation(this, dispArray[1]) presentation?.window!!.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) presentation?.show() } startForeground(42, notification) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { when(intent?.action) { Actions.START.toString() -> start() Actions.STOP.toString() -> stopSelf() } return super.onStartCommand(intent, flags, startId); } override fun onDestroy() { super.onDestroy() presentation?.hide(); if (wakeLock?.isHeld == true) { wakeLock?.release(); } } enum class Actions { START, STOP } } class MyPresentation(outerContext: Context?, display: Display?) : Presentation(outerContext, display) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.my_layout); } }
问题分析
- PARTIAL_WAKE_LOCK不生效:这个锁仅保证CPU持续运行,完全不影响屏幕状态,对维持屏幕常亮没有作用。
- FLAG_KEEP_SCREEN_ON时机错误:当前在
Presentation.show()之前设置窗口flag,但此时Presentation的窗口还未完全初始化,导致flag没有正确应用到第二屏幕的窗口上。 - 未针对第二屏幕设置专属WakeLock:默认的WakeLock作用于主屏幕,需要明确指定作用到第二屏幕。
解决方案
1. 修正FLAG_KEEP_SCREEN_ON的设置时机
把添加flag的逻辑移到MyPresentation的onCreate方法中,此时窗口已经完成初始化,能确保flag正确生效:
class MyPresentation(outerContext: Context?, display: Display?) : Presentation(outerContext, display) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.my_layout) // 窗口初始化完成后添加常亮flag window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) } }
2. 为第二屏幕设置专属WakeLock
首先在AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.WAKE_LOCK" />
然后修改Service中WakeLock的创建逻辑,指定作用到第二屏幕:
override fun onCreate() { super.onCreate() val powerManager = getSystemService(POWER_SERVICE) as PowerManager // 创建保持屏幕高亮的WakeLock,结合ACQUIRE_CAUSES_WAKEUP确保能唤醒屏幕 wakeLock = powerManager.newWakeLock( PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP, "MyApp::MyWakeLockTag" ) // 绑定到第二屏幕 val dm = getSystemService(DISPLAY_SERVICE) as DisplayManager val displays = dm.displays if (displays.size > 1) { wakeLock?.setAllowedDisplay(displays[1].displayId) } wakeLock?.acquire(10*60*1000L /*10 minutes*/) }
3. 双重保障(推荐)
同时使用上述两种方案,既给Presentation窗口添加常亮flag,又为第二屏幕设置专属WakeLock,最大化确保屏幕常亮效果。
验证步骤
- 确认
WAKE_LOCK权限已添加到清单文件 - 替换代码后重新编译安装应用
- 启动服务,按下电源键,检查第二屏幕是否保持常亮
内容的提问来源于stack exchange,提问作者dknaack
相关产品推荐
相关产品推荐

