2010-04-11 9 views
9

Ich habe eine Android-Anwendung, die den ganzen Tag sporadisch geweckt werden muss.Wie übertrage ich Daten von einem BroadcastReceiver zu einer Aktivität, die gerade gestartet wird?

Dazu verwende ich den AlarmManager, um einen PendingIntent einzurichten und einen BroadcastReceiver auszulösen. Dieser BroadcastReceiver startet dann eine Aktivität, um die Benutzeroberfläche in den Vordergrund zu bringen.

Alles oben scheint zu funktionieren, in dem die Aktivität sich korrekt startet; aber ich möchte, dass der BroadcastReceiver der Aktivität mitteilt, dass er durch den Alarm gestartet wurde (im Gegensatz zum Starten durch den Benutzer). Um dies zu tun Ich versuche, aus der OnReceive() -Methode des BroadcastReceiver eine Variable im Extra Bündel der Absicht zu setzen, also:

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

Im onResume() -Methode meiner Tätigkeit hat mich dann sucht die Existenz dieser boolean Variable:

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"); 
} 

die getIntent() getExtras() -Aufruf in onResume() immer null zurück - ich scheine nicht in der Lage sein, alle Extras passieren überhaupt durch in diesem. bündeln.

Wenn ich die gleiche Methode verwende, um Extras an den PendingIntent zu binden, der den BroadcastReceiver auslöst, kommen die Extras jedoch gut durch.

Kann mir jemand sagen, was anders ist, wenn ein Bündel von einem BroadcastReceiver an eine Aktivität übergeben wird, statt das Bündel von einer Aktivität an einen BroadcastReceiver zu übergeben? Ich fürchte, ich könnte etwas sehr, sehr offensichtlich falsch hier tun ...

+0

Neugieriger und neugieriger ... es begann gerade arbeiten (im Emulator), genau so, wie ich erwarten würde . Arbeitete wiederholt für ein bisschen. Ich habe den Emulator heruntergefahren, neu gestartet (ohne Codeänderungen oder Neukompilierung) und bin wieder beim alten Verhalten angelangt (Aktivität wird gestartet, aber kein Bundle wurde übergeben). Ich kann Protokolle für beide Läufe immer noch sehen - in der ersten, Bundles kommen durch, in letzterem nicht. –

Antwort

30

Just (nicht mit anderen Flaggen mischen), um deutlich zu machen (weil ich viel Zeit verwendet, herauszufinden, wie es funktioniert)

In die Serviceklasse, die BroadcastReceiver erweitert. Setzen Sie in dem folgenden Code in 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); 

Die FLAG_ACTIVITY_SINGLE_TOP stellt sicher, dass die Anwendungen nicht nicht offen wieder, wenn bereits geöffnet. Dies bedeutet, dass die "alte" Absicht, die YourActivity an erster Stelle geöffnet hat, wiederverwendet wird und KEINE zusätzlichen Werte enthält. Sie haben sie in einem anderen Verfahren onNewIntent() in 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 

Bitte beachten Sie die beiden if-Anweisungen genannt zu fangen - das onResume() weiß nicht, ob es heißt nach OnCreate()->OnStart() OR onRestart()->onStart()
Bitte sehen:http://www.anddev.org/images/android/activity_lifecycle.png

Es ist nur Wird verwendet, um zu testen, ob die App vom Benutzer gestartet wurde (Absicht ohne Extras) ODER über die BroadcastReceiver (Absicht mit Extras).

+0

aber stl ich habe das gleiche Problem? ..my Aktivität immer wieder neu starten..have irgendein anderes Update? – CoDe

+1

Das hört sich vielleicht dumm an: Aber haben Sie überprüft, ob Sie die richtige Flagge gesetzt haben und die Beschreibung zu jedem Punkt befolgt haben?Ich habe lange gebraucht, um das herauszufinden, und mir wurde klar, dass nicht alle Flaggen so funktionieren, wie ich es von ihnen erwarte. Wenn Sie mehr Flags als beschrieben hinzufügen, versuchen Sie, sie zu entfernen. Machen Sie das und fügen Sie sie einzeln hinzu, um zu sehen, was passiert. – Norfeldt

+1

Was ist "opstartsIntent" Ich kann das nicht finden/kompilieren. – MrHIDEn

2

Anstelle von getIntent().getExtras().getBoolean(wakeupKey) ist es konventioneller zu schreiben getIntent().getBooleanExtra(wakeupKey, defaultValue). Ich kann nicht sicher sein, ob dies mit deinem Problem zusammenhängt, aber es gibt ein paar Dinge, die mit dem Erstellen eines Bundles in getExtras() zu tun haben, über das ich nicht sicher bin, also könnte es sich sowieso lohnen.

+0

Danke Jim. Ich habe gerade versucht, diese Änderung vorzunehmen, aber der Wert ist immer falsch (und ich setze ihn immer nur auf "True"). –

5

Diese BroadcastReceiver dann startet eine Aktivität der Benutzeroberfläche zum Vordergrund zu bringen.

Dies könnte der Kern Ihres Problems hier sein. Versuchen Sie, onNewIntent() zu überschreiben und zu sehen, ob das Intent daran weitergegeben hat Ihr Extra. Wenn ja, liegt das an der Art und Weise, wie Sie die Aktivität im Manifest einrichten (z. B. verwenden Sie singleTop), und an der Tatsache, dass die Aktivität in diesem speziellen Fall bereits vorhanden war.

Sie könnten auch in Betracht ziehen, i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); loszuwerden und sehen, ob das Änderungen von Bedeutung ist.

Das Ergebnis ist, dass das, was Sie tun - die Zugabe in die Intent für startActivity() - sollte gut funktionieren. In der Tat können Sie Beispiele davon sehen here. Dies legt nahe, dass es etwas Ungewöhnliches an der Aktivität (z. B. singleTop) oder der Art, wie Sie die Aktivität aufrufen (z. B. FLAG_ACTIVITY_NEW_TASK), ist.

EDIT:

Seit meinem ersten Schüsse nicht funktioniert hat, und Ihr „neugieriger“ Kommentar oben gegeben ...

Das fühlt sich ein bisschen wie ein PendingIntent - mit denen, wenn Sie machen Sie Schritte, Sie können keine Extras aktualisieren.

Versuchen Sie aus Versehen, Ihrer Aktivität im Manifest eine zweite <intent-filter> hinzuzufügen, nur eine eindeutige Aktionszeichenfolge, und versuchen Sie, Ihre Aktivität von Ihrem Empfänger aus zu starten. Oder werfen Sie einfach einen Aktions-String in Ihren Intent, den der Empfänger für startActivity() verwendet, ohne mit dem Manifest zu verfahren.

+0

Nö, onNewIntent() gibt es auch nicht bekommen ... Die FLAG_ACTIVITY_NEW_TASK gibt es, weil ohne sie ich eine Runtime erhalten: E/Android Runtime (274): java.lang.RuntimeException: Kann nicht starten Empfänger com. futureplatforms.twitchr.BirdArrivesAlarmReceiver: android.util.AndroidRuntimeException: Der Aufruf von startActivity() von außerhalb eines Aktivitätskontexts erfordert das Flag FLAG_ACTIVITY_NEW_TASK. Ist das wirklich was du willst? –

+0

Ich bearbeitete meine frühere Antwort mit anderen Dingen, die Sie versuchen können - kommentieren hier für den Fall, dass Sie nicht auf eine Antwort benachrichtigt werden bearbeiten ... – CommonsWare

+1

OK, erneut versucht. onNewIntent() bekommt es jetzt - ich habe den launchmode der Aktivität in singleTask geändert, und es funktioniert genau so, wie ich es mir erhofft hatte. Ich überschreibe dann newIntent und setze eine Variable, die die Aktivität an anderer Stelle aufnehmen könnte, um festzustellen, dass sie durch einen Alarm geweckt wurde. Vielen Dank! –

1

Set Flagge SingleTop Werke

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

einfach die onNewIntent wie dies außer Kraft setzen und das Bundle var wird in der onResume Methode zur Verfügung:

@Override 
protected void onNewIntent(Intent intent) { 
    super.onNewIntent(intent); 
    setIntent(intent); 
} 
Verwandte Themen