问题描述
即使经过了大量的研究,我还没有完全确定,如果我如何实现方式 WakeLock
为服务
开始由的BroadcastReceiver
是正确的 - 尽管它似乎很好地工作。广播接收器会从警报发送给它的,所以下手意图,从API文档 AlarmManager
:
所以,在的onReceive()
我做的:
意图serviceIntent =新的意图(背景下,SomeService.class);
context.startService(serviceIntent);
如果(SomeService.wakeLock == NULL){
电源管理器电源管理器=(电源管理器)context.getSystemService(Context.POWER_SERVICE);
SomeService.wakeLock = powerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
SomeService.WAKE_LOCK_TAG);
}
如果(!SomeService.wakeLock.isHeld()){
SomeService.wakeLock.acquire();
}
在我做的服务:
尝试{
//做一些工作
} 最后 {
如果(wakeLock!= NULL){
如果(wakeLock.isHeld()){
wakeLock.release();
}
wakeLock = NULL;
}
}
在 SomeService.wakeLock
字段是包私有,静态震荡。
我不能确定的是使用支票 isHeld()
- 它真的告诉我,如果一个 WakeLock
被收购与否,做我需要做这个检查呢?
其实有点难回答。纵观源电源管理器
和 PowerManager.WakeLock
这里的 WakeLock.acquire()
和 WakeLock.acquireLocked()
方法如下所示...
公共无效的获取(长期超时){
同步(mToken){
acquireLocked();
mHandler.postDelayed(mReleaser,超时);
}
}
私人无效acquireLocked(){
如果(!mRefCounted || mCount ++ == 0){
//做到这一点,即使唤醒锁已被认为是举行(mHeld ==真)
//因为非引用计数的唤醒锁并不总是正确释放。
//例如,键盘锁的苏醒锁定可能被强制地由释放
//不知道键盘保护电源管理器。随后调用收购
//应立即尽管永远不必再次购买之后锁
//被明确释放了键盘锁。
mHandler.removeCallbacks(mReleaser);
尝试 {
mService.acquireWakeLock(mToken,mFlags,MTAG,mWorkSource);
}赶上(RemoteException的E){
}
mHeld = TRUE;
}
}
... MSERVICE
是 IPowerManager
接口和源,因为这是不可用,所以很难告诉什么可以或试图打电话的时候,可能不会出错 acquireWakeLock(...)
。
在任何情况下,可以被捕获的唯一的例外是的RemoteException
和抓
块什么都不做。紧随try / catch语句之后, mHeld
设置真
不管。
总之,如果你调用 isHeld()
后立即获取()
的结果总是真
。
展望更远的进入源 PowerManager.WakeLock
显示了类似的行为发布()
这就要求发布(INT标志)
其中 mHeld
成员始终设置为假
不管发生什么事。
在最后,我会建议它始终是一个好主意,检查 isHeld()
一样的情况下后面的变化的Android版本的这种行为,最好的做法 WakeLock
的方法。
Even after a lot of research I am still not completely sure if the way how I implement a WakeLock
for a Service
started by a BroadcastReceiver
is correct - even though it seems to work fine. The broadcast receiver gets intents sent to it from an alarm, so to start with, from the API docs of AlarmManager
:
So, in onReceive()
I do:
Intent serviceIntent = new Intent(context, SomeService.class);
context.startService(serviceIntent);
if(SomeService.wakeLock == null) {
PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
SomeService.wakeLock = powerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
SomeService.WAKE_LOCK_TAG);
}
if(! SomeService.wakeLock.isHeld()) {
SomeService.wakeLock.acquire();
}
and in the service I do:
try {
// Do some work
} finally {
if(wakeLock != null) {
if(wakeLock.isHeld()) {
wakeLock.release();
}
wakeLock = null;
}
}
The SomeService.wakeLock
field is package private, static and volatile.
What I am unsure about is the check using isHeld()
- does it really tell me if a WakeLock
is acquired or not, and do I need to do this check at all?
Actually slightly tricky to answer. Looking at the source for PowerManager
and PowerManager.WakeLock
here the WakeLock.acquire()
and WakeLock.acquireLocked()
methods are as follows...
public void acquire(long timeout) {
synchronized (mToken) {
acquireLocked();
mHandler.postDelayed(mReleaser, timeout);
}
}
private void acquireLocked() {
if (!mRefCounted || mCount++ == 0) {
// Do this even if the wake lock is already thought to be held (mHeld == true)
// because non-reference counted wake locks are not always properly released.
// For example, the keyguard's wake lock might be forcibly released by the
// power manager without the keyguard knowing. A subsequent call to acquire
// should immediately acquire the wake lock once again despite never having
// been explicitly released by the keyguard.
mHandler.removeCallbacks(mReleaser);
try {
mService.acquireWakeLock(mToken, mFlags, mTag, mWorkSource);
} catch (RemoteException e) {
}
mHeld = true;
}
}
...mService
is an IPowerManager
interface and the source for it isn't available so it's hard to tell what may or may not go wrong when attempting to call acquireWakeLock(...)
.
In any case, the only exception that can be caught is RemoteException
and the catch
block does nothing. Immediately after the try/catch, mHeld
is set true
regardless.
In short, if you call isHeld()
immediately after acquire()
the result will always be true
.
Looking further into the source for PowerManager.WakeLock
shows similar behaviour for release()
which calls release(int flags)
where the mHeld
member is always set to false
regardless of what happens.
In conclusion I'd suggest it is always a good idea to check isHeld()
just as a best practice in case later versions of Android change this behaviour of the WakeLock
methods.
这篇关于正确的方式来获取WakeLock在一个BroadcastReceiver和服务将其释放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!