Android:如何通过编程打开和关闭屏幕?

112

在将此帖子标记为“重复”之前,我写此帖子是因为没有其他帖子提供问题的解决方案。

我正在尝试关闭设备,然后在几分钟或传感器更改后重新打开设备。

关闭显示测试

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

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
你的关闭屏幕的方法对我不起作用。你设置了一个标志来一直保持屏幕亮着,这会消耗电量。 - Kristy Welsh
你最终解决了吗?PlayStore上有几个应用程序建议可以做到这一点。我尝试了这个,它可以工作,但需要设备管理权限。https://play.google.com/store/apps/details?id=com.katecca.screenofflock&hl=en - George
你在这个问题上有任何进展吗?!! - Muhammed Refaat
16个回答

71

我假设你只希望在应用程序处于前台时才启用此功能。

这段代码:

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时设置了它,则无需在撤消亮度时再次设置标志。标志将保持设置,直到您更改它。)


10
有没有更好的方法关闭屏幕? - akash
正如@hackbod上面所说的,“params.screenBrightness = 0;”并不能完全关闭屏幕,而是尽可能使屏幕变暗。“params.screenBrightness = -1;”将屏幕恢复到先前的亮度水平。然而,在某些情况下我们需要完全关闭屏幕。还可能有其他的方法... - jonathanzh
6
除了仅仅将屏幕亮度设置为最低可能有或没有效果的方法,有哪些可以真正关闭屏幕的其他方法? - Michael
1
我已将亮度设置为0.004,这使得屏幕非常昏暗。将其设置为0.003与将其设置为零相同。 - Mohamad Ghaith Alzin

38

我编写了这个方法来在屏幕锁定后打开屏幕。它对我来说完美地工作。试试吧-

    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
当您想要终止活动时,如果计划打开屏幕,则此内容无用。 - Johann
7
大家好,我建议不要使用我的方法,因为在Micromax Canvas2+上这种方式对我无效。请使用 这个链接 代替。 - Rajkiran

30

我建议使用这个:

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

ACQUIRE_CAUSES_WAKEUP标志的作用是这样解释的:

普通唤醒锁实际上不会打开屏幕背光灯,而是在它被打开后(例如由用户活动引起),使其一直保持亮着的状态。当获取WakeLock时,此标志将强制立即打开屏幕和/或键盘。典型用途是对于对用户来说非常重要的通知。

同时,请确保在AndroidManifest.xml文件中添加以下权限:

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

5
很不幸,SCREEN_BRIGHT_WAKE_LOCK 标志已被弃用。 - Camille Sévigny

22

嗨,我希望这能帮助到你:

 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
嗨,@Michael,你只需要使用public void turnOffScreen()函数即可。 - mangu23
3
是的,但似乎此功能使用PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,仅在接近传感器处于“靠近”状态时关闭屏幕。 - Michael
啊,好的,我明白了,你可以使用这个代替 PowerManager.SCREEN_DIM_WAKE_LOCK。 - mangu23
这在Android M以上版本中不起作用。有任何新的解决方案吗? - Nithinjith
2
问题 - 一旦我释放PROXIMITY_SCREEN_OFF_WAKE_LOCK等待锁定,屏幕就会重新点亮。我该如何防止这种情况发生? - Michael

8
     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
@HammerNL,这个答案和Ramdroid提供的答案有什么区别? - Bugs Happen
@BugsHappen Ramdroids的回答更详细 :) 但是没错,它们是一样的。不知道Pir Fahim Shah为什么发布了这个答案,或者为什么我当时没有看到Ramdroids的回答。 - HammerNL

6

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

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

你可以使用AlarmManager类1,发射一个intent来启动你的活动并获取唤醒锁定。这将打开屏幕并保持其开启状态。释放唤醒锁定将允许设备自行进入睡眠状态。
你还可以查看使用PowerManager将设备设置为睡眠状态:http://developer.android.com/reference/android/os/PowerManager.html#goToSleep(long)

1
谢谢您的回复。是的,我确定了。它在我的清单中,也没有调试错误。当我使用传感器打开屏幕时,AlarmManager对我没有帮助。我在使用goToSleep方面并没有太多的好运,但是即使如此,它仍然不能帮助我打开屏幕。目前,我能够让屏幕关闭。 - thegreyspot

6

只需添加

android:keepScreenOn="true" 

或者拨打电话

setKeepScreenOn(true) 

在父视图上。

5

使用 Rooted 设备的最佳方法:

@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){
  }
}

And this:

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

非常抱歉我的英文不好。


你好,Rodrigo Gontijo,请问为什么我们需要root设备?能否请您解释一下? - Kinjal
@Kinjal 因为你需要调用函数(“goToSleep”),而这个函数需要特殊权限,只授予系统应用程序: <uses-permission android:name="android.permission.DEVICE_POWER"/> - Rodrigo Gontijo
好的,谢谢。如果可能的话,请提供设备如何获取root权限的链接或步骤。提前感谢您。 - Kinjal

4

这是在Marshmallow上工作的。

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

如果您能解释为什么您的答案有效,这将有助于 Stack Overflow 社区成员更好地理解。 - dkb
关闭屏幕的效果不是很好...当接近传感器从近到远时,屏幕会重新亮起...如果在此之前释放唤醒锁定,它仍然会立即亮起! - Michael

4

这里有一个成功的例子,展示了如何在支持较低屏幕亮度值的设备上实现相同的功能(我在运行API15的全志中国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
那么,这个实现肯定不适合公开发布,尽管它可能用于与特定设备的集成。我会保留这篇文章,因为它可能对某些人有所帮助。 - ılǝ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接