首页 > 编程知识 正文

Android M新特性Doze and App Standby模式详解,联想新blos模式详解

时间:2023-05-05 04:45:14 阅读:256013 作者:582

转载请标明出处:http://blog.csdn.net/xx326664162/article/details/52312122 文章出自:ttdbl的博客

你也可以查看我的其他同类文章,也会让你有一定的收货

一、Optimizing for Doze and App Standby

从Android6.0开始,Android提供了两种省电延长电池寿命的功能:Doze和App Standby;

表现形式:当设备没有连接到电源,设备进入Doze模式时,系统将通过延迟最近用户没有使用的应用程序的后台CPU运作及网络活动,让应用程序处于App Standby状态,以此来减少电池消耗。谷歌表示,在Nexus5和Nexus6上测试,当屏幕处于关闭状态,平均续航时间提高30%;

版本要求:Android6.0(API level 23)及其更高版本;

开发者影响:为了保证用户的最佳体验,开发者有必要在Doze和App Standby模式下测试应用程序,及其对代码进行相应的调整。

二、Understanding Doze 1.设备进入Doze睡眠模式时机:

用户不操作设备一段时间

屏幕关闭

设备未连接电源充电

2.Doze模式下应用程序有什么变化:

系统试图通过限制应用程序访问网络和CPU密集型服务节省电池;

防止应用程序访问网络,推延应用程序的工作,同步,和标准的警报;

系统定期提供一个短暂的时间让应用程序完成延迟的工作活动,之后再次进入Doze模式。在这个时间片里,系统将提供维持性窗口(maintenance window)应用程序可以在此时执行访问网络,同步,和报警等活动。

Doze模式的五种状态,分别如下:

ACTIVE:手机设备处于激活活动状态

INACTIVE:屏幕关闭进入非活动状态

IDLE_PENDING:每隔30分钟让App进入等待空闲预备状态

IDLE:空闲状态

IDLE_MAINTENANCE:处理挂起任务

如下图所示,Doze期间提供间隔一小段时间(30s)供应用程序使用网络和处理挂起的活动。

从这张图我们可以看到,系统进入Doze模式后,系统会隔一段时间处理正在挂起的任务,随着时间推移,后面间隔的时间会越来越长,以此来减少电量消耗。

3.退出Doze模式: 移动设备打开屏幕设备连接电源

以上三种情况会退出Doze模式,之后apps回复正常模式。

4.Doze有哪些限制?

网络连接会被禁止

Wake Lock会被屏蔽

AlarmManager定时任务延迟到下一个maintenance window进行处理,除非使用AlarmManager提供的方法:setAndAllowWhileIdle() 或者setExactAndAllowWhileIdle()

系统将不扫描热点WIFI

同步工作将被禁止

不允许JobScheduler进行任务调度

5.适配Doze模式有什么方法?

Doze影响到AlarmManager闹钟和定时器管理活动,在Android6.0引入了两个新方法:setAndAllowWhileIdle() 和setExactAndAllowWhileIdle(),调用两个方法可以在Doze模式下让系统响应定时任务。

Doze模式下限制了网络的连接,如果应用程序依赖于实时信息,那么这个将影响App的体验。那么你需要使用Google Cloud Messaging (GCM)谷歌云消息(后面详细讲解)

三、Understanding App Standby

当用户不触摸使用应用程序一段时间时,该应用程序处于App Standby状态,系统将把该App标志为空闲状态(idle)。除非触发以下任意条件,应用程序将退出App Standby状态:

用户主动启动该App;

该App当前有一个前台进程(或包含一个活动的前台服务,或被另一个activity或前台service使用);

App生成一个用户所能在锁屏或通知托盘看到的Notification, 而当用户设备插入电源时,系统将会释放App的待机状态,允许他们自由的连接网络及其执行未完成的工作和同步。如果设备空闲很长一段时间,系统将允许空闲App一天一次访问网络。

四、Doze和App Standby的区别:

Doze模式需要屏幕关闭(通常晚上睡觉或长时间屏幕关闭才会进入),而App Standby不需要屏幕关闭,App进入后台一段时间也会受到连接网络等限制。

五、DeviceIdleController

DeviceIdleController是Doze模式的主要驱动。接下来,我将使用device idle mode而不是doze mode来描述“Doze”,因为它更符合代码的实际情况。

5.1、deviceidle——新的系统服务

如果你已经阅读了官方文档,你可能已经注意到下面的命令,开发者可以通过这些命令得知当下设备的应用行为:

adb shell dumpsys battery unplug adb shell dumpsys deviceidle step

对于上面的命令你可能并不熟悉,dumpsys是用来与系统服务交互的(查看它们的状态)。deviceidle是我们之前没有看到过的,它是一个新的系统服务。用来检测是否进入idle mode(Doze模式)

$ adb shell service list | grep deviceidle 59 deviceidle: [android.os.IDeviceIdleController]

我们可以使用‘-h’看到所有的deviceidle的所有选项:

$ adb shell dumpsys deviceidle -h Device idle controller (deviceidle) dump options: [-h] [CMD] -h: print this help text. Commands: step Immediately step to next state, without waiting for alarm. disable Completely disable device idle mode. enable Re-enable device idle mode after it had previously been disabled. whitelist Add (prefix with +) or remove (prefix with -) packages. 5.2、DeviceIdleController的五种状态

DeviceIdleController维持着设备包含的五种状态,和上面介绍的Doze的五种状态是一样的:

ACTIVE – 设备在使用中,或者连接着电源。INACTIVE – 设备已经从ACTIVE状态中出来一段时间了(使用者关闭了屏幕或者拔掉了电源)IDLE_PENDING – 请留意,我们将进入idle mode.IDLE – 设备进入idle mode.IDLE_MAINTENANCE – 应用窗口已经打开去做处理.

1、当设备被唤醒和正在使用中,控制器就处于ACTIVE状态,
2、不活跃时间超时,用户关闭屏幕等等,将会使设备状态进入到INACTIVE.

3、INACTIVE状态下,DeviceIdleController将会通过AlarmManager来设置他自己的alarm来驱动进程:

一个alarm会被设置在一个预设的时刻(这个时间在M的预览中是30分钟)。
当这个alarm生效后,DeviceIdleController 会进入到IDLE_PENDING然后再次设置同样的alarm。

4、当触发下一个alarm后,控制器会进入到IDLE 状态,进入到这个状态后,应用特性会被完全限制。

5、IDLE 状态后,会在IDLE 和IDLE_MAINTENANCE两个状态之间周期性的跳转。IDLE_MAINTENANCE也就是Doze中提到的maintenance window,在这个状态下,应用程序可以在此时执行访问网络,同步,和报警等活动。

这些服务的公共API(由IDeviceIdleController 接口展现)持有全部方法访问白名单。应用(系统应用或其它第三方应用)任何情况下都不能驱动控制器状态

5.3、DeviceIdleController 维护着一个应用白名单

正如你在上面的帮助菜单中看到的一样,DeviceIdleController 维护着一个应用白名单,不需要额外的参数,通过dump服务的状态,我们能够看到现在的这个列表:

$ adb shell dumpsys deviceidle Whitelist system apps: com.android.providers.downloads com.android.vending com.google.android.gms Whitelist app uids: UID=10012: true UID=10016: true UID=10026: true …

这个名单分为两个部分:系统应用和第三方应用。

系统应用

系统应用会被平台制作者通过配置定义列在白名单中。下面这个是从Nexus 6中得到的一个配置定义例子,它将GMS核心(在GCM中使用),应用商店,以及一个任意的用于电源监控的app白名单化:

<?xml version="1.0" encoding="utf-8"?> <!-- These are configurations that must exist on all GMS devices. --> <config> <allow-in-power-save package="com.google.android.gms" /> <allow-in-power-save package="com.android.vending" /> <allow-in-power-save package="com.google.android.volta" /> </config>

其它的系统服务可以通过SystemConfig的实例访问到这些值。DeviceIdleController使用SystemConfig.getAllowInPowerSave()将这些系统定义的元素放到白名单中。

注意:当设备处于“省电模式”时,同样也是这个配置文件决定哪个系统应用可以在后台开启服务。

第三方应用

白名单中剩下的部分是用户定义的,这些项可以通过两种方式被增加和删除。

第一种:开发者可以通过dumpsys接口使用白名单命令: $ adb shell dumpsys deviceidle whitelist +com.example.myapplication $ adb shell dumpsys deviceidle Whitelist system apps: com.android.providers.downloads com.android.vending com.google.android.gms Whitelist user apps: com.example.myapplication Whitelist app uids: UID=10012: true 第二种:用户可以通过设置(Settings -> Battery -> Ignore optimizations)来修改白名单。

另外:在小米手机中,神隐模式中把应用设置为无限制或者在近期任务中下拉锁定,就会出现在上述的白名单中。

六、测试Doze和App Standby模式的方法(Adb命令) 测试Doze模式

1、 首先确保你的硬件或虚拟设备是Android6.0或更高版本系统;

2、 连接设备到开发机上并安装你的app;

3、 运行app并让其运行活动;

4、 关闭设备的屏幕;

5、运行以下adb命令使系统进入Doze模式:

$ adb shell dumpsys battery unplug$ adb shell dumpsys deviceidle step

你可能需要多次执行第二条命令,直到设备处于idle 状态。注意,第一条命令的意思是,拔去电源,即使现在正在插着usb调试,也不会充电。建议运行$ adb shell dumpsys battery reset,否则会出现手机充不上电的情况。

6、 观察你的app表现行为是否有需优化改进的地方。

测试App Standby模式

步骤1-3同测试Doze模式

4、 运行以下adb命令迫使系统进入App Standby模式:

$ adb shell dumpsys battery unplug$ adb shell am set-inactive <packageName> true

5、 模拟唤醒你的应用程序使用以下命令:

$ adb shell am set-inactive <packageName> false$ adb shell am get-inactive <packageName>

6、 观察你的App,确保应用程序可以从standby mode优雅得恢复,应该检查App的通知及后台能按预期的继续工作。

七、客户端使用方法:

App程序可发送action为ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS的intent引导用户进入设置界面将应用程序设置进白名单列表里。

应用程序还可以使用AREQUEST_IGNORE_BATTERY_OPTIMIZATIONS 权限来触发一个系统对话来让用户添加到白名单里,而无需进入设置界面去设置。

当然,官方也提供用户把你的App移除电池优化白名单的选项。这个白名单也会被Android M的另一个新特性 App Standby使用,所以用户只能简单的进行控制,也就是说设备并不会完全相信这个白名单。

这个白名单只是谷歌的一个建议,就是说在下面这些情况下,你可以使用上面两张方法,来引导用户把你的app设为白名单

官方举了一下白名单例子:

总结:

我认为Doze 模式和 APP Standby模式,限制app的权限种类都是一样的。都是进入idle状态。只是各自模式的进入和退出所需要的条件不一样、进入模式后控制APP的周期也不一样。

Doze模式的推出本身是为了减少电池的消耗,且Google希望统一使用GCM来传递消息进行通讯,而对于国内开发来讲,确实带来了很大的麻烦:

国内开发的一些消息推送机制(PUSH)将受到影响;

若使用GCM,在国内使用GCM延迟高,对于即时通讯产品来说选择还需勇气啊;

国内第三方手机厂商如华为、小米、三星,定制的Rom也将使用定制的推送消息机制。这让同一款App如何选择哪种推送机制才能兼容呢?

解决方法:

用户添加应用程序到电池优化白名单列表;

开发者使用Google提供的ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS意图和AREQUEST_IGNORE_BATTERY_OPTIMIZATIONS权限设置以此忽略(推荐);

使用Google提供的GCM;

通过so绕过Doze模式。

我使用MIUI 7.5(Android 6.0.1)测试过程中发现,自己维持长连接一进入standby模式,网络就断了(手机其它app网络正常),但是运行在后台的代码还是一直在跑,log也能正常输出到手机的文件上,就是连不上网。按照官方的描述进入standby模式,工作应该被挂起,但是为什么后台代码还是正常运行呢??请高人指点一下

微信的主进程可以手动设置为standby 模式,APP的子进程都是无法设置为standby 模式,但是如果主进程是standby 模式,子进程也会是standby 模式。即使使用命令查看子进程的standby 状态也是false。在正常使用手机的情况下,微信的主进程无法进入standby 模式,感觉是使用so绕过standby模式。具体so文件是怎么实现的,还请大神指点一下。

参考:
Optimizing for Doze and App Standby
Android M新特性Doze and App Standby模式详解
深入android6.0 设备 idle状态
Android M 的 Doze 模式下第三方推送服务还能用吗?

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。