Android: el servicio no activa el dispositivo como debería


Mi aplicación realiza una solicitud repetitiva cada segundo: pide al servidor nuevos datos y, si los hay, activa el dispositivo y ejecuta la aplicación principal. (esto es por solicitud de los usuarios, y no les importa el uso de la batería, es obligatorio ejecutar cada segundo. Es una operación altamente crítica) (cualquier cambio en la configuración que pueda ayudar está permitido por el usuario)

Actualmente intento lograr esto usando AlarmManager o System.Threading.Timer (intenté con ambos), pero cada vez termino con el siguiente problema:

  • El dispositivo deja de solicitar el servidor en algún momento mientras está inactivo y en algún momento aparentemente aleatorio restaura su funcionamiento por un breve período. ¿Por qué sucede esto y cómo solucionar este problema?

( SO : Android 5.x )

El código de la variación del servicio en Java (usando AlarmManager)

Calendar cal = Calendar.getInstance();
        cal.add( Calendar.SECOND, ConfigReader.serviceRepeatInterval );

        Intent intent = new Intent( this, SaleService.class );

        PendingIntent pintent = PendingIntent.getService( this, 0, intent, 0 );

        AlarmManager alarm = ( AlarmManager )getSystemService( Context.ALARM_SERVICE );

        alarm.setRepeating( AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), ConfigReader.serviceRepeatInterval, pintent );

El código de la variación del servicio es C# (Xamarin) usando Timer.

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
        {

            if( _powerManager == null )
            {
                 _powerManager = (PowerManager)this.GetSystemService(PowerService);
                _wakeLock      = _powerManager.NewWakeLock( WakeLockFlags.Full | WakeLockFlags.AcquireCausesWakeup | WakeLockFlags.OnAfterRelease, mySaleServiceWakeLock );
                 vibrator      = (Vibrator)this.GetSystemService( Context.VibratorService );                
            }

            timer = new System.Threading.Timer( getCurrentPendingObjects, null, timerRepeatInterval, Timeout.Infinite );

            return StartCommandResult.Sticky;
        }


------------Respuesta------------

Usar AlarmManager.ELAPSED_REALTIME_WAKEUP o AlarmManager.RTC_WAKEUP activará el dispositivo cuando se dispare la alarma.

El dispositivo deja de solicitar el servidor en algún momento mientras está inactivo y en algún momento aparentemente aleatorio restaura su trabajo por un corto tiempo. ¿Por qué sucede esto y cómo solucionar este problema?

Esto podría suceder porque su PendingIntent está llamando a un servicio. De esta manera el dispositivopuede volver a dormir antes de que se ejecute onStartCommand(). En su lugar, debe usar un BroadcastReceiver (ya que un WakeLock está "garantizado" durante onReceive()), adquiera un WakeLock en onReceive(), inicie su Servicio desde allí y libere su WakeLock del Servicio, cuando corresponda.

Aunque, repetir una solicitud cada segundo durante un período de tiempo prolongado (e incluso cuando el dispositivo está inactivo) parece un diseño terrible. Agotará la batería bastante rápido.

Deberías repensarsu implementación, tal vez use algún tipo de mecanismo de devolución de llamada, o al menos aumente los intervalos entre las solicitudes (significativamente).

Etiquetas: android-5.0-lollipop xamarin.android xamarin android

Artículos relacionados:

css: la animación no funciona en Chrome

ios - ¿Cómo se puede probar el SDK de LinkedIn en el simulador?