Handler von mehreren Klassen nutzen

  • Antworten:8
  • Bentwortet
Rolf Baumann
  • Forum-Beiträge: 24

06.12.2014, 15:28:33 via Website

In meiner MainActivitiy definiere ich einen Handler, der die Resultate der Klasse „Aufgaben“ (Bluetooth-Abfrage) übernimmt. Dies läuft alles wie es soll:

public class MainActivity extends Activity{
….

if (mAufgaben == null) {
    mAufgaben = new Aufgaben(this, mHandler);
    mAufgaben.start();
}
mAufgaben.connect(device);
….

public Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
    MessageType message = MessageType.from(msg.what);

….

public static class MyReceiver extends BroadcastReceiver{   
     @Override
     public void onReceive(Context context, Intent intent){
            Bundle extras = intent.getExtras();
            Intent service1 = new Intent(context, mService.class);
            service1.putExtra("MAC", mac_data);
           context.startService(service1); 
     }   
}




public class Aufgaben {
    private final Handler mHandler; 
    public Aufgaben(Context context, Handler handler) {
        …
        mHandler = handler;
    }

    public synchronized void start() {
    ….
    }

Message msg = mHandler.obtainMessage(MessageType.DEVICE_NAME.val());
        Bundle bundle = new Bundle();
        bundle.putString(MessageType.DEVICE_NAME.toString(), device.getName());
        msg.setData(bundle);
        mHandler.sendMessage(msg);

Bis hier funktioniert alles wie es soll!
Neu möchte ich von einem Service, der im Background läuft, auch auf die Klasse Aufgaben zugreifen (Initiierung neues Objekt und Start der Aufgaben). Die Resultate sollen wieder in der MainActivity verfügbar sein mittels gleichem Handler.

public class mService extends Service{

….
    if (mAufgaben == null) {
        mAufgaben = new Aufgaben(this, mHandler);
        mAufgaben.start();
}
mAufgaben.connect(device);

Der in der MainActivity definierte Handler ist jedoch in Service nicht bekannt (mHandler cannot be resolved!!). Wie kann ich von mService auf „Aufgaben“ zugreifen und die Resultate in der MainActivity erhalten?

Antworten
pepperonas
  • Forum-Beiträge: 434

07.12.2014, 22:25:19 via Website

Hallo Rolf,
meiner Meinung ist der Service hier nicht nötig, oder ich habe die Frage bzw dein Vorhaben nicht 100%tig geblickt..
Daten kannst du via Broadcast an deine Activity senden.

Auf die Reise geht die Nachricht dann vom Service aus mit diesem Code:

 dzBundle.putInt(DIRECTION_BKEY, mDirection);

    // Intent mit Filter erstellen
    Intent dzIntent = new Intent(TRACKER_FILTER);

    // dem Intent das Extra übergeben
    dzIntent.putExtras(dzBundle);

    // Broadcast senden
    LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(dzIntent);

in deiner Main legst du den Receiver als eine Art Member an...

    /**
     * Receiver reagiert auf Positionsänderungen die aus ProtectionService übermittelt wurden.
     */
    private final BroadcastReceiver mTrackReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
          [...]
     }
}

und nicht vergessen den BR in onCreate der Main zu registrieren, das könnte so aussehen...

  // BR für Positionsänderungen
   mLbM = LocalBroadcastManager.getInstance(this);
    mLbM.registerReceiver(mTrackReceiver, new IntentFilter(TRACKER_FILTER));

-> in onDestroy soltest du ihn dann wieder abmelden.. (bzw. in onPause() - wie es bei dir halt Sinn macht)

TRACKER_FILTER ist einfach nur ein String, der den BR kennzeichnet...

Hoffe du hast eine grobe Idee bekommen wie er funktioniert

Weitere Infos findest du zB hier oder in der Doku :)

Open Source

Antworten
Rolf Baumann
  • Forum-Beiträge: 24

08.12.2014, 09:28:07 via Website

Ganz herzlichen Dank für den Input. Das Ganze funktioniert so wie vorgeschlagen. Super:D

Eine Frage bleibt: Ich habe gewisse Aktivitäten in den Service ausgelagert, da meine MainActivity jeweils nach einigen Stunden Inaktivität des Nutzers "heruntergefahren" und die Bluetooth-Abfrage gestoppt wurde. Empfängt der BroadcastReceiver in diesem Fall immer noch Daten vom Service?

Antworten
pepperonas
  • Forum-Beiträge: 434

08.12.2014, 10:00:04 via Website

Super, das freut mich :)
Okay, jetzt wo ich das mit dem Bluetooth lese macht der Service doch Sinn^^
Nope, die Main ist dann nicht mehr über den BR ansprechbar, die Nachrichten gehen ins Leere (jedenfalls so wie ich Sache jetzt von hier aus der Ferne "abschätze") du kannst die Main aber wieder via Intent aus dem Service aufrufen bzw. in den Vordergrund holen - sogar könntest du den Keyguard (sprich das "Bildschirmentsperren") deaktivieren.
Aufpassen solltest besonders an zwei konkreten Stellen: Wenn du einen Intent vom Service an eine Activity richtest, erfolgt der Intent mittels dem Flag "NEW_TASK" anderenfalls meldet sich Logcat recht deutlich zu Wort :D - gleichzeitig wirst du noch die onNewIntent in Main überschreiben müssen um dort den Intent bzw. die Daten aus dem Service "auszuwerten".

Open Source

Antworten
Rolf Baumann
  • Forum-Beiträge: 24

08.12.2014, 10:21:27 via Website

Kurz 2 Fragen:
- muss man vor dem Aufruf der Main zuerst prüfen, ob die Main noch aktiv ist oder nicht mehr?
- Ist der Aufruf der Main ein eigenes Intent, so wie ich mir dies so vorstelle:

// Intent für Aktivierung Main
Intent dialogIntent = new Intent(getBaseContext(), MainActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(dialogIntent);

 // Intent für Daten an Main
Intent dzIntent = new Intent(TRACKER_FILTER);
Bundle dzBundle = new Bundle();
dzBundle.putString("Daten", daten);
dzIntent.putExtras(dzBundle);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(dzIntent);

Oder kann man dies in ein Intent packen?

Antworten
pepperonas
  • Forum-Beiträge: 434

08.12.2014, 14:52:03 via Website

Hallo, meines Wissens führt kein Weg an der Kombination der zwei verschiedenen "Mechanismen" vorbei (also so wie du es oben beschreibst, habe ich es auch implementiert und funktioniert super...)
Der BR wird ja über den Receiver empfangen, wohingegen die Daten beim "richtigen Intent" (also der, der mehr darstellt als die "Filterfunktion" - so hab ichs mir jedenfalls vorgestellt^^) über die onNewIntent abgerufen werden...
100%tig sicher bin ich mir allerdings auch nicht, aber ich wüsste sonst keinen Weg den Context wieder zubekommen - ihn in Main zu speichern scheidet aus (das würde Memory-Leaks mit sich ziehen) / der Broadcast liefert nur die Daten aber nicht den Context als solchen und der Service bedient ja nicht direkt die UI.. sogesehen bin ich mir schon ziemlich sicher, dass man die Logik "teilen" muss. Aber ist ja mit 2-3 kleinen Funktionen gemacht.

— geändert am 08.12.2014, 14:58:39

Open Source

Antworten
Rolf Baumann
  • Forum-Beiträge: 24

08.12.2014, 15:11:39 via Website

Vielen Dank für Deine Antwort.

Wahrscheinlich ist es auch sinnvoll, wenn man prüft, ob die Main noch aktiv ist oder nicht, bevor man die Main aktiviert mittels

// Intent für Aktivierung Main
Intent dialogIntent = new Intent(getBaseContext(), MainActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(dialogIntent);

Ich hoffe, ich liege da nicht falsch.

Antworten
pepperonas
  • Forum-Beiträge: 434

08.12.2014, 16:05:18 via Website

Kommt drauf an.. Bei meinem Programm ist es nicht weiter schlimm, da wenn der Service Ergebnisse liefert, der Nutzer unbedingt die Info bekommen soll, sonst wäre das gesamte Programm witzlos^^. Dementsprechend hab ich auf so eine Prüfung verzeichtet und nehme in Kauf, dass der Nutzer aus dem "normalem Betrieb" herausgeworfen werden kann und dann in meiner App aufschlägt. :D (Android dreht einem da keinen Strick)...
Wenn das bei dir keinen Sinn macht, könntest du via statischem Boolean ja diese Prüfung durchführen. In onResure wird er true (Activity ist "da") und dann in onPause wieder false (onStop muss nicht durchlaufen werden, deswegen ist onPause imho besser).

Open Source

Antworten
Rolf Baumann
  • Forum-Beiträge: 24

08.12.2014, 19:10:50 via Website

Ich habe dies alles so umgesetzt und es funktioniert, super! Ganz herzlichen Dank für Deine Unterstützung.:D

pepperonas

Antworten