正确的模式,以获取BroadcastReceiver中的WakeLock并在服务中释放它

Tor*_*mer 19 service android broadcastreceiver wakelock

即使经过大量的研究,我仍然不能完全确定我是如何实现WakeLock一个Service开始的方式BroadcastReceiver是正确的 - 即使它似乎工作正常.广播接收器从警报中获取发送给它的意图,所以首先从API文档开始AlarmManager:

如果您的警报接收器调用了Context.startService(),则手机可能会在启动所请求的服务之前休眠.为了防止这种情况,您的BroadcastReceiver和服务需要实施单独的唤醒锁定策略,以确保电话继续运行,直到服务可用.

所以,在onReceive()我做:

    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();
    }
Run Code Online (Sandbox Code Playgroud)

在我做的服务中:

    try {
        // Do some work
    } finally {
        if(wakeLock != null) {
            if(wakeLock.isHeld()) {
                wakeLock.release();
            }
            wakeLock = null;
        }
    }
Run Code Online (Sandbox Code Playgroud)

SomeService.wakeLock字段是包私有,静态和易失性.

我不确定的是检查使用isHeld()- 是否真的告诉我是否WakeLock获得了,我是否需要进行检查?

Squ*_*onk 4

我不确定的是检查使用isHeld()- 它真的告诉我 aWakeLock是否被获取,以及我是否需要进行此检查?

其实回答起来有点棘手。PowerManager查看和的来源,PowerManager.WakeLock 这里的和方法如下......WakeLock.acquire()WakeLock.acquireLocked()

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

...mService是一个IPowerManager接口,并且它的源不可用,因此很难判断在尝试调用acquireWakeLock(...).

无论如何,唯一可以捕获的异常是RemoteExceptioncatch块不执行任何操作。无论如何,在 try/catch 之后立即mHeld设置true

简而言之,如果您isHeld()立即调用,acquire()结果将始终是true.

进一步查看源代码PowerManager.WakeLock显示了类似的行为,无论发生什么release()情况release(int flags),调用mHeld成员总是设置为false

总之,我建议检查一下始终是一个好主意,isHeld()作为最佳实践,以防更高版本的 Android 更改WakeLock方法的这种行为。