我的IntentService从两个地方被触发,无论是通过警报还是通过活动,由于持续时间与它需要从网络获取的数据量有关,根据我的理解,我需要保持部分唤醒锁定。
这是我的实现:
@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个唤醒锁没有风险。
后期编辑:
IntentService有两种调用方式:
来自我的活动,如
startService(new Intent(context, MyService.class).putExtra()..);
2来自使用PendingIntent 触发的Alarm
PendingIntent pendingIntent = PendingIntent.getService(context, someId, myServiceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
当从Alarm
运行时,服务是否有足够的时间获取唤醒锁定?
是否需要保持唤醒锁定与Service
的工作量无关——理论上,即使工作量很小,设备也可以进入睡眠状态。
只有当您绝对必须确保设备在Service
运行时无法休眠时,才应考虑唤醒锁定。像这样的病例非常罕见。一些例子:
- 闹钟应用程序(即使设备处于睡眠状态也需要唤醒您)
- 实时消息应用程序(即使设备处于睡眠状态,也需要通知您新消息)
大多数应用程序都没有如此严格的时间要求。例如,以下不是使用唤醒锁的好理由:
- 定期与服务器同步数据(应延迟到设备唤醒)
- 在地图上显示当前用户的位置(可以在设备唤醒时获得;但监控用户整个路线的应用程序需要唤醒锁定)
如果您确实需要确保设备在Service
执行期间不会休眠,那么您需要获取唤醒锁(几种类型之一)。让我们假设这里就是这样。
您希望能够从应用程序的UI(Activity
)启动"唤醒"Service
,并使用AlarmManager
。
从UI开始
由于设备应该是完全唤醒的,以便用户与UI交互,您可以放心地假设,如果您启动Service
以响应UI交互,它将有机会获得唤醒锁定(但在Service
启动后立即执行)。
您的解决方案涵盖了这种情况。
从AlarmManager
开始
不幸的是,当AlarmManager
启动Service
时,无法保证(至少没有书面保证)它将保持唤醒锁并允许Service
获取自己的唤醒锁。这意味着设备可以在警报响起后进入睡眠状态,但在您的Service
有机会获得唤醒锁定之前。
这意味着在这种情况下,您的解决方案将"中断"。
AlarmManager
将帮助您进行唤醒锁定的唯一记录方案涉及广播:
报警管理器在报警时保持CPU唤醒锁定receiver的onReceive()方法正在执行。这保证了在您处理完广播之前,手机不会休眠。一旦onReceive()返回,报警管理器就会释放此唤醒锁。这意味着在某些情况下,手机会在onReceive()方法完成。如果你的闹钟响了Context.startService(),手机可能会休眠在启动所请求的服务之前。为了防止这种情况BroadcastReceiver和Service将需要实现单独的唤醒锁定策略,以确保手机继续运行,直到服务可用。
这就是WakefulBroadcastReceiver非常方便的地方。
请注意,如果使用此方案,则不需要为"UI启动"情况支持不同的方案——在这两种情况下使用相同的方法。
你可能还想看看这个由@CommonsWare开发的库(不过我自己没有用过)。