在 IntentService 中获取部分唤醒锁

Aquire partial wakelock in a IntentService

我的 IntentService 从 2 个地方被触发,通过警报或通过 Activity 并且由于持续时间与它需要从网络上获取的数据量有关,据我所知,我需要保持部分唤醒锁。

这是我的实现:

     @Override
     protected void onHandleIntent(Intent intent) {

    PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
    WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WakeLock");

    try {
         wakeLock.setReferenceCounted(false);
         wakeLock.acquire(3600000); 

          ///other code here
    }
    catch{
    }
    finally{ 
         if (wakeLock.isHeld()) {
             wakeLock.release();
         }
    }

我的问题是:这项工作是否足够好? finally 会确保唤醒锁在任何情况下都被释放吗?据我所知,onHandleIntent 一个接一个地处理意图,因此同时拥有 2 个 intents/2 唤醒锁没有风险。

稍后编辑:

IntentService 有两种调用方式:

  1. 来自我的 Activity,喜欢

    startService(new Intent(context, MyService.class).putExtra()..);

2 来自使用 PendingIntent

的触发 Alarm
 PendingIntent pendingIntent = PendingIntent.getService(context, someId, myServiceIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Alarm 运行 时,服务是否有足够的时间获取唤醒锁?

是否需要保持wake-lock应该与Service的工作量无关-理论上,即使工作量很小,设备也可以进入休眠状态。

仅当您绝对必须确保设备在 Service 为 运行 时无法休眠时,才应考虑

Wake-locks。像这样的案例非常罕见。一些例子:

  • 闹钟应用(即使设备处于休眠状态也需要唤醒您)
  • 实时消息传递应用程序(即使设备处于休眠状态也需要通知您有关新消息的信息)

大多数应用程序没有如此严格的时序要求。例如,以下不是使用唤醒锁的好理由:

  • 定期与服务器同步数据(应延迟到设备唤醒)
  • 在地图上显示当前用户的位置(可以在设备唤醒时获得;但是wake-lock将需要监控用户整个路线的应用程序)

如果您确实需要确保设备在 Service 执行期间不休眠,那么您需要获取一个 wake-lock(几种类型之一)。让我们假设这里就是这种情况。

您希望能够从应用程序的 UI (Activity) 启动 "wakeful" Service,并使用 AlarmManager.

从UI开始

由于设备应该完全唤醒以便用户与 UI 交互,您可以安全地假设如果您启动 Service 以响应 UI 交互它将有机会获得 wake-lock(但在 Service 开始后立即获得)。

您的解决方案涵盖了这种情况。

AlarmManager开始

不幸的是,无法保证(至少没有书面保证)当 AlarmManager 启动 Service 时它将持有唤醒锁并允许 Service 获取自己的唤醒锁wake-lock。这意味着设备可以在警报触发后进入睡眠状态,但在您的 Service 有机会获得 wake-lock.

之前

这意味着您的解决方案将 "break" 在这种情况下。

AlarmManager 将帮助您 wake-lock 的唯一记录方案涉及广播:

The Alarm Manager holds a CPU wake lock as long as the alarm receiver's onReceive() method is executing. This guarantees that the phone will not sleep until you have finished handling the broadcast. Once onReceive() returns, the Alarm Manager releases this wake lock. This means that the phone will in some cases sleep as soon as your onReceive() method completes. If your alarm receiver called Context.startService(), it is possible that the phone will sleep before the requested service is launched. To prevent this, your BroadcastReceiver and Service will need to implement a separate wake lock policy to ensure that the phone continues running until the service becomes available.

这就是 WakefulBroadcastReceiver 派上用场的地方。

请注意,如果您使用此方案,则无需为 "UI initiated" 情况支持不同的方案 - 在两种情况下使用相同的方法。

您可能还想看看由@CommonsWare 开发的this library(虽然我自己没有使用它)。