2013-09-15 5 views
2

Я использую AlarmManager для отправки широковещательной передачи, когда экран выключен. Это отлично работает на большинстве устройств, но на некоторых (например, Samsung Galaxy S4) требуется 30, 40 или даже 120 секунд вместо указанных 20 секунд до тех пор, пока передача не будет получена. У меня нет доступа к устройствам, на которых это происходит, поэтому я не могу проверить logcat.Несоответствие AlarmManager

Это, как я устанавливаю вверх AlarmManager:

AlarmManager mAlarmManager=(AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); 
long mInterval = 20 * 1000; 
Intent i = new Intent(); 
i.setAction(MY_ACTION); 
mPendingIntent = PendingIntent.getBroadcast(mContext, 0, i, PendingIntent.FLAG_UPDATE_CURRENT); 
mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + mInterval, mPendingIntent); 

И это приемник, зарегистрированный в манифесте:

private class MyIntentReceiver extends BroadcastReceiver { 

    private static final String TAG = "MyIntentReceiver"; 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     if (intent.getAction().equals(MY_ACTION)) { 

      PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 
      PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, ""); 
      wl.acquire(); 

      Log.e(TAG, "onReceive"); 

      //Carry out my action... 


      wl.release(); 

     } 
    } 

} 
+0

Два вопроса: вы не должны тратить больше, чем на пару миллисекунд в 'onReceive()', и уже есть 'WakeLock', когда вы находитесь в' onReceive() '. Вам нужен ваш собственный «WakeLock», если вы передаете управление другому компоненту (например, «// Выполняем мое действие», действительно делегируем «IntentService»), хотя затем освобождение 'WakeLock', где вы находитесь, неверно. Если вы делегируете другой компонент, используйте [my 'WakefulIntentService' (https://github.com/commonsguy/cwac-wakeful) или пакет поддержки Android WakebackBroadcastReceiver. – CommonsWare

+0

Спасибо, Марк. Я изменил свой код на конструкцию WakefulBroadcastReceiver/IntentService, но несогласованность на S4 все еще существует (она работает на других устройствах, как и раньше). Если я увеличиваю интервал (например, 30 или 40 секунд вместо 20), несогласованность увеличивается экспоненциально (т. Е. На 1-2 минуты дольше, чем предполагалось до тех пор, пока не будет выполнено мое действие). Я в шоке от этого, потому что я думал, что использование «RTC_WAKEUP» гарантирует, что фактическое время будет использоваться, а не только «устройство пробуждено» - время? – Nick

+0

Это должно быть. Если вы можете создать воспроизводимый тестовый пример, загрузите его где-нибудь, и я загляну к нему. У меня есть S4, хотя он может быть не такой же S4-модель, как у вас (Samsung применил «S4» к нескольким устройствам). Или попробуйте [этот образец «WakefulIntentService»] (https://github.com/commonsguy/cw-omnibus/tree/master/AlarmManager/Wakeful) или [этот образец «WakefulBroadcastReceiver»] (https://github.com/ commonsguy/cw-omnibus/tree/master/AlarmManager/WakeCast) и попробуйте воспроизвести свои симптомы на основе одного из них. – CommonsWare

ответ

0

Я изменил параметры метода AlarmManager.set() в AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() вместо моего начального AlarmManager.RTC_WAKEUP, System.currentTimeMillis() на основе CommonsWare's sample, и теперь он работает и на S4. Я не знаю, почему ELAPSED_REALTIME_WAKEUP не работает, так как он конкретно несет WAKEUP от своего имени и работает на всех других устройствах, на которых я его тестировал.

0

Поведение AlarmManager изменен с прибытием API 19. Многие потратили впустую часы на устранение неполадок приложения, которое раньше отлично работало, прежде чем читать обновленный Javadoc.

Примечание: Начиная с API 19 (KITKAT) доставки сигнала неточна: операционная система будет смещаться сигналы для того, чтобы свести к минимуму пробуждений и использование батареи. Существуют новые API-интерфейсы для поддержки приложений, требующих строгих гарантий доставки; см. setWindow(int, long, long, PendingIntent) и setExact(int, long, PendingIntent). Приложения, чьи targetSdkVersion являются более ранними, чем API 19, будут продолжать видеть предыдущее поведение, при котором все аварийные сигналы доставляются точно по запросу.