Location Manager, Listener wird nicht aufgerufen

  • Jetzt wird's merkwürdig:
    Ich hätte gerne zyklisch ( alle 15 Minuten ) eine Info über meine aktuelle Position.


    Ich habe per Alarmmanager einen zyklischen 15 Minuten Alarm gestartet. Der kommt auch.


    Im Broadcast Receiver des Alarms rufe ich dann die Funktion:

    Code
    locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    if (locationManager != null)
    {
      Toast.makeText(context, "SingleUpdate", Toast.LENGTH_LONG).show();
      locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, locationListener, null);
    }



    Durch die Toast-Ausgabe kann ich sehen, das die SingleUpdate Funktion wirklich alle 15 Minuten aufgerufen wird.


    Und jetzt kommt das Merkwürdige:
    Ich habe zwei völlig identische Handys, zur gleichen Zeit beim gleichen Handler gekauft.
    Bei dem ersten Handy funktioniert alles, beim zweiten wird der Listener nicht aufgerufen.
    Kann sich jemand einen Reim darauf machen?


    Hier der relevante Code als Auszug:

    Was noch merkwürdig ist:
    Ich hatte den Listener zuerst als separate Memberfunktion des Alarms geschrieben und den Listener nur einmal am Anfang erzeugt.
    Dabei ist meine App aber ständig abgestürzt.
    Die oben angegebene Vorgehensweise ( Listener mit new in der onReceiveFunktion erzeugen ) habe ich aus einem Beispiel.
    Das kommt mir sehr suspekt vor, hat aber funktioniert.

  • also ich mache das immer so dass meine listener member sind. Sonst wird ja jedesmal wenn ein alarm kommt, ein neues objekt erzeugt. Was für eine Fehlermeldung kam denn?


    Das hat aber denk ich nichts damit zutun, dass es bei dem einen handy geht und bei dem anderen nicht. Läuft auf beiden Handys das selbe Android?

  • Eben, das mit den ständig erzeugten Listenern kam mir auch merkwürdig vor.
    Warum macht man sowas?
    Das kann doch nur funktionieren, wenn der Listener nach dem Aufruf wieder zerstört wird.


    Mit dem Listener als Member des Alarms stürzte die App immer ab.
    "Es tut uns Leid, MyApplication wurde leider beendet".
    Ich habe leider noch nicht herausbekommen können, ob es irgendwo eine Log-Datei gibt und wie
    man sie liest.
    Ich kann's ja nochmal ausprobieren, ist schon ne Weile her. Ich kann mich jetzt nicht mehr genau erinnern,
    wann der Ansturz erfolgte.


    Die Handys sind komplett identisch, Android Version ist 4.4.4.

  • Naja, das ist nun nicht soo schlimm, nur nicht wirklich schön gecodet. Es wird halt nach jedem alarm ein neuer listener gesetzt.


    Wozu machst du eigentlich nochmal den listener? du bekommst doch schon dein broadcast und kannst dann ausführen was du willst sobald ein locationchange gemacht wurde.
    Also mir erschließt sich noch nicht warum du einen broadcast brauchst? Wozu verwendet du den?
    Es genügt wenn du dir den Locationmanager in einer Activity holst und dort dann die update trackst. Bzw wenn du das über einen längeren Zeitraum machen möchtest nutzt du lieber einen Service.

  • So, habs nochmal mit dem Listener als Member-Funktion des Alarms probiert und
    genauere Ausgaben gemacht.
    Das Problem ist folgendes:
    Der Listener wird in einer Membervariablen des Alarms gespeichert.


    Wenn ich den Listener einmalig am Anfang in der Init-Funktion erzeuge und der Variablen zuweise,
    zeigt die Variable auf das erzeugte Objekt ( den Listener ).


    Wenn dann später der Alarm auslöst, ist die Variable aber null.


    Hier der relevante Code:

  • Wenn ich den Locationmanager wie üblich programmiere, bekomme ich andauernd Location Updates.
    Ich möchte aber nur genau alle 15 Minuten eine Standortabfrage durchführen.
    Also benutze ich einen Alarm, der periodisch alle 15 Minuten auslöst.
    Und in der zyklischen Alarmfunktion rufe ich ein mal die SingleUpdate Funktion des LocationManagers auf.
    Diese ermittelt dann die Position und ruft den Listener auf.
    Geht das auch einfacher?


    Ach ja, und ich habe gelesen, das Belastung der Batterie des Handys geringer sein Soll, wenn man einen Alarm benutzt.
    Ich denke, en Service würde ständig im Hintergrund laufen und Strom verbrauchen

  • du hast mich missverstanden. So geht es erst recht nicht. Die Klasse Alarm wird vom android framework instanziiert, das heißt dein init wird nie aufgerufen. Wenn du den Alarm instanziierst, ist deine Instanz nicht die selbe in der das OnReceive aufgerufen wird.


    Ich meinte, du sollst hinter deine membervariable kein ";" machen sondern ein "= new ....."
    Oben, bei der Variable, dort instanziierst du deinen Listener.


    Und hab gerade wieder realisiert wofür der broadcast ist :D
    Aber danke das dus nochmal ausgeführt hast.


    Und ja da hast du vollkommen recht!
    Ich hatte wie gesagt ausgeblendet dass du das nur alle 15min machen möchtest. Da ist natürlich ein Alarm weitaus akku schonender. Wenn du aber aller paar sekunden etwas aktualiseren willst, dann ist ein service geeigneter.

  • Hallo Champ,
    zunächst mal möchte ich dir danken, dass du hier so aktiv alle NewbeeFragen beantwortest.
    Ich finde es bewundernswert, wenn sich jemand diese Zeit nimmt und die Geduld aufbringt.


    Ich finde, das musste mal gesagt werden !


    Zu deiner Antwort:


    Doch, die Init Funktion wird aufgerufen, und zwar von meiner Activity, nachdem ich den Alarm mit new erzeugt habe.
    Ich dachte nur, wenn man ein Objekt (Alarm) mit new erzeugt, dann hat man eine neue Instanz und kann in dieser aller Funktionen ( auch die Init ) aufrufen.


    Wie du dargelegt hast, scheint das wohl doch nicht so zu sein.
    Wenn ich dich richtig verstanden habe, rufe ich die Init Funktion in einer Instanz des Alarms auf, der Alarm selbst läuft aber in einer anderen Instanz. Deshalb war der Listener auch null, wenn der Alarm ausgelöst hat.( Laienhaft ausgedrückt, ich stecke da noch nicht so ganz drin, ich kenne mich bisher nur etwas mit C++ aus, Java ist völlig neu für mich ).


    Ich hatte mir allerdings eine andere Erklärung für das Phänomen ausgedacht:
    Ich dachte, dass jedesmal, wenn der Alarm ausgelöst wird, eine neue Instanz des Alarms erzeugt wird, und gelöscht wird, wenn der Alarm behandelt ist. Und damit sind auch alle Klassenvariablen innerhalb des Alarms nach dem Löschen futsch.


    Dein Tip, den Listener gleich bei der Variablendeklaration im Kopf des Alarms anzulegen, war jedenfalls gut.


    Wenn allerdings meine Vermutung zutrifft, und die Alarminstanz bei jedem Auslösen des Alarms neu erzeugt wird, dann ist das dann das Gleiche in Grün, weil:


    Code
    ObjectType object;
    
    
    object = new ObjectType;


    ist das Gleiche wie:

    Code
    ObjectType object = new ObjectType;


    Leider kann ich im Moment nicht ausprobieren, ob das jetzt auch auf dem zweiten Handy funktioniert, für den ich diese App eigentlich gedacht habe. Auf meinem Handy geht das jedenfalls.

  • Danke, es freut mich immer wenn die User dann auch aktiv sind und weiterhin mit diskutieren. Nichts ist schlimmer wenn man eine Frage beantwortet und der User schreibt dann nicht mehr.


    Alarm ist in dem fall nur ein name, das ist nichts anderes als eine normale klasse die aber von der Android Framworkklasse "Broadcast Receiver" erbt. In deiner Manifest hast du diesen BroadcastReceiver bestimmt definiert oder? Aber Ja so wie du es "laienhaft" :P ausgedrückt hast, passiert es. Das ist auch keine Eigenart von Java, sondern von dem Android Framework was einem diese Werkzeuge wie den Broadcast Receiver zur Verfügung stellt.


    Deine Vermutung ist aber meines Wissens Falsch, das jedesmal eine neue Alarm Instanz erzeugt wird. Es wird eine Instanz erzeugt (auf die du keinen Zugriff von deiner Activity aus hast), und bei jedem Alarm wird nur die onReceive Methode erneut aufgerufen. Deswegen deklarierst du deine Alarm Klasse auch als Broadcast Receiver in der Manifestdatei. So weiß Android dass es für deine App eine Instanz dieser Klasse erzeugen muss. Diese bleibt dann erhalten und es wird nur noch deren onReceive Methode aufgerufen.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!