Частичный Wakelock Aquire в IntentService

Мой IntentService запускается из 2-х мест, либо по тревоге, либо по активности, и, поскольку длительность связана с количеством данных, которые ему нужно получить из Интернета, из того, что я понял, мне нужно сохранить частичную блокировку.

Вот моя реализация:

     @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 намерения /2 вейк-блокировки одновременно.

Позже отредактируйте:

IntentService вызывается двумя способами:

  1. из моей деятельности, как

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

2 из срабатывания Alarm используя PendingIntent

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

Будет ли у службы достаточно времени, чтобы получить wakelock, когда бежал от Alarm?

1 ответ

Решение

Нужно ли вам держать Wake-Lock или нет, не должно быть связано с объемом работы вашего Service делает - теоретически, устройство может пойти спать, даже если объем работы невелик.

Wake-Locks следует рассматривать только в том случае, если вы абсолютно уверены, что устройство не может спать, пока Service бежит. Случаи, подобные этому, очень редки. Некоторые примеры:

  • Приложения будильника (нужно разбудить вас, даже если устройство спит)
  • Приложения для обмена сообщениями в режиме реального времени (необходимо уведомлять вас о новых сообщениях, даже если устройство спит)

Большинство приложений не имеют таких строгих требований к времени. Например, следующие НЕ являются вескими причинами для использования пробужденных замков:

  • Периодическая синхронизация данных с сервером (должна быть отложена до пробуждения устройства)
  • Отображение местоположения текущего пользователя на карте (может быть получено при пробуждении устройства; но блокировка пробуждения потребуется для приложений, которые отслеживают весь маршрут пользователя)

Если вам действительно нужно убедиться, что устройство не спит во время Service выполнение, то вам нужно приобрести Wake-Lock (один из нескольких типов). Давайте предположим, что это так.

Вы хотите, чтобы иметь возможность начать "бодрствующий" Service из пользовательского интерфейса приложения (Activity) и используя AlarmManager,

Начиная с пользовательского интерфейса

Поскольку устройство должно быть полностью активным, чтобы пользователь мог взаимодействовать с пользовательским интерфейсом, можно смело предполагать, что если вы запустите Service в ответ на взаимодействие с пользовательским интерфейсом у него будет возможность получить пробуждение (но сделайте это, как только Service запущен).

Ваше решение покрывает этот случай.

Начиная сAlarmManager

К сожалению, нет гарантии (по крайней мере, нет документированной гарантии), что когда AlarmManager начинает Service он будет держать замок после Service приобрести свой собственный вейк-шлюз. Это означает, что устройство может перейти в спящий режим после срабатывания сигнализации, но до Service был шанс приобрести вейк-шлюз.

Это означает, что ваше решение "сломается" в этом случае.

Единственная документированная схема, в которой AlarmManager Вам поможет с вейк-блокировками задействует трансляции:

Диспетчер аварийных сигналов удерживает активную блокировку ЦП, пока выполняется метод onReceive () приемника аварийных сигналов. Это гарантирует, что телефон не будет спать, пока вы не закончили обработку трансляции. Как только функция onReceive () возвращается, диспетчер тревог снимает эту пробужденную блокировку. Это означает, что телефон в некоторых случаях будет спать, как только ваш метод onReceive () завершится. Если ваш приемник тревоги называется Context.startService (), возможно, что телефон будет находиться в спящем режиме до запуска запрошенной службы. Чтобы предотвратить это, вашему BroadcastReceiver и Сервису потребуется реализовать отдельную политику блокировки пробуждения, чтобы телефон продолжал работать до тех пор, пока сервис не станет доступным.

Вот где WakefulBroadcastReceiver очень удобен.

Обратите внимание, что если вы используете эту схему, то нет необходимости поддерживать другую для случая "инициированного пользовательским интерфейсом" - используйте один и тот же подход в обоих случаях.

Возможно, вы также захотите взглянуть на эту библиотеку, разработанную @CommonsWare (хотя я сам не использовал ее).

Другие вопросы по тегам