如何在我的应用打开且屏幕打开时允许 Android 打瞌睡?

Posted

技术标签:

【中文标题】如何在我的应用打开且屏幕打开时允许 Android 打瞌睡?【英文标题】:How can I allow Android to Doze while my app is open and the screen is on? 【发布时间】:2019-03-30 02:38:25 【问题描述】:

我正在通过Activity#setShowWhenLocked(true) 制作一个将在设备锁定时运行的应用程序。我不想阻止设备进入低功耗状态。我知道系统使用Always-On Display 执行此操作,并且显示器具有相关的电源模式:

/frameworks/base/core/java/android/view/Display.java

286    /**
287     * Display state: The display is dozing in a low power state; it is still
288     * on but is optimized for showing system-provided content while the
289     * device is non-interactive.
290     *
291     * @see #getState
292     * @see android.os.PowerManager#isInteractive
293     */
294    public static final int STATE_DOZE = ViewProtoEnums.DISPLAY_STATE_DOZE; // 3
295
296    /**
297     * Display state: The display is dozing in a suspended low power state; it is still
298     * on but the CPU is not updating it. This may be used in one of two ways: to show
299     * static system-provided content while the device is non-interactive, or to allow
300     * a "Sidekick" compute resource to update the display. For this reason, the
301     * CPU must not control the display in this mode.
302     *
303     * @see #getState
304     * @see android.os.PowerManager#isInteractive
305     */
306    public static final int STATE_DOZE_SUSPEND = ViewProtoEnums.DISPLAY_STATE_DOZE_SUSPEND; // 4

/frameworks/base/core/java/android/os/PowerManagerInternal.java也有这个板块:

51     * Wakefulness: The device is dozing.  It is almost asleep but is allowing a special
52     * low-power "doze" dream to run which keeps the display on but lets the application
53     * processor be suspended.  It can be awoken by a call to wakeUp() which ends the dream.
54     * The device fully goes to sleep if the dream cannot be started or ends on its own.
55     */
56    public static final int WAKEFULNESS_DOZING = 3;

如果可能,我想避免使用 root 来执行此操作,但如果所有其他方法都失败了,我可以manually control doze with root using these commands,但这听起来很乱,我不想搞砸任何其他应用的打瞌睡交互。

另外,我只特别关注 Android Pie (9.0) 及更高版本。

更新:

我也试过获取DOZE_WAKE_LOCK,但是需要系统权限DEVICE_POWER。我尝试adb shell pm grant 我的应用程序的权限,但它不是可更改的权限类型。

【问题讨论】:

您的应用需要做什么?播放内容?是否有任何后台服务正在进行或仅与用户界面有关? @YvetteColomb 我想主要显示静态信息(但可能经常需要更改或动画以避免老化) @BLuFeNiX 你找到解决办法了吗? @user3405331 不,很遗憾。不过,我对 Android 9 进行了初步研究,因此 Android 10 可能有一些方法可以实现这一点。 @BLuFeNiX 如果我们通过 adb 授予 WRITE_SECURE_SETTINGS 权限,那么我们可以编辑 device_idle_constants 一定有办法解决,但没有适当的文档 【参考方案1】:

您可以通过屏幕保护程序DreamService 执行此操作。你不能通过活动来做到这一点。 Activity 阻止设备进入睡眠模式。

Dreams 是充电设备启动时启动的交互式屏幕保护程序 闲置,或停靠在桌面底座中。梦想提供了另一种形式 应用程序来表达自己,为展览/靠背量身定制 经验。

【讨论】:

不幸的是,这仅在手机插入或对接时有效。我已经看过这个策略了,但是找不到在手机没有充电或没有对接时让 Dream 运行的合理方式。我尝试使用adb shell dumpsys battery 将电池状态模拟为正在充电,但这不是一个现实的解决方案。另外,Doze mode does not engage when the device is plugged into a power charger.【参考方案2】:

您想要的是 android wear 中的环境模式,它可以让活动在设备处于睡眠状态时显示可绘制对象(通常是一些带有黑色背景的白线)。据我所知,手机设备的代码没有这个功能,因为您的活动必须扩展一个名为 WearableActivity 的类,并由一个名为 Ambient 的系统应用程序管理。您找到的唤醒锁 DOZE_WAKE_LOCK 用于此 Ambient 应用程序。

【讨论】:

以上是关于如何在我的应用打开且屏幕打开时允许 Android 打瞌睡?的主要内容,如果未能解决你的问题,请参考以下文章

Android如何在屏幕关闭/打开时防止webview重新加载?

为啥我的“允许位置访问”在我打开时总是关闭?

使用人脸 ID 从锁定屏幕打开时应用程序被阻止

相机打开时如何释放相机?

在 Android 应用程序中单击并打开时,分支链接不提供数据

Android Soft Keyboard在重新打开时隐藏EditText