Activity starten mit Sonderwünschen

  • 13 Antworten
  • Letztes Antwortdatum
Micka

Micka

Fortgeschrittenes Mitglied
1
Hallo,

ich stehe derzeit vor einem Problem im Bezug auf das starten einer Activity.

Mein Projekt ist relativ umfangreich und arbeitet mit einem Arduino Mega und einer CouchDB. Ich versuche mal die relevanten Dinge zu erklären ohne das Ganze Projekt in aller Ausführlichkeit zu beschreiben.

Das Projekt besitzt 2 Activity's(Activity1 und Activity2). In der einen(Activity1) sind die Buttons und ein paar Textfelder. Wird Button1 betätigt startet ein Thread ruft übers Netzwerk Sensordaten ab und packt diese in die CouchDB. Das funktioniert auch alles.
Ich möchte die Daten aber nicht nur in die Datenbank lagern sondern bei Bedarf nach Betätigung des Button2 eine weitere Activity(Activity2) aufrufen.
Bishierhin alles kein Problem.

Das Problem besteht darin, dass ich von der Actvity1 auf eine Funktion der Activity2 zugreifen will. Genauer gesagt auf die Funktion die dem Graphen Punkte hinzufügt.

Nun dachte ich mir ich versuchs mal wie folgt.

Es gibt ne boolsche Variable namens temperaturgraphAnzeigen die bei Betätigung des Buttons2 auf true gesetzt wird. Im Thread wird die boolsche Variable abgefragt und dann ggf. gehandelt.
Code:
if(temperaturgraphAnzeigen)
{
   Activity2.Methodexyz(...)
}
Bei Betätigung des Button2
passiert folgendes:
Code:
public void temperaturgraphAnzeigen(View v)
    {
        activity2 = new TemperaturGraphActivity();
        startActivity(activity2.getIntent());
        temperaturgraphanzeigen = true;
    }
activity2 habe ich vorher deklariert.


Hier noch der Auszug aus dem logcat:
04-11 15:26:58.311: W/dalvikvm(21265): threadid=1: thread exiting with uncaught exception (group=0x40d7d2a0)
04-11 15:26:58.356: E/AndroidRuntime(21265): FATAL EXCEPTION: main
04-11 15:26:58.356: E/AndroidRuntime(21265): java.lang.IllegalStateException: Could not execute method of the activity
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.view.View$1.onClick(View.java:3704)
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.view.View.performClick(View.java:4232)
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.view.View$PerformClick.run(View.java:17298)
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.os.Handler.handleCallback(Handler.java:615)
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.os.Handler.dispatchMessage(Handler.java:92)
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.os.Looper.loop(Looper.java:137)
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.app.ActivityThread.main(ActivityThread.java:4921)
04-11 15:26:58.356: E/AndroidRuntime(21265): at java.lang.reflect.Method.invokeNative(Native Method)
04-11 15:26:58.356: E/AndroidRuntime(21265): at java.lang.reflect.Method.invoke(Method.java:511)
04-11 15:26:58.356: E/AndroidRuntime(21265): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
04-11 15:26:58.356: E/AndroidRuntime(21265): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
04-11 15:26:58.356: E/AndroidRuntime(21265): at dalvik.system.NativeStart.main(Native Method)
04-11 15:26:58.356: E/AndroidRuntime(21265): Caused by: java.lang.reflect.InvocationTargetException
04-11 15:26:58.356: E/AndroidRuntime(21265): at java.lang.reflect.Method.invokeNative(Native Method)
04-11 15:26:58.356: E/AndroidRuntime(21265): at java.lang.reflect.Method.invoke(Method.java:511)
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.view.View$1.onClick(View.java:3699)
04-11 15:26:58.356: E/AndroidRuntime(21265): ... 11 more
04-11 15:26:58.356: E/AndroidRuntime(21265): Caused by: java.lang.NullPointerException
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.app.Instrumentation.execStartActivity(Instrumentation.java:1424)
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.app.Activity.startActivityForResult(Activity.java:3446)
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.app.Activity.startActivityForResult(Activity.java:3407)
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.app.Activity.startActivity(Activity.java:3617)
04-11 15:26:58.356: E/AndroidRuntime(21265): at android.app.Activity.startActivity(Activity.java:3585)
04-11 15:26:58.356: E/AndroidRuntime(21265): at de.gerding.wert_auslesen_wifi.WertAuslesen.temperaturgraphAnzeigen(WertAuslesen.java:144)
04-11 15:26:58.356: E/AndroidRuntime(21265): ... 14 more
die fett gedruckte unterstrichene Zeile zeigt im Code auf die Zeile mit dem Befehl
Code:
 startActivity(temperaturgraphactivity.getIntent());
Scheinbar war mein Lösungsansatz falsch weil die oncreate Funktion der Activity ja nicht aufgerufen wird.

Gibt es ne Möglichkeit aus der Activity1 auf die Funktionen der Activity2 zuzugreifen?
 
Du musst die zweite Activity über einen Intent starten. Dann kannst Du in den Intent action (was soll getan werden) und Daten (putExtra) packen.

Grüsse Uwe
 
  • Danke
Reaktionen: Micka
u.k-f schrieb:
Du musst die zweite Activity über einen Intent starten. Dann kannst Du in den Intent action (was soll getan werden) und Daten (putExtra) packen.

Grüsse Uwe
Intent.putExtra(...) kenne ich. Intent.Action bisher noch nicht. Kann ich über Intent.Action Methoden der Activity nutzen?

Mit Intent.put Extra kann ich der Activity ja vor dem Start Daten mitgeben, aber kann ich aus dem in Activity1 gestarteten Thread auch die Daten ändern während Activity2 schon aktiv ist?

Das Problem ist der Thread der aufrufenden Activity ist die ganze Zeit noch aktiv. In Dem Thread werden die Daten vom Sensor alle 3 sekunden abgerufen. Jetzt möchte ich Die Methode zum hinzufügen von Datenpunkten zum Graphen aus diesem Thread ausrufen.


Ich brauche entweder aus dem in Activity1 gestarteten Thread Zugriff auf die Methoden der Activity2 oder aus Activity2 Zugriff auf Variablen des in Activity1 gestarteten Threads.
 
Du bekommst beim Starten einer neuen Activity via Intent keine Referenz zur Activity Instanz.

Vorschlag: mit LocalBroadcastManager und entsprechendem Receiver in Activity2 kannst du deine Werte verschicken und jeder der sie haben will (Activity2) registriert sich und bekommt den Broadcast.
 
  • Danke
Reaktionen: Micka
Genau wie Deek vorgeschlagen hat, sollte man es machen.

Action ist nur ein String, den die geruufene Activity auslesen kann und anhand des Strings entscheiden muss, was sie tut.

Grüsse Uwe
 
  • Danke
Reaktionen: Micka
Okay, werd mich morgen mal ransetzen und in LocalBroadcast versuchen einzulesen.


Ist das viel an Quellcode?

Gesendet von meinem GT-I9100 mit der Android-Hilfe.de App
 
Nö, ist super einfach:

So sieht das in einer meiner Classes aus:

Empfänger:

Code:
	IntentFilter inFi = new IntentFilter();
	inFi.addAction("<MyString>");
	LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getActivity().getApplicationContext());
	lbm.registerReceiver(new BroadcastReceiver()
	{
		@Override
		public void onReceive(Context context, Intent intent) {
			[COLOR="Red"]new Handler().post(new Runnable() {
			    public void run() {
					setState(...);
			    }
			});[/COLOR]				
		}
	},inFi);

Bei addAction einen String übergeben, der dann vom Absender genauso übergeben wird. Es bietet sich an, hier de FullQualifiedClassName zu verwenden, um Überschneidungen (*) zu verneiden

Absender:

Code:
Intent in = new Intent("<MyString>");
LocalBroadcastManager.getInstance(this).sendBroadcast(in);

(*)Bei LocalBroadcast gibt es eigentlich keine Überschneidungen, wenn Du aber irgendwann auf Globale Broadcasts wechselst, bist Du auf der sicheren seite...

Der Handler (die rot markierte CodeStelle) ist nur nötig, wenn Du UI-Elemente bearbeitest, um zu erreichen, dass der UI-Thread verwendet wird...

Grüsse Uwe

Der ursprüngliche Beitrag von 17:40 Uhr wurde um 17:44 Uhr ergänzt:

Anmerkung:

Daten zwischen Sender und Receiver über Intent.putExtra(...) übergeben!

Grüsse Uwe
 
  • Danke
Reaktionen: Micka
Wenn ich das richtig im Kopf habe, sollte der Handler gar nicht nötig sein, da im Normalfall der LocalBroadcastManager im UI Thread zurück kommt, oder?
 
  • Danke
Reaktionen: Micka
Ich weiss es nicht genau.

Ich rufe aus einem Service den Local-Broadcast-Manger.

Dann hatte ich anschliessend probleme, dass meine App ageschmiert ist, wenn ich gerade das Tablet gedreht habe, während die Meldung aus dem Service kam.

Daraufhin habe ich den Handler verwendet....

Vielleicht hilft der auch nur, den Task ans Ende der Event-Queue zu stellen...

Grüsse Uwe
 
  • Danke
Reaktionen: Micka
Hatte heute leider keine Zeit mich dranzusetzen, werde das aber spätestens Montag testen und dann hier berichten.

Trotzdem schonmal Danke für eure Antworten

Gesendet von meinem GT-I9100 mit der Android-Hilfe.de App
 
hy

heute habe ich mich mal wieder rangesetzt. Ich bin mir nicht sicher ob ein Broadcast Receiver das richtige für meinen Fall ist. Wenn ich das richtig verstehe reagiert ein solcer Receiver auf Systemereignisse, in meinem Projekt verwende ich aber keine Systemereignisse.

Mein Problem ist das ich in Activity 1 einen Thread starte der permanent(bis er gestoppt wird) Sensorwerte abfragt. Diesen Wert speichert der Thread dann in einer Couch DB. Soweit so gut, das klappt alles.

Nun habe ich aber das Problem das ich in einer zweiten Activity die Sensorwerte in real time brauche die in dem Thread abgerufen werden um sie in einer AChartEngine anzuzeigen. Ich könnte sie ja aus der DB wieder auslesen (eintragen alle x sekunden im Thread, auslesen alle x sekunden aus der Activity) aber dafür ist die Verbindung zur Datenbank zu langsam. Abgesehen von der Geschwindigkeit der Datenbankverbindung hätte ich auch das Problem das die Abstände in denen Sensorwerte angerufen werden variabel sind. Der Thread ruft die Werte ab und trägt sie in die DB ein, dann pausiert er 3 sekunden und beginnt von vorn. Die Werte werden über wifi vom Arduino abgerufen, die Antwort ist mal schneller mal langsamer.

Kann ich die Werte (einen Double z.B:) aus dem Thread heraus an eine aktive Activity senden? Am praktischsten wäre es wenn ich an der Stelle des Threads wo ich die werte abrufe sie direkt zur activity übermittel. (oder geht genau das mit einem Broadcast Receiver und ich checks nur nicht?)

Ich habs über extras versucht aber die kann man zur Laufzeit der Activity ja nicht mehr ändern oder?
 
Nein, du kannst einen BroadcastReceiver eben nicht nur für Systemereignisse verwenden. Wenn du den LocalBroadcastManager verwendest kannst du selbst Ereignisse schicken, die deine Receiver erhalten können. Meiner Meinung nach funktioniert das was du machen willst, damit wunderbar...
 
  • Danke
Reaktionen: Micka
Okay, ich habs zuerst falsch verstanden. Danke für den Vorschlag das entspricht genau dem was ich suche jetzt wo ichs begriffen habe.

Falls noch jemand ein ähnliches Problem hat, hier meine Lösung mit kurzer Erläuterung:

Beim Absender ists ziemlich übersichtlich, Intent mit Stringkey erstellen, extras mit Stringkey hinzufügen, Broadcast senden

Code:
[B]Intent in = new Intent("neuerWert");
                                    in.putExtra("TEMPERATUR", erg);
                                    sendBroadcast(in);[/B]
Beim Empfänger ists ein bisschen mehr, aber auch recht simpel
BroadcastReceiver anlegen, registrieren, angeben was bei Empfang gemacht werden soll(onReceive Methode)

Code:
public class TemperaturGraphActivity extends Activity 
{
    ...
    [B]private BroadcastReceiver mReceiver  = new BroadcastReceiver() 
    {
        public void onReceive(Context context, Intent intent) 
        {
            Bundle extras = intent.getExtras();
            double y = extras.getDouble("TEMPERATUR");
            ...
        }
    };[/B]
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        ...
       [B] registerReceiver(mReceiver, new IntentFilter("neuerWert"));[/B]
        ...
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) 
    {
        if (keyCode == KeyEvent.KEYCODE_BACK) 
            {
                [B]unregisterReceiver(mReceiver);[/B]
                this.finish();
            }
            return super.onKeyDown(keyCode, event);
        }
}
neuerWert - StringKey des Broadcast
TEMPERATUR - StringKey für den zu übergebenden bzw. abzurufenden Wert

ob unregisterReceiver(mReceiver); pflicht ist weiß ich nicht, aber schaden tuts nicht.
 

Ähnliche Themen

D
Antworten
5
Aufrufe
600
swa00
swa00
Zurück
Oben Unten