2010-06-25 5 views
13

Antecedentes:AlarmManager y BroadcastReceiver en lugar de Servicio, ¿es malo? (Tiempo de espera)

tengo que actualizar algunos datos de la web, cada hora más o menos, incluso cuando mi aplicación está cerrada. La actualización de los datos en sí tarda de 40 segundos a 1 minuto. Luego se guarda como Serializable en un archivo. Este archivo se lee cuando se inicia mi aplicación.

Este es el enfoque que di por el momento (no utilice un Servicio)

utilizar el AlarmManager y BroadcastReceiver así:

private void set_REFRESH_DATA_Alarm(){ 
    mContext = Main.this; 
    alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); 
    broadcast_intent = new Intent(mContext, 
      RepeatingAlarmReceiver_REFRESH_DATA.class); 
    pendingIntent = PendingIntent.getBroadcast(mContext, 0, broadcast_intent, 0); 
    // do a REFRESH every hour, starting for the first time in 30 minutes from now ... 
    Calendar now = Calendar.getInstance(); 
    long triggerAtTime = now.getTimeInMillis()+ (1 * 30 * 60 * 1000); // starts in 30 minutes 
    long repeat_alarm_every = (1 * 60 * 60 * 1000); // repeat every 60 minutes 
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtTime, 
      repeat_alarm_every, pendingIntent); 
} 

Mi RepeatingAlarmReceiver_REFRESH_DATA.class se encarga de la actualización los datos de la Web:

public class RepeatingAlarmReceiver_REFRESH_DATA extends BroadcastReceiver { 

    public static Context mContext; 
    ConnectivityManager mConnectivity; 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     mContext = context; 
     // if Network connection is OK (Wifi or Mobile) then Load data ... 
     mConnectivity = (ConnectivityManager) context 
       .getSystemService(Context.CONNECTIVITY_SERVICE); 
     Log.i("Hub", 
       "mConnectivity.getNetworkInfo(0)=" 
         + mConnectivity.getNetworkInfo(0)); 
     Log.i("Hub", 
       "mConnectivity.getNetworkInfo(1)=" 
         + mConnectivity.getNetworkInfo(1)); 
     if ((mConnectivity.getNetworkInfo(0).getState() == NetworkInfo.State.CONNECTED) 
       || (mConnectivity.getNetworkInfo(1).getState() == NetworkInfo.State.CONNECTED)) { 
      Log.i("Hub", "Connectivity OK ..."); 
      Refresh_HIST_DATA(); 
     } else { 
      // else Show Dialog "No network connection" ... 
      Log.i("Hub", 
        "No network connection for the moment... will try again later!"); 
     } 
    } 

    // ========================================================================= 
    private void Refresh_HIST_DATA() { 
     Log.i("Hub", "Refresh_HIST_DATA()... Starting ..."); 
     // etc... 
    } 
} 

en el manifiesto que tengo:

<receiver android:name="com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA" android:process=":remote" /> 

PROBLEMA:

La alarma se disparó en el tiempo y los de actualización se inicia pero después de unos 10 segundos que se detenga (tiempo de espera):

06-25 11: 55: 05.278: WARN/ActivityManager (76): Tiempo de espera de broadcast BroadcastRecord {44bb4348 null} - [email protected]

06-25 11: 55: 05,278: WARN/ActivityManager (76): Receptor durante timeout: ResolveInfo {44bb42c0 com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA p = 0 o = 0 m = 0x0}

06-25 11: 55: 05.278: INFO/Proceso (76): Señal de envío. PID: 819 SIG: 9

06-25 11: 55: 05,298: INFO/ActivityManager (76): Proceso com.cousinHub.myapp: remoto (pid 819) ha muerto.

ps: por extraño que parezca, este "tiempo de espera" no sucede después de unos 10 segundos en mi HTC Hero (todavía en Android 1.5 - API Nivel 4), sino también en mi Nexus One (2,1-Update1)

Preguntas:

  1. Por qué este tiempo de espera? ¿Alguna forma fácil de evitar esto?
  2. ¿Configuré mi BroadcastReceiver correctamente en el manifiesto? ¿Debo agregar algo (para evitar este tiempo de espera)?
  3. ¿Debo ir por un servicio para este tipo de funcionalidad "Actualizar desde la Web"? (teniendo en cuenta este artículo: http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) En caso afirmativo (debería cambiar a un servicio): Cualquier buen fragmento de código/tutorial para esto ...

Como siempre, gracias por su ayuda.

H.

Respuesta

18

Por qué este tiempo de espera?

Se está ejecutando en el subproceso principal de la aplicación. No se puede ejecutar en la secuencia principal de la aplicación durante más de unos pocos segundos. Además, al hacer esto, está dañando el rendimiento del dispositivo (porque es running with foreground priority), como la pérdida de velocidad de cuadro en juegos o videos.

¿Alguna manera fácil de evitar esto?

No haga un trabajo significativo (> 100ms) en la cadena principal de la aplicación. Tenga a su delegado BroadcastReceiver en un IntentService, quizás un WakefulIntentService.

¿Configuré correctamente mi BroadcastReceiver en el manifiesto?

Por favor, por favor, deshágase del android:process=:remote. No lo necesita, no lo está ayudando, y está degradando el rendimiento del dispositivo aún más.

¿Debo absolutamente ir a dar un servicio para este tipo de "Actualizar desde Web" funcionalidad? (Teniendo en cuenta este artículo : http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) Si SÍ (I debería cambiar a un servicio): Cualquier buen fragmentos de código/tutorial para este ...

en mi humilde opinión, sí. Por otra parte, escribí esa publicación en el blog. Para un ejemplo, vea el proyecto WakefulIntentService.

+0

y WakefulIntentService podrá "vivir" más de 30 segundos y actualizar todos mis datos? ¿tendrá acceso al archivo que mi aplicación leerá? – Hubert

+0

"y el WakefulIntentService podrá" vivir "más de 30 segundos y actualizar todos mis datos?" El ['IntentService'] (http://developer.android.com/reference/android/app/IntentService.html) vivirá mientras su' onHandleIntent() '(o' doWakefulWork() 'en' WakefulIntentService') está haciendo su trabajo. "¿tendrá acceso al archivo que mi aplicación leerá?" Por mucho que lo haga su 'BroadcastReceiver', presumiblemente. Tenga en cuenta que no soy usted, y por lo tanto no escribí su código, así que no tengo idea de qué es este "archivo que mi aplicación leerá". – CommonsWare

+0

Una última pregunta si puedo: ¿Cómo puedo acceder mejor al contexto de la aplicación (mContext => tal vez "Contexto mContext = (Contexto) getApplicationContext();") dentro de AppService.doWakefulWork? El objetivo es acceder a las Preferencias de mis aplicaciones con "pref = PreferenceManager.getDefaultSharedPreferences (mContext);" y mis archivos con "FileOutputStream fOut = mContext.openFileOutput (Globals.mFileName, Context.MODE_WORLD_READABLE);" – Hubert

1

Para obtener más información, he tratado con un nuevo hilo y funciona en Wi-Fi (toma alrededor de 1'30" para actualizar los datos cuando el teléfono está dormido, que no consigue 'mató'!

//let's try with a new separate thread ? 
     new Thread(new Runnable() { 
      public void run() { 
       Refresh_HIST_DATA(); 
      } 
      }).start(); 

pero no cuando el móvil (GPRS), ya que es asesinado después de unos 10 segundos!

es la mitad-a-solución por el momento y voy a intentar la solución de CommonsWare de un enfoque más limpia/más sostenible ...

Veamos si la nueva solución de hilo funciona siempre bien o solo fue suerte (I ' he probado solo durante un par de horas) ...

Si alguien más tiene otra sugerencia, por favor publíquela.

+0

la nueva solución de hilo no lo hace siempre trabaja, ¡así que evita! Vamos a buscar la solución de CommonsWare entonces. – Hubert

0

En lugar de hilo. Puede iniciar una AsyncTask desde su receptor de difusión en el método Receptor(). Esto no bloqueará el hilo de UI. Yo mismo he hecho lo mismo en mis proyectos, que es de la misma naturaleza, es decir, tiene que publicar datos cada 1 hora.

public void onReceive(Context context, Intent intent) { 
     // start your Asynctask from here. which will post data in doInBackground() method 
} 
Cuestiones relacionadas