安卓手机 - 关闭屏幕但不让手机进入睡眠/锁屏状态 - 触摸屏幕开启

30
我一直在尝试找到一种方法来关闭显示屏,并且可以通过用户触摸触摸屏幕唤醒。设备处于嵌入式环境中,其中设备是平板电脑,用户除了触摸屏幕之外没有访问任何东西(完全没有按钮)。
设备已连接电源,因此电池不会成为问题,但当我检测到没有活动时,我想关闭屏幕,这样它就不会整天盯着他们的脸,也不会减少LCD背光的寿命。
我永久保持一个wakelock并自行决定何时休眠。
问题在于,当我使用以下命令关闭屏幕时:
WindowManager.LayoutParams params = getWindow().getAttributes();
params.screenBrightness = 0;
getWindow().setAttributes(params);

这个设备会暂停和停止活动,不会响应触摸唤醒。需要按下电源键来唤醒,这时才会显示“滑动解锁”。

我想关闭显示屏,但仍然让设备运行以便能够检测到触摸屏幕事件并重新打开显示屏。

我还尝试把显示屏亮度设置为0.1,在某些设备上可以工作,但是我需要的那个设备只是“调暗”了显示屏。

我也尝试了这个方法:

// First Remove my FULL wakelock

//then aquire a partial wake lock (which should turn off the display)
PowerManager.WakeLock wl = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Your Tag");

wl.acquire();

然而,这种方法并不会关闭显示器。


1
如果我理解正确的话,您已经成功地保持了您的活动运行,剩下的问题是如何关闭屏幕。为此,我建议实现一个没有布局的置顶辅助活动 - 在这种情况下,Android 显示黑屏。您可以使用 android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 来进行全屏黑屏。 - Stan
3
针对我的情况,使用唤醒锁定实现的黑屏不够用,因为屏幕背光依然开着,所以即使是全屏黑色活动,完全黑暗的房间里仍然太亮了——我仍然可以看到设备屏幕,但其实我不应该看到。 - Mathias Conradt
你对这个问题有什么进展吗?!! - Muhammed Refaat
很不幸,没有太多的解决方案。我的解决方法是从其他触发器中唤醒。在我的情况下,通过注册BroadcastReceiver检查设备是否正在充电来实现。这在我非常特定的情况下是可以接受的。我尝试过的另一件事,并且有一些成功的经验是使用传感器来检测设备的移动。注册这些事件的接收器允许我在它们发生时应用wakelock来触发唤醒。希望这有所帮助。 - NebulaSleuth
4个回答

7
最后终于搞明白了,希望能有所帮助。:)
  • Get an instance of WindowManager.

    WindowManager windowManager = (WindowManager) Class.forName("android.view.WindowManagerImpl").getMethod("getDefault", new Class[0]).invoke(null, new Object[0]);

  • Create a full screen layout xml(layout parameters set to fill_parent)

  • Set your view as not clickable, not focusable, not long clickable, etc so that touch is passed through to your app and the app can detect it.

    view.setFocusable(false);
    view.setClickable(false);
    view.setKeepScreenOn(false);
    view.setLongClickable(false);
    view.setFocusableInTouchMode(false);

  • Create a layout parameter of type android.view.WindowManager.LayoutParams. LayoutParams layoutParams = new LayoutParams();

  • Set layout parameter like height, width etc

    layoutParams.height = LayoutParams.FILL_PARENT; 
    layoutParams.width = LayoutParams.FILL_PARENT;
    layoutParams.flags = 280; // You can try LayoutParams.FLAG_FULLSCREEN too
    layoutParams.format = PixelFormat.TRANSLUCENT; // You can try different formats
    layoutParams.windowAnimations = android.R.style.Animation_Toast; // You can use only animations that the system to can access
    layoutParams.type = LayoutParams.TYPE_SYSTEM_OVERLAY;
    layoutParams.gravity = Gravity.BOTTOM;
    layoutParams.x = 0;
    layoutParams.y = 0;
    layoutParams.verticalWeight = 1.0F;
    layoutParams.horizontalWeight = 1.0F;
    layoutParams.verticalMargin = 0.0F;
    layoutParams.horizontalMargin = 0.0F;
    
  • Key step: You can set what percentage of brightness you need. view.setBackgroundDrawable(getBackgroundDrawable(i));

    private Drawable getBackgroundDrawable(int i) {
    int j = 255 - (int) Math.round(255D * Math.exp(4D * ((double) i / 100D) - 4D));
    return new ColorDrawable(Color.argb(j, 0, 0, 0));}
    
  • Finally add view to windowManager that you created earlier.

    windowManager.addView(view, layoutParams);

注意:您需要SYSTEM_ALERT_WINDOW权限才能在屏幕上覆盖叠加层。
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

我已测试过,它可以正常工作。如果你遇到困难,请告诉我。

2
这并没有真正关闭背光,对吧?“我想要关闭屏幕,这样它就不会减少液晶背光的寿命。” - Michael
只在JB上测试过,之后没有进行测试。 - Bharath Lakshman
我在实现这个过程中遇到了问题。有人有一个我可以查看的示例项目吗? - Old Badman Grey
它可以关闭屏幕,但无法在触摸屏幕后再次打开。 - Muhammed Refaat

1

如果您的服务使用唤醒锁,但如果您是从Activity端进行操作,则最好使用标志来获取标志。

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); // For keeping screen on
        // You can blur screen or dim screen using following flags
        // FLAG_BLUR_BEHIND -   Blur screen
        // FLAG_DIM_BEHIND - Dim Behind

您可以清除这些标志并施加其他标志来调暗屏幕或模糊它。

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

希望这能解决您的问题。您还可以从http://developer.android.com/reference/android/view/Window.html中探索其他标志。

另外,还有一个提示:在Android中调用隐藏API关闭屏幕


如果我移除了wakelock并使用这种方法来防止设备进入睡眠状态,我仍然无法关闭显示屏而不停止我的活动。 - NebulaSleuth
1
好消息是:调用隐藏的API函数setScreenState可以关闭显示屏,而不会暂停或停止我的活动。坏消息是:它似乎也禁用了触摸屏... - NebulaSleuth
@NebulaSleuth 你找到解决方案了吗?我也需要屏幕在完全变暗的情况下仍然能够监听触摸事件。谢谢! - Mathias Conradt
1
这里只是提出一个想法...既然你说成功关闭了屏幕而不是让手机进入睡眠状态,为什么不使用加速度计来检测屏幕上的轻敲并将其打开呢? - Mircea Nistor
据我所知,当屏幕关闭(手机处于休眠状态)时,加速度计不起作用。我尚未成功关闭屏幕而不使手机进入睡眠状态。NebulaSleuth提到他成功使用了隐藏的API,但是对我来说并不起作用(http://pastebin.com/WQKR857z)- 在安卓2.3.6上的Nexus One手机上。 - Mathias Conradt
@ Mathias - 我从来没有完全解决过这个问题。基本上,我仍然只能显示黑屏,并将背光设置为极亮的最低亮度。 - NebulaSleuth

0

我不知道这是否对你有所帮助,但是你可以简单地使用唤醒锁定功能,让屏幕保持开启并显示一个ImageView来展示黑色图片。


8
谢谢,但实际上这已经是我们目前拥有的现状了。不幸的是,这并不足够,因为屏幕背光仍然亮着,所以即使使用黑色全屏活动,完全黑暗的房间里仍然太亮了 - 我仍然可以看到设备屏幕,但我不应该看到它。在我的情况下,我需要这个功能来控制安装在酒店房间里的平板电脑(用作各种设备的控制面板)。在完全黑暗的房间里,不应该有任何光线,甚至不应该有暗淡的屏幕背光。只有当用户触摸设备时,屏幕才会开启。 - Mathias Conradt
1
我认为唯一的方法是构建一个定制的ROM并修改内核。这是针对三星Galaxy Tab 1的。但仍需要检查哪些内核类是相关的。 - Mathias Conradt
@MathiasLin 你知道哪些内核文件是需要编辑的,以构建这个定制ROM吗? - Vins
@vins 不记得了,太久以前的事了。 - Mathias Conradt
1
@MuhammedRefaat 我记不得我曾经工作的项目已经是4年前的事了。至少,我没有通过应用程序代码来管理它。最终,其中一位开发人员通过内核调整完成了它,但我已经记不清楚了。 - Mathias Conradt
显示剩余2条评论

0

你可以通过获取部分唤醒锁并关闭屏幕来实现:

PowerManager.WakeLock wl = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Your Tag");
wl.acquire();
WindowManager.LayoutParams params = getWindow().getAttributes();
params.screenBrightness = 0;
getWindow().setAttributes(params);

这将把亮度设置为最低水平,但不会关闭显示。 - Muhammed Refaat

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