提问者:小点点

理解


我正在努力让我的Android应用成为后AndroidM世界的好公民,后AndroidM世界对应用在设备打瞌睡时能做什么/不能做什么施加了严格的限制。我对所涉及的问题的理解仍然相当零碎,所以我希望这里有人能填补空白。

打瞌睡的持续时间

我自己的经验发现

  • 在静止、关闭屏幕、不活动后大约半小时内开始打瞌睡
  • 第一个维护窗口发生在30分钟内
  • 下一个发生在大约一个小时后
  • 在ca 2,4和6 h之后的那些。我没有测试超过那个

这些是官方的Android打瞌睡时间,还是只是一个经验观察。

以上所有内容都在Android N设备上。

在打瞌睡模式下测试应用程序

  • 使用ADB将设备连接到计算机
  • 将应用程序带到前台
  • 关闭设备屏幕
  • 从命令行发出adb shell dumfos电池拔掉
  • 现在循环通过命令'adb shell dumints device空闲步进灯或深
  • 最后发出adb shell dumfos电池复位

进入/退出打瞌睡

>

  • 当屏幕关闭且设备未被移动时发生

    据推测,这使用了手机中的运动传感器,因此静静地坐在非常平稳行驶的火车上的手机仍然会打瞌睡?

    如果我拿起一个打瞌睡的手机,开始带着它四处走动,而不与它互动,它会自动退出打瞌睡吗?

    假设我的应用程序在其主机设备进入打瞌睡时不在前台。然后我再次开始使用该设备,但没有访问该应用程序。它会再次自动开始“工作”,即

    它的广播接收器会正常工作吗?

    它的处理程序将开始工作?

    它的带有setInvresDeviceIdle(true)的计划作业将停止被调用?

    打瞌睡的各种模式

    >

  • 据我所知,有两种打瞌睡模式

    灯:活动,空闲,Idle_Maintenance,覆盖。我不明白各种模式做什么。从ADB我已经发出步进灯屏幕上,看到返回值活动。随着屏幕关闭步进灯返回IDLE

    深度:活动,IDLE_PENDING,SENSING,LOCATING,空闲,IDLE_MAINTENANCE屏幕打开时也返回活动,但屏幕关闭时返回IDLE_PENDING。那么其他子模式,空闲,SENSING…到底是什么时候发生的呢?

    我假设IDLE_MAINTENANCE发生在设备从DOZE进入维护窗口并尝试运行来自各种应用程序的挂起作业请求时。

    但如果是这种情况,为什么PowerManager. isDeviceIdleMode()PowerManger.isPowerSaveMode()在我的应用程序中运行计划作业时检查它们时总是返回false

    JobInfo. Builder非常友好地允许您设置诸如set最小延迟setOverrideDeadline之类的标准,但据我所知,OS母鸡会轻率地忽略它们——有时我的工作会在几秒钟内运行,有时会间隔两个小时。

    为什么没有API函数来测试打瞌睡及其子模式?我希望在PowerManager中找到它,但我发现有isDeviceIdleModeisPowerSaveMode,每当测试时始终返回false

    打瞌睡模式下的应用程序

    >

  • 它的所有后台服务都会被销毁吗?

    不会获取到正常优先级的推送消息?

    不会响应警报-但除了setAndAllowWhenIdle之外吗?

    不会得到任何广播接收器的通讯?

    将无法在套接字上连接到外部世界-因此推送消息、发布/订阅等将不起作用?

    将立即销毁Android清单中声明的任何广播接收器。这是我自己的发现——我用Java代码创建的接收器留在原地,尽管它们在打瞌睡时不起作用。

    我自己的应用程序通过设置广播接收器并调用来监视地理位置的变化。FusedLocationApi. request estLocationUpdate。这个接收器在打瞌睡/唤醒周期中幸存下来。但是,是否可以保证我的LocationUpdate请求在醒来后仍然得到满足?

    我遇到了一个相当奇怪的bug。我发现我在打瞌睡中的计划作业有时彼此之间跑得太近了,尽管我给了它们900,000毫秒(15分钟)的延迟和1,000,000毫秒的截止日期。我想我可以通过跟踪上次运行时间来测试最后一次运行作业来解决这个问题

    private static Boolean shortInstantGap()
    {
      Long instantNow = Instant.now().getEpochSecond();
      if (300 > (instantNow - this.lastInstant)) return true;
      //ignore the job opportunity if the last one was
      //less than 300s (5 minutes) ago
      this.lastInstant = instantNow;
      return false;
     }
    

    然后中止工作

    private static Runnable timeRunner = new Runnable() 
    {
     @Override
     public void run() 
     {
      if (shortInstantGap()) return;
      callMyHandlerCode();
     }
    };
    

    但是,我发现当我经历屏幕关闭屏幕打开周期时,如果应用程序在屏幕上,此代码会导致OS突然终止我的应用程序。为什么会这样?

    最后,有没有一个API电话我可以用来测试设备刚刚从打瞌睡回来,所以我有机会做一些打瞌睡后的家务?


  • 共1个答案

    匿名用户

    我认为这个帖子和问题很好,谢谢。真的希望AndroidOS将改善消息推送延迟。有时,如果你不触摸屏幕,它不会得到一个小时的通知。由于节省电池,这可能对一些用户有好处,但优化消息推送以及电池优化可以为每个人赢得双赢。

    不管怎样,这里我的2美分,是一些小建议,给那些想分析打瞌睡的东西和那些还没有意识到这些的人:

    无线调试功能可用于将设备与计算机/adb工具连接。因此,在连接测试时无需USB电缆和充电手机。我认为,由于Android 11大多数设备在开发人员选项下都有无线调试选项,因此无需USB电缆设置即可本机工作。如果没有可用的wifi调试(11之前的Android版本),则可以使用USB电缆进行设置。

    “adb shell dumints device空闲”此命令总结了一些信息,例如打瞌睡状态和子状态,可用于在打瞌睡/应用程序测试期间检查当前状态。

    您可以检查其他adb打瞌睡命令及其效果,例如强制打瞌睡、启用/禁用它等。在线。