Android:如何以编程方式打开和关闭屏幕?


97

在将此帖子标记为“重复”之前,我正在写此帖子,因为没有其他帖子可以解决该问题。

我试图关闭设备,然后在几分钟后或更换传感器后,将其重新打开。

关闭显示测试

我可以使用以下方法关闭屏幕:

params.flags |= LayoutParams.FLAG_KEEP_SCREEN_ON;
params.screenBrightness = 0;
getWindow().setAttributes(params);

我一直无法使用wl.release()方法关闭屏幕。

开启显示测试

我的第一个猜测如下。没有任何反应,屏幕保持关闭。

params.flags |= LayoutParams.FLAG_KEEP_SCREEN_ON;
params.screenBrightness = -1f;
getWindow().setAttributes(params);

然后,我也尝试使用唤醒锁,但没有成功。

PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "tag");
wl.acquire();

最后,我尝试了以下操作,但没有结果。

getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);

总而言之,对于这些方法中的任何一种,我在控制台中都不会出现任何类型的错误。当我使用电源按钮打开设备时,屏幕上会显示我的测试文本“屏幕应打开”。这表明代码应该已经运行了。请仅在您测试了代码后回答,看来许多功能(如params.screenBrightness = -1)无法按sdk的要求正常工作。


1
您关闭屏幕的方法对我不起作用。您设置该标志以使屏幕始终保持打开状态,这会耗尽电源。
克里斯蒂·威尔士

你有没有解决这个问题?PlayStore上有一些应用程序建议这样做。尝试过这一方法,它可以工作,但需要设备管理。play.google.com/store/apps/...
乔治

您在这个问题上遇到了什么吗?
Muhammed Refaat

Answers:


69

我将假设您只希望在应用程序处于前台时才生效。

这段代码:

params.flags |= LayoutParams.FLAG_KEEP_SCREEN_ON;
params.screenBrightness = 0;
getWindow().setAttributes(params);

传统意义上不会关闭屏幕。它使屏幕尽可能暗。在标准平台上,它的暗淡程度是有限制的。如果您的设备实际上允许屏幕完全关闭,则说明该设备的实现有些特殊之处,而不是您可以指望跨设备使用的行为。

实际上,将其与FLAG_KEEP_SCREEN_ON结合使用意味着即使特定的设备允许您将屏幕亮度设置为全屏,也绝不会允许屏幕关闭(从而使设备进入低功耗模式)。请牢记这一点。您将比屏幕真正关闭时消耗更多的电量。

现在要将屏幕恢复为常规亮度,只需设置亮度值即可:

WindowManager.LayoutParams params = getWindow().getAttributes();
params.screenBrightness = -1;
getWindow().setAttributes(params);

我无法解释为什么这不能代替您先前设置的0值。作为测试,您可以尝试在其中放置强制全亮度以强制达到该特定亮度:

WindowManager.LayoutParams params = getWindow().getAttributes();
params.screenBrightness = 1;
getWindow().setAttributes(params);

这绝对有效。例如,Google的“图书”应用使用此功能可让您在使用图书时将屏幕亮度设置为暗淡,然后在关闭时将其恢复为常规亮度。

为了帮助调试,您可以使用“ adb shell dumpsys window”来查看窗口的当前状态。在窗口数据中,它将告诉您已为其设置的当前LayoutParams。确保您认为真正存在的价值。

同样,FLAG_KEEP_SCREEN_ON是一个单独的概念;它和亮度不会相互直接影响。(并且,如果在将亮度设置为0时已经设置了该标志,则没有理由在取消亮度时再次设置该标志。该标志将保持设置状态,直到您对其进行更改。)


8
是否有更好的方法关闭筛网?
akash 2013年

如@hackbod所述,“ params.screenBrightness = 0;” 不能完全关闭屏幕;而是使屏幕尽可能暗。和“ params.screenBrightness = -1;” 将屏幕恢复到之前的亮度级别。但是,在某些情况下,我们需要完全关闭屏幕。可能还有其他方法...
jonathanzh 2015年

6
那些实际上会关闭屏幕而不仅仅是设置可能会或可能不会工作的最小亮度的其他方法是什么?
迈克尔

37

我编写了此方法来在屏幕锁定后打开屏幕。它非常适合我。试试吧-

    private void unlockScreen() {
        Window window = this.getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
        window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
        window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
    }

并从调用此方法onResume()


1
如果您打算在要终止活动时打开屏幕,则该功能将无用。
AndroidDev

7
好的,我建议不要使用我的方法,因为这在Micromax Canvas2 +上对我不起作用。请改用此链接
Rajkiran 2013年

28

我建议这个:

PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "tag");
wl.acquire();

标志ACQUIRE_CAUSES_WAKEUP的解释如下:

正常的唤醒锁实际上不会打开照明。取而代之的是,一旦照明打开(例如,来自用户活动),它们就会使照明保持打开状态。当获取WakeLock时,此标志将强制屏幕和/或键盘立即打开。典型的用途是用于通知,这对于用户立即查看很重要。

另外,请确保您在AndroidManifewst.xml文件中具有以下权限:

<uses-permission android:name="android.permission.WAKE_LOCK" />

3
不幸的是,标志SCREEN_BRIGHT_WAKE_LOCK已被弃用。
卡米尔·塞维尼(CamilleSévigny)2014年

20

嗨,我希望这会有所帮助:

 private PowerManager mPowerManager;
 private PowerManager.WakeLock mWakeLock;

 public void turnOnScreen(){
     // turn on screen
     Log.v("ProximityActivity", "ON!");
     mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "tag");
     mWakeLock.acquire();
}

 @TargetApi(21) //Suppress lint error for PROXIMITY_SCREEN_OFF_WAKE_LOCK
 public void turnOffScreen(){
     // turn off screen
     Log.v("ProximityActivity", "OFF!");
     mWakeLock = mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "tag");
     mWakeLock.acquire();
}

如何在不涉及接近传感器的情况下关闭屏幕?
迈克尔

@Michael,您好,您仅使用public void turnOffScreen()函数
mangu23 '16

3
是的,但是似乎使用此功能PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK仅在接近传感器处于“附近”状态时才关闭屏幕。
迈克尔,


1
问题-一旦我释放PROXIMITY_SCREEN_OFF_WAKE_LOCK等待锁,屏幕就会重新打开。我该如何预防?
迈克尔

7
     WakeLock screenLock =    ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(
    PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
    screenLock.acquire();

  //later
  screenLock.release();

//用户清单文件


2
这应该是正确的答案。我正在使用Android 5,这是唯一有效的方法。唯一的注释是SCREEN_BRIGHT_WAKE_LOCK已过时,我看不到直接替代产品。任何人?
HammerNL

没问题,您的答案完全可以使用。正如我所说:“这是唯一
可行的

@HammerNL这个答案和ramdroid提供的答案有什么区别?
错误发生

@BugsHappen Ramdroids更加复杂:)但是,是的,它是相同的。不知道为什么Pir Fahim Shah发布了这个答案,或者为什么我当时没有看到Ramdroids。
HammerNL '18

6

您确定在清单文件中请求了适当的权限吗?

<uses-permission android:name="android.permission.WAKE_LOCK" />

您可以使用AlarmManager 1类触发旨在启动您的活动并获取唤醒锁的意图。这将打开屏幕并保持打开状态。释放唤醒锁将使设备自行进入睡眠状态。

您还可以看一下使用PowerManager将设备设置为休眠状态:http : //developer.android.com/reference/android/os/PowerManager.html#goToSleep(long)


1
感谢您的回复。是的,我敢肯定。它在我的清单中,没有调试错误。当我使用传感器打开屏幕时,AlarmManager不会帮助我。我的goToSleep运气不太好,但是,这仍然无法帮助我打开屏幕。我目前能够关闭屏幕
thegreyspot 2012年

5

最好的方法(使用有根设备):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    .
    .
    .

    int flags = WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
    getWindow().addFlags(flags); // this is how your app will wake up the screen
    //you will call this activity later

   .
   .
   .
}

现在我们有两个功能:

private void turnOffScreen(){

  try{
     Class c = Class.forName("android.os.PowerManager");
     PowerManager  mPowerManager = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
     for(Method m : c.getDeclaredMethods()){
        if(m.getName().equals("goToSleep")){
          m.setAccessible(true);
          if(m.getParameterTypes().length == 1){
            m.invoke(mPowerManager,SystemClock.uptimeMillis()-2);
          }
        }
     } 
  } catch (Exception e){
  }
}

还有这个:

public void turnOnScreen(){
  Intent i = new Intent(this,YOURACTIVITYWITHFLAGS.class);
  startActivity(i);
}

对不起,我的英语不好。


您好,Rodrigo Gontijo为什么我们需要根设备pl。告诉我?
Kinjal

@Kinjal,因为您需要调用该函数(“ goToSleep”),并且此函数需要特殊权限,仅授予系统应用程序:<uses-permission android:name =“ android.permission.DEVICE_POWER” />
Rodrigo Gontijo

好的,谢谢,如果可能,请提供链接或逐步引导设备。提前致谢。
Kinjal

4

这是在支持较低屏幕亮度值的设备上实现相同操作的成功示例(我在运行API15的Allwinner中文7英寸平板电脑上进行了测试)。

WindowManager.LayoutParams params = this.getWindow().getAttributes();

/** Turn off: */
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
//TODO Store original brightness value
params.screenBrightness = 0.1f;
this.getWindow().setAttributes(params);

/** Turn on: */
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
//TODO restoring from original value
params.screenBrightness = 0.9f;
this.getWindow().setAttributes(params);

如果其他人尝试了此方法,请在下面评论该设备是否有效,以及设备(Android API)是否有效。


2
在我的设备nexus 7上,它不能很好地工作,屏幕仍然亮着,只是稍暗一些,但不是全黑。
JackWM

当然,该实现不应用于公共发行,尽管它可以与特定设备集成。我将保留该职位,因为它可能会在以后对某人有所帮助。
2013年

3

要保持屏幕显示:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

返回屏幕默认模式:只需清除标志FLAG_KEEP_SCREEN_ON

getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

3

这是在棉花糖上

private final String TAG = "OnOffScreen";
private PowerManager _powerManager;
private PowerManager.WakeLock _screenOffWakeLock;

public void turnOnScreen() {
    if (_screenOffWakeLock != null) {
        _screenOffWakeLock.release();
    }
}

public void turnOffScreen() {
    try {
        _powerManager = (PowerManager) this.getSystemService(POWER_SERVICE);
        if (_powerManager != null) {
            _screenOffWakeLock = _powerManager.newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
            if (_screenOffWakeLock != null) {
                _screenOffWakeLock.acquire();
            }
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

如果您解释您的回答为什么起作用,这将非常有用,这将有助于SO成员更好地理解。
dkb

关闭屏幕效果不佳...当接近传感器从近到远时,屏幕会重新打开...并且如果我在此之前释放唤醒锁,它仍会立即打开!
迈克尔


2

如果您的应用是系统应用,则可以使用PowerManager.goToSleep()关闭屏幕,需要特殊权限

在使用goToSleep()之前,您需要使用反射,如下所示:

public static void goToSleep(Context context) {
    PowerManager powerManager= (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    try {
        powerManager.getClass().getMethod("goToSleep", new Class[]{long.class}).invoke(powerManager, SystemClock.uptimeMillis());
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
}

现在,您可以使用goToSleep()关闭屏幕。

当按下电源键关闭屏幕时,会发生这种情况。


2

只需添加

android:keepScreenOn="true" 

或致电

setKeepScreenOn(true) 

在父视图上。


1

我不会希望在活动中“唤醒屏幕”。如果屏幕关闭,则该活动可能处于暂停状态,并且不应运行任何代码。

醒来时,出现锁屏问题。我不知道任何应用程序都可以自动绕过锁屏。

您应该考虑在服务中运行后台任务,然后在检测到任何内容时使用通知管理器发送通知。该通知应提供某种设备警报(屏幕唤醒,通知图标,通知指示灯等)。单击通知时,它可以启动意图以开始您的活动。

您也可以尝试直接从服务启动活动,但是我真的不知道这是否会打开屏幕或绕过锁定屏幕。


谢谢您的回应,我输入了一些振动代码,当我关闭屏幕并激活一个传感器时,它就会振动。因此,代码肯定正在运行。锁屏不是什么大问题,我只使用键盘锁。
thegreyspot 2012年

即使代码运行,它也处于生命周期之外。您不能信任不在屏幕上的活动。想想游戏下载器,大多数是写在活动中的,您可能会离开30秒钟到几分钟,他们仍然会下载,但它们通常会中断,因为操作系统会根据您的使用模式终止活动。
HaMMeReD 2012年

1

根据Android API 28及更高版本,您需要执行以下操作以打开屏幕

setShowWhenLocked(true); 
setTurnScreenOn(true); 
KeyguardManager keyguardManager = (KeyguardManager)
getSystemService(Context.KEYGUARD_SERVICE);
keyguardManager.requestDismissKeyguard(this, null);

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.