Aquire partial wakelock in a IntentService

谁都会走 提交于 2019-12-20 07:37:51

问题


My IntentService gets fired from 2 places, either by an Alarm or by the Activity and since the duration is related to the amount of data it needs do fetch from the web, from what I understood, I need to keep a partial wakelock.

Here's my implementation:

     @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();
         }
    }

My question is: will this work good enough? Will the finally make sure that the wakelock is released in any circumstances? From what I know onHandleIntent handles intent one after another, so there is no risk in having 2 intents/2 wakelocks in the same time.

Later edit:

The IntentService is called in 2 ways:

  1. from my Activity, like

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

2 from a triggered Alarm using a PendingIntent

 PendingIntent pendingIntent = PendingIntent.getService(context, someId, myServiceIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Will the service have enough time to aquire wakelock when ran from the Alarm?


回答1:


Whether you need to keep wake-lock or not should not be related to the amount of work your Service does - theoretically, device can go to sleep even if the amount of work is small.

Wake-locks should be considered only if you absolutely must ensure that device can't sleep while the Service is running. Cases like this are very rare. Some examples:

  • Alarm clock applications (need to wake you up even if the device is sleeping)
  • Real time messaging applications (need to notify you about new messages even if the device is sleeping)

Most applications don't have such a strict timing requirements. For example, the following are NOT good reasons to use wake locks:

  • Periodic synchronization of data with the server (should be delayed until device awakes)
  • Displaying current user's location on map (can be obtained when device awakens; but wake-lock will be needed for applications that monitor user's entire route)

If you really need to ensure that the device doesn't sleep during Service execution, then you need to acquire a wake-lock (one of the several types). Let's assume that this is the case here.

You want to be able to start the "wakeful" Service from application's UI (Activity), and using AlarmManager.

Starting from UI

Since the device should be completely awake in order for the user to interact with UI, you can safely assume that if you start the Service in response to UI interaction it will have a chance to acquire a wake-lock (but do it as soon as the Service is started).

Your solution covers this case.

Starting from AlarmManager

Unfortunately, there is no guarantee (at least no documented guarantee) that when AlarmManager starts the Service it will hold a wake lock and allow the Service to acquire its own wake-lock. This means that the device can go to sleep after alarm fired, but before your Service had a chance to acquire the wake-lock.

This means that your solution will "break" in this case.

The only documented scheme in which AlarmManager will help you with wake-locks involves broadcasts:

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.

This is where WakefulBroadcastReceiver comes in very handy.

Note that if you use this scheme, then there is no need to support a different one for "UI initiated" case - use the same approach in both cases.

You might also want to take a look at this library developed by @CommonsWare (I didn't use it myself though).



来源:https://stackoverflow.com/questions/41953458/aquire-partial-wakelock-in-a-intentservice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!