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状态。


  • 2018-10-27 16:36:09

    关于 android 中 postDelayed方法的讲解

    当然,你也可以做一个闹钟提醒延时的函数试试,比如,先用MediaPlayer播放闹钟声音, 如果不想起,被停止播放之后,下次就5分钟后再播放,再被停止的话,下次就4分钟后播放,

  • 2018-10-27 17:24:45

    使用localstorage和预加载做到webview秒开

    提到网页加载速度优化,大家都会想到静态资源上CDN,CSS和JS文件合并,图片合并成雪碧图等常用手段;但是在某些特殊情况下这些常用方法也无法达到理想的效果。比如,在国际化场景下,很多国家还停留在2G网络阶段,无论如何优化,都无法避免过慢的网络请求。最近一直在做国际化(主要是印尼和泰国)背景下的webview性能优化,也算有一些经验。由于我们的产品是面向android用户的,而android手机对H5支持很好,因此我们主要是应用H5的新特性。

  • 2018-10-28 10:50:26

    VectorDrawable简单介绍

    在项目中使用矢量图至少可以缩小我们apk包的尺寸,而且可以在屏幕适配时提供很大的方便,因为矢量图是分辨率无关的。

  • 2018-10-28 11:14:29

    矢量资源工具Vector_Asset_Studio

    Android Studio有一个称为“Vector Asset Studio”的工具, 它可以将SVG文件和PSD文件转化为工程可用的矢量可绘制资源(vector drawable resources),

  • 2018-10-28 11:16:09

    Android vector标签 PathData 画图超详解

    SVG是一种矢量图格式,是Scalable Vector Graphics三个单词的首字母缩写。在xml文件中的标签是<vector>,画出的图形可以像一般的图片资源使用,例子如下

  • 2018-10-30 00:16:41

    android ToolBar 设置颜色

    app:popupTheme——有时候我们有需求:ActionBar文字是白的,ActionBar Overflow弹出的是白底黑字让ActionBar文字是白的,那么对应的theme肯定是Dark。可是让ActionBar弹出的是白底黑字,那么需要Light主题。这时候popupTheme就派上用场了。android:theme 与app:theme——在AppCompat v21里,提供了一个快速方便的方法设置Toolbar的主题,使用app:theme。而新版本22.1.x中,AppCompat 允许对 Toolbar 使用 android:theme代替 app:theme。最好的一点是:它会自动继承父视图的theme ,并且兼容所有APIv11以上的设备。