2010-04-11 10 views
9

Tengo una aplicación de Android que necesita ser activada esporádicamente durante el día.¿Cómo paso los datos de un BroadcastReceiver a una actividad que se inicia?

Para hacer esto, estoy usando el AlarmManager para configurar un PendingIntent y hacer que active un BroadcastReceiver. Este BroadcastReceiver luego inicia una Actividad para llevar la IU al primer plano.

Todo lo anterior parece funcionar, ya que la actividad se inicia correctamente; pero me gustaría que el BroadcastReceiver notifique a la Actividad que fue iniciada por la alarma (en lugar de ser iniciada por el usuario). Para hacer esto que estoy tratando, a partir del método OnReceive() de la BroadcastReceiver para establecer una variable en el paquete de extras de la intención, por lo tanto:

Intent i = new Intent(context, MyActivity.class); 
    i.putExtra(wakeupKey, true); 
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    context.startActivity(i); 

En el onResume() de mi actividad, que luego buscar la existencia de esta variable booleana:

protected void onResume() { 
    super.onResume(); 

    String wakeupKey = "blah";  
    if (getIntent()!=null && getIntent().getExtras()!=null) 
     Log.d("app", "onResume at " + System.currentTimeMillis() + ":" + getIntent().getExtras().getBoolean(wakeupKey)); 
    else 
     Log.d("app", "onResume at " + System.currentTimeMillis() + ": null"); 
} 

la llamada getIntent() getExtras() en onResume() siempre devuelve null - yo no parecen ser capaces de pasar a través de cualquier accesorio para nada en esto. haz.

Si utilizo el mismo método para vincular extras al PendingIntent que desencadena el BroadcastReceiver, sin embargo, los extras vienen bien.

¿Alguien puede decirme qué tiene de diferente pasar un paquete de un BroadcastReceiver a una actividad, en lugar de pasar el paquete de una actividad a un BroadcastReceiver? Me temo que puedo estar haciendo algo muy, muy obvio mal aquí ...

+0

curioso y más curioso ... que acaba de comenzar a trabajar (en el emulador), exactamente como yo esperaría . Trabajó repetidamente por un tiempo. Apagué el emulador, reinicié (sin ningún cambio de código ni recompilación) y volví al comportamiento anterior (la actividad se inicia pero no se transfiere ningún paquete). Aún puedo ver los registros de ambas ejecuciones; en el primero, los paquetes están llegando, en el último caso no. –

Respuesta

30

Sólo para que quede claro (porque he usado mucho tiempo encontrar la manera de hacer que funcione)

En la clase de servicio que se extiende BroadcastReceiver. Poner en el código siguiente en onReceive()

Intent intent2open = new Intent(context, YourActivity.class); 
intent2open.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
intent2open.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 
String name = "KEY"; 
String value = "String you want to pass"; 
intent2open.putExtra(name, value); 
context.startActivity(intent2open); 

El FLAG_ACTIVITY_SINGLE_TOP asegura las aplicaciones no volver a abrir si ya está abierta. Esto significa que el "viejo" intento que abrió YourActivity en primer lugar se reutiliza y NO contendrá los valores adicionales. Tienes que atraparlos en otro método llamado onNewIntent() en YourActivity.

public class YourActivity extends Activity { 
    private String memberFieldString; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     // Code doing your thing... 
    } // End of onCreate() 

    @Override 
    protected void onNewIntent(Intent intent) { 
    Log.d("YourActivity", "onNewIntent is called!"); 

    memberFieldString = intent.getStringExtra("KEY"); 

    super.onNewIntent(intent); 
} // End of onNewIntent(Intent intent) 

    @Override 
    protected void onResume() { 
     if (memberFieldString != null) { 
      if (opstartsIntent.getStringExtra(KEY) != null) { 
       Log.d("YourActivity", "memberFieldString: "+ memberFieldString); 
      } else { 
       Log.d("YourActivity", "The intent that started YourActivity did not have an extra string value"); 
      } 
     } 
    } // End of onResume() 

} // End of YourActivity 

Tenga en cuenta que los dos sentencias if - la onResume() no sabe si se llama después de OnCreate()->OnStart() OR onRestart()->onStart()
favor ver:http://www.anddev.org/images/android/activity_lifecycle.png

Es sólo usado para probar si la aplicación fue lanzada por el usuario (intento sin extras) O por el BroadcastReceiver (intento con extras).

+0

pero stl estoy enfrentando el mismo problema? ... mi actividad comienza una y otra vez ... ¿tengo alguna otra actualización? – CoDe

+1

Esto puede sonar estúpido: ¿Pero ha comprobado si ha establecido la bandera correcta y seguido la descripción en cada punto?Me llevó mucho tiempo resolver esto y me di cuenta de que no todas las banderas funcionaban como esperaba que lo hicieran. Si agrega más banderas que las que se describen, intente eliminarlas. Haz que funcione y luego agrégalos uno por uno para ver qué pasa. – Norfeldt

+1

¿Qué es "optartsIntent"? No puedo encontrar/compilar eso. – MrHIDEn

2

En lugar de getIntent().getExtras().getBoolean(wakeupKey) es más convencional escribir getIntent().getBooleanExtra(wakeupKey, defaultValue). No puedo estar seguro de si esto está relacionado con su problema, pero hay algunas cosas que hacer con la creación de un paquete dentro de getExtras() que no estoy seguro, por lo que podría valer la pena ir de todos modos.

+0

Gracias Jim. Solo intenté hacer ese cambio, pero el valor siempre es falso (y solo lo configuro en verdadero). –

5

Este BroadcastReceiver continuación, pone en marcha un Actividad para llevar la interfaz de usuario para la primer plano.

Esto puede ser la clave de su problema aquí. Intente anular onNewIntent() y vea si el Intent que se le transfirió tiene su extra. Si es así, eso se debe a la forma en que configuras la actividad en el manifiesto (por ejemplo, estás usando singleTop) y al hecho de que, en este caso específico, la actividad ya existía.

También puede considerar deshacerse de i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); y ver si eso cambia las cosas.

El resultado es que lo que está haciendo - poner el extra en el Intent para startActivity() - debería funcionar bien. De hecho, puedes ver ejemplos de eso here. Esto sugiere que es algo funky sobre la actividad (por ejemplo, singleTop) o la forma en que invoca la actividad (por ejemplo, FLAG_ACTIVITY_NEW_TASK).

EDIT:

Desde mis primeros disparos no funcionaron, y dada su "curioso" comentario anterior ...

Esto se siente un poco como un PendingIntent - con los que, a menos que toma medidas, no podrás actualizar extras.

Por un capricho, intente agregar un segundo <intent-filter> a su actividad en el manifiesto, solo en alguna cadena de acción única, e intente iniciar su actividad desde su receptor usando eso. O bien, simplemente arroje una cadena de acción en su Intent que el receptor está utilizando para startActivity(), sin interferir con el manifiesto.

+0

No, onNewIntent() no lo entiende bien ... El FLAG_ACTIVITY_NEW_TASK está ahí porque sin ella consigo un RuntimeException: E/Android Runtime (274): java.lang.RuntimeException: No se puede iniciar el receptor com. futureplatforms.twitchr.BirdArrivesAlarmReceiver: android.util.AndroidRuntimeException: la llamada a startActivity() desde fuera del contexto de una actividad requiere el indicador FLAG_ACTIVITY_NEW_TASK. ¿Es esto realmente lo que quieres? –

+0

He editado mi respuesta anterior con otras cosas que puedes probar, comentando aquí en caso de que no te notifiquen en una edición de respuesta ... – CommonsWare

+1

OK, vuelve a intentarlo. onNewIntent() lo consigue ahora - Cambié el modo de inicio de la actividad a singleTask, y está funcionando exactamente como esperaba. Luego reemplacé el nuevoIntent y establecí una variable que la actividad podría detectar en otro lugar para determinar que había sido despertado por una alarma. ¡Gracias! –

1
bandera

Conjunto SingleTop obras (no mezclar con otras banderas)

Intent intent = new Intent(ContextManager.getContext(),OrderList.class); 
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 
Bundle bundle = new Bundle();  

bundle.putString("username",username); 
bundle.putString("password",password); 

intent.putExtras(bundle); 
startActivityForResult(intent,0); 
0

Así anulan la onNewIntent como este y la var paquete estará disponible en el método onResume:

@Override 
protected void onNewIntent(Intent intent) { 
    super.onNewIntent(intent); 
    setIntent(intent); 
} 
Cuestiones relacionadas