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-12-04 15:30:01

    如何在Mac OS X上安装 Ruby运行环境

    ​ 对于新入门的开发者,如何安装 Ruby和Ruby Gems 的运行环境可能会是个问题,本页主要介绍如何用一条靠谱的路子快速安装 Ruby 开发环境。 此安装方法同样适用于产品环境!

  • 2018-12-04 15:31:15

    iOS--Pod install && Pod update

    许多人在最初接触CocoaPods时认为pod install只是在第一次为项目设置CocoaPods时使用,之后都应该使用pod update.看起来是这样,但也不是(But that's not the case at all.)。 这篇文章的目的就是教你啥时候用pod install,啥时候用pod update

  • 2018-12-04 15:33:19

    CocoaPods安装和使用教程

    当你开发iOS应用时,会经常使用到很多第三方开源类库,比如JSONKit,AFNetWorking等等。可能某个类库又用到其他类库,所以要使用它,必须得另外下载其他类库,而其他类库又用到其他类库,“子子孙孙无穷尽也”,这也许是比较特殊的情况。总之小编的意思就是,手动一个个去下载所需类库十分麻烦。另外一种常见情况是,你项目中用到的类库有更新,你必须得重新下载新版本,重新加入到项目中,十分麻烦。如果能有什么工具能解决这些恼人的问题,那将“善莫大焉”。所以,你需要 CocoaPods。

  • 2018-12-04 23:37:37

    pod install 和 pod update

    当我们新建一个Podfile文件运行后,会自动生成一个Podfile.lock文件,Podfile.lock文件里存储着我们已经安装的依赖库(pods)的版本。 当我们第一次运行Podfile时,如果对依赖库不指定版本的话,cocoapods会安装最新的版本,同时将pods的版本记录在Podfile.lock文件中。这个文件会保持对每个pod已安装版本的跟踪,并且锁定这些版本。

  • 2018-12-04 23:40:26

    pod删除已导入的第三方库和移除项目中的cocoapods

    CocoaPods是一个负责管理iOS项目中第三方开源库的工具。CocoaPods的项目源码在Github上管理。在我们有了CocoaPods这个工具之后,只需要将用到的第三方开源库放到一个名为Podfile的文件中,然后在命令行执行$ pod install命令。CocoaPods就会自动将这些第三方开源库的源码下载下来,并且为我的工程设置好相应的系统依赖和编译参数. 但是如果我们导入的某个第三方不适用,或者我们又不想使用该第三方,那我们又该如何将这些相关的东西从我们的项目中清理出去呢?

  • 2018-12-04 23:41:47

    制作自己的Pod库(公有/私有)

    目的:1.管理自己常用的类;2.组件化开发步骤:1.想一个比较酷的名字,在桌面简历文件夹。2.打开terminal,cd到这个文件夹下面,执行pod lib create  xxx(这里我们以JJCategoryKit为例子,下同)命令,如下图。这个过程会问几个问题,根据实际情况输入回答即可。这里我们选择添加demo,结束的时候会自动Lanuch这个app. 作者:深水日月 链接:https://www.jianshu.com/p/ece0b5721461 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 2018-12-05 06:08:26

    CocoaPods建立私有仓库 spec repo

    好多项目里都有公共的组件,copy来,copy去很容易出错,而且不容易维护,所以就想到用用cocoapods 建自己的私有库,Carthage用法虽然相对简单,但是它是把公共组件都放在framework里不容易单步调试,所以我还是选择用Cocoapods 来建立私有仓库 参考使用Cocoapods创建私有podspec

  • 2018-12-05 15:11:18

    为什么 Objective-C非常难

    作为一个Objective-C的coder,我总能听到一部 分人在这门语言上抱怨有很多问题。他们总在想快速学习这门语言来写一个App出来,但他们也总是联想到Objective-C看上去实在太难了或者在想这 些语法符号都是神马玩意?不错,他们问得非常好,所以本人也解释一下为什么很多程序员相比较学习Ruby或者Java很容易,但在决定开发iOS或者OS X应用时会那么犹豫。

  • 2018-12-05 15:22:23

    十分钟让你明白Objective-C的语法(和Java、C++的对比)

    很多想开发iOS,或者正在开发iOS的程序员以前都做过Java或者C++,当第一次看到Objective-C的代码时都会头疼,Objective-C的代码在语法上和Java, C++有着很大的区别,有的同学会感觉像是看天书一样。不过,语言都是相通的,有很多共性。下面列出Objective-C语言的语法和Java,C++的对比,这样你就会很容易Objective-C的语法是怎么回事了。