PowerManager之PowerManager

2018-04-04 23:52:03

1.何时需要使用WakeLock?

A wake lock is a mechanism to indicate that your application needs to have the device stay on.

当你在做一些事情时,如果持续时间过长,那么一段时间后屏幕会灭掉,如果你想在你做这些事时屏幕始终保持点亮状态,那么你需要WakeLock的帮助。

比如:视频播放器在播放视频过程中,一段时间无操作后就会休眠灭屏,那么用户就需要每隔一段时间就去做类似触摸屏幕的操作来保持屏幕常亮,用户是不会接受这样的视频播放器,那么你就需要WakeLock啦。


2.如何使用WakeLock?

sample code:


[java] view plain copy

  1. PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);  

  2. PowerManager.WakeLock wl = pm.newWakeLock(  

  3.                                      PowerManager.SCREEN_DIM_WAKE_LOCK  

  4.                                      | PowerManager.ON_AFTER_RELEASE,  

  5.                                      TAG);  

  6. wl.acquire();  

  7. // ... do work...  

  8. wl.release();  

  9. }  

Any application using a WakeLock must request the android.permission.WAKE_LOCK permission--需要在AndroidManifest.xml中声明使用这个permission。


使用过程:首先创建实例,然后acquire保持屏幕点亮,然后做你的事情,做完后,一定要release,这样屏幕会在合适的时候熄灭,这对电池的续航很重要。


3.关于newWakeLock方法

Creates a new wake lock with the specified level and flags--创建实例,但同时指明了WakeLock的级别和flag。


[java] view plain copy

  1. public WakeLock newWakeLock(int levelAndFlags, String tag) {  

  2.     validateWakeLockParameters(levelAndFlags, tag);  

  3.     return new WakeLock(levelAndFlags, tag);  

  4. }  

首先讨论级别:


一共有五个级别,对应用可见的只有四个级别。


[java] view plain copy

  1. public static final int PARTIAL_WAKE_LOCK = 0x00000001;  

  2. public static final int SCREEN_DIM_WAKE_LOCK = 0x00000006;  

  3. public static final int SCREEN_BRIGHT_WAKE_LOCK = 0x0000000a;  

  4. public static final int FULL_WAKE_LOCK = 0x0000001a;  

  5. {@hide}  

  6. public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020;  

  7. public static final int WAKE_LOCK_LEVEL_MASK = 0x0000ffff;  

Exactly one wake lock level must be specified as part of the {@code levelAndFlags} parameter.
在newWakeLock时,必须指定级别,否则会抛出异常信息:throw new IllegalArgumentException("Must specify a valid wake lock level.");


这几个级别之间的差别,留在后面分析,这里先跳过。

Flag只有两种:


[java] view plain copy

  1. //Turn the screen on when the wake lock is acquired.  

  2. public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;  

  3. //When this wake lock is released, poke the user activity timer so the screen stays on for a little longer.  

  4. public static final int ON_AFTER_RELEASE = 0x20000000;  

ACQUIRE_CAUSES_WAKEUP:


一般地,WakeLock并不会真的唤醒设备,它的作用只是在屏幕是亮的状态下保持这种亮的状态。但是有时我们需要它能不仅仅是保持亮,还能把它从灭唤醒,那么就需要这个flag:在acquired时,它会唤醒屏幕。

ON_AFTER_RELEASE:

在release时,它会重置timeout,这样能让屏幕保持亮的状态稍久一些。当然,如果已经灭了,它也不能在唤醒屏幕。


level和flag可以一起使用,但是PARTIAL_WAKE_LOCK是个例外,如果是这个level,那么不能使用这两个flag(备注:如果你这样使用了并不会报错,只是这两个flag不会起作用,会被忽略)。

留意WAKE_LOCK_LEVEL_MASK,它的作用很清楚:既然level和flag可以一起使用,那么就规定level之占用较低的两个字节,flag则使用较高的两个字节。


4.关于acquire和release

这是一对操作,一般地,调用多少次acquire,就要相应地调用相同次数的release:

如果acquire多于release,那么屏幕会一直保持点亮的状态;

如果release多于acuire,那么会抛出异常:throw new RuntimeException("WakeLock under-locked " + mTag);

WakeLock中有个变量mCount负责记录,当acquire时增一,release时减一。

实际的操作还是由PowerManagerService的acquireWakeLock和releaseWakeLock方法来实现。


public void acquire(long timeout)

acquire的这个方法允许传人一个参数,那么在timeout时间之后,会自动调用release一次。


public void setReferenceCounted(boolean value)

这个方法的作用(默认value为true,可以通过此方法将其设置为false):若为false,则不管之前调用了多少次acquire,一次release就ok啦。


5.关于level的讨论

这是SDK中的一张图,从这张图我们可以看到WakeLock控制了哪些器件:CPU、Screen和Keyboard。


看起来,似乎FULL_WAKE_LOCK最强大,它保持三个器件都处于on或bright的状态,但请注意,如果用户按下power键使手机进入sleep状态时,这三个器件将都不再on或bright,都会进入休眠状态。

而PARTIAL_WAKE_LOCK是比较特别的,它的on上打了个*标记:即使用户按下power键使手机进入sleep状态,如果持有这个level的WakeLock,那么CPU也会一直处于on的状态,直到它被释放,也就是在这个level下,用户是无法使CPU off的。相比其它三个level,用户可以在任何时候使他们处于off状态。


  • 2020-03-20 13:35:55

    随便想到,群聊天的数据库简单设计

    拆分成两个表,一个是消息的流水表,一个是每个人的配置表。 记录每个群下面的这个用户的最后读取的消息last_msg_id,然后在计算消息未读数据。 这样优化之后数据将减少好多,数量是 m+n条数据。不在是成倍增长了。

  • 2020-03-20 13:39:50

    类似与微信朋友圈功能数据库如何实现

    每次发圈子的时候,给关注我的每个uuid,发一个内容id。 大概表的设计就是 uuid,idlist 这样的,idlist是按照时间顺序的。 然后定期删除idlist过多的老圈子。

  • 2020-03-21 00:11:38

    Android卡片布局(圆角阴影)的几种实现及分析

    在开发中,为了界面美观,圆角view和阴影效果是开发中经常遇到的UI场景,比如银行卡效果,卡片式itemView布局,Banner图等,开发中我们通过各种方式实现了这种效果,但是哪种方案最好呢,接下来本文将比较几种常见的圆角阴影布局实现,并从内存占用角度分析它们的优缺点.

  • 2020-03-21 12:05:24

    android 自定义组件,使用AttributeSet

    首先要在res/values目录下建立一个attrs.xml(名字可以自己定义)的文件,并在此文件中增加对控件的属性的定义.其xml文件如下所示:

  • 2020-03-21 12:09:59

    Android使用AttributeSet自定义控件的方法

    我们可以在attrs.xml中声明自己控件的属性,在布局xml文档中声明自己的命名空间,这时就可以对设置自己想要的值了,然后在AttributeSet这个属性中获取对应的值。好了不多说,我们来看下代码,一切尽在不言中:

  • 2020-03-22 21:16:07

    用vue做的跟随鼠标移动的div

    最近接到一个任务,就是在既存用electron-vue开发的桌面端程序上追加随鼠标移动的动画效果,之前一直使用angular和react,没怎么接触过vue,先做一个vue的简单例子,然后再整合。