1. Nimm jetzt an unserem Uhans - 3. ADVENT - Gewinnspiel teil - Alle Informationen findest Du hier!

GPS LocationManager!

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von BFK, 13.04.2011.

  1. BFK, 13.04.2011 #1
    BFK

    BFK Threadstarter Erfahrener Benutzer

    Beiträge:
    160
    Erhaltene Danke:
    10
    Registriert seit:
    08.12.2010
    Hallo,
    habe eine kleine Frage an euch.
    Wie ja schon bekannt ist, kann man mit..:

    Code:
    LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    LocationListener mlocListener = new MyLocationListener();
    
    mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 10000L,50.0f, mlocListener);
    
    den GPS-Provider aktivieren und mit hilfe der Klasse LocationListener da die emfangene Daten verarbeiten.

    Bei .:
    Code:
    mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 10000L,50.0f, mlocListener);
    
    gibt man an wann der GPS-Status abgefragen soll, bei meinem Fall habe ich 10.000 ms, also 10 sec und 50 meter als minimale Werte angegeben.

    Meine Frage ist jetzt, ob ich diese minimale Werte weglassen kann und zwar möchte ich z.B. nur einen minimalen Wert für die Zeit haben (z.B. meine 10 sec), aber keinen Wert für die Distanz.

    Eine Lösung wäre ja beides auf 0 zu setzen und bei onLoactionchange (bei der LocationListener-Klasse) eine if-Bedinung zu setzen. Das Problem ist nun das hier der Akku ohne Grund verschwendet wird.

    deshalb meine Frage ob es eine elegantere Lösung gibt..!
     
    Zuletzt bearbeitet: 13.04.2011
  2. aslkoeln, 13.04.2011 #2
    aslkoeln

    aslkoeln Neuer Benutzer

    Beiträge:
    13
    Erhaltene Danke:
    1
    Registriert seit:
    13.04.2011
    minDistance kannst Du nicht weglassen. Auf 0, 0 würde ich die beiden aber auch nicht setzen - das frisst den Akku.

    minDistance ist aber nun mal das i-Tüpfelchen (die minTime spielt überhaupt keine Rolle wenn minDistance nicht erreicht ist) deshalb solltest Du vielleicht an Hand Deiner Anwendung überlegen was ein sinnvoller Wert wäre.

    Z.B. an Hand eines Radfahrers. Der kann in 10 Sekunden bei 10-50 km/h wieviele Meter zurücklegen (nimm 30). Der Fußgänger (3-10 km/h - nimm 20). Der Autofahrer (30-300 km/h - nimm 100).

    So würde ich daran gehen.

    Gruß
    Harald
     
  3. krackmoe, 14.04.2011 #3
    krackmoe

    krackmoe Junior Mitglied

    Beiträge:
    41
    Erhaltene Danke:
    0
    Registriert seit:
    02.03.2011
    Mh.. mal ne Frage zu der Distance..

    Wie ist das mit minTime und minDistance zu verstehen.

    Wenn ich z.b. minTime: 2sekunde habe und minDistance 100m

    Prüft er dann alle 2 Sekunden ab ob er 100m entfernt ist und ändert die Position dann?
     
  4. aslkoeln, 14.04.2011 #4
    aslkoeln

    aslkoeln Neuer Benutzer

    Beiträge:
    13
    Erhaltene Danke:
    1
    Registriert seit:
    13.04.2011
    Der LocationManager legt sich tatsächlich für minTime schlafen - wenn er nichts anderes zu tun hat. Dann wacht er auf, prüft ob die minDistance erreicht wurde und legt sich wieder für minTime hin. So verstehe ich die Doku.

    Allerdings sehe ich in den Aufzeichnungen meiner Apps das die Broadcasts teilweise völlig daneben sind - aber das ist ja auch so dokumentiert. Das ist halt kein Real-Time-Service.

    Gruß
     
  5. BFK, 14.04.2011 #5
    BFK

    BFK Threadstarter Erfahrener Benutzer

    Beiträge:
    160
    Erhaltene Danke:
    10
    Registriert seit:
    08.12.2010
    Erstmal danke für euere Antworten...!

    Also der LocManager, so wie aslkoeln auch erklärt hat prüft beide Werte. Es müssen also beide Bedinungen stimmen, damit ein Signal emfangen wird.

    Mein Problem war ja, dass ich einen Wert auslassen möchte. Das alles nur um zum Testen ob es geht. Wie es scheint funktioniert das ja auch, z.B. wenn ich folgendes schreibe..:
    Code:
    mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER,0,100, mlocListener);
    
    dann wird nur ein Signal emfangen, wenn der nächste Punkt min 100m vom vorrigen Punkt entfernt ist.

    Aber das folgende funktioniert leider nicht..:
    Code:
    mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER,10000,0, mlocListener);
    
    ...also hier ist die minDistanz auf 0 gesetzt, aber die minZeit auf 10 sec.
    Hier habe ich gesehen, dass z.B. die onLocationChanged-Methode dauerhaft aufgerufen wird, deshalb auch mein Thread.

    Ich bin mir jetzt zwar nicht sicher, aber ich glaube, dass das Problem beim Emulator liegt und das der obenbeschriebene Code aufm Gerät mit echten GPS-Signal funktionieren wird.
    Ich kam zur dieser Annahme, weil die Zeit vom simulierten Signal ja falsch ist und so der LocManager denkt dass die 10 sec schon um sind..!

    Wie gesagt bin mir nicht sicher, aber ich galube, dass das der Fehler sein könnte..!
     
  6. aslkoeln, 14.04.2011 #6
    aslkoeln

    aslkoeln Neuer Benutzer

    Beiträge:
    13
    Erhaltene Danke:
    1
    Registriert seit:
    13.04.2011
    Korrekt, aber Du saugst den Akku leer. Der LocationManager pausiert nicht. Du bekommst zwar erst nach jeweils 100m eine Location aber das Subsystem arbeitet die ganze Zeit ohne Pause - so schnell es kann.

    Alles andere arbeitet wie in der Doku beschrieben: "If minDistance is greater than 0" - ist es im zweiten Beispiel aber nicht. Da minTime zudem ein "Hint" ist (ist ja nur eine Hilfe um Batterie zu sparen) knallt alles so schnell wie möglich rein.

    Lange Rede, kurzer Sinn. Füllt bitte beide Felder mit Werten über 0. Was Du an Werten nimmst würde ich an Hand der Problemstellung festmachen - siehe meine Beispiele oben.

    Ich habe zum Beispiel zwei Anwendungen im Store - die eine für Sportler die andere für Autofahrer. in beiden gibt es die Möglichkeit die Strecke aufzuzeichnen. In beiden gebe ich dem Benutzer die Möglichkeit das in den Settings einzustellen - vorbesetzt habe ich aber Folgendes:

    GaCoMo für Sportler: 2sec, 7m
    Tankbuch Mobil fürs Auto: 10sec, 1000m

    ABER: Will man zum Beispiel im Auto eine Karte mitlaufen lassen dann sind 10sec/1000m arg grob, also lasse ich mir im Auto auch 2sec/7m liefern, speichere in der Datenbank dann aber nur zu den vom Benutzer angegebenen Werten. Ich schiebe also quasi noch eine Schicht dazwischen (im Auto ist ja meist ein Stromkabel dran). Ein Sportler ist in der Regel max. 4 Stunden unterwegs da sind 2sec/7m in der Datenbank halbwegs überschaubar. Wenn Onkel Karl mit dem Auto nach Italien brettert und es werden alle 2sec Rows erzeugt - dann möchte ich die Map nicht mehr auf einem Smartphone zeichnen müssen ;-)

    Gruß
    Harald
     
  7. BFK, 14.04.2011 #7
    BFK

    BFK Threadstarter Erfahrener Benutzer

    Beiträge:
    160
    Erhaltene Danke:
    10
    Registriert seit:
    08.12.2010
    Ah, also du meinst im Falle das minTime gleich 0 ist, wird ununterbrochen geprüft ob minDistance mindestens den Wert 100 hat (im meinem Besipiel) und das leert den Akku.

    Da du schon das Beispiel mit der Map angesprochen hast, wollte ich dich noch was fragen. Ist klar, dass die DB riesig wird, wenn du mit dem Auto alle 2 sec die Daten speicherst und der Nutzer noch nach Italien fährt (>1000 km Entfernung). Aber wie meinst du das mit eine Schicht dazwischen schieben. Meinst du das alle 2s,7m der Standpunkt auf der Karte angezeigt wird, aber nur alle 10s,1000m die Daten in der DB gespeichert werden..?

    Ein anderers Beispiel, was wäre wenn ich auf der Karte die Route zeichnen will und ich dazu den LocListener benutzen würde (weiss nicht ob hierfür ne andere Klasse besser geignet wäre), dann würde ja alle 1000 m der neue Punkt mit dem vorrigen Punkten verbunden, das wirklich nicht gut ausehen würde.

    Was würdest mir raten, wenn ich die Route auf der Karte zeichnen will..?
    Eine andere Einstellung für die Karte und eine andere für das abspeichern..?
     
  8. aslkoeln, 14.04.2011 #8
    aslkoeln

    aslkoeln Neuer Benutzer

    Beiträge:
    13
    Erhaltene Danke:
    1
    Registriert seit:
    13.04.2011
    Ja und nochmal ja.

    Wenn der Benutzer unterwegs ist will ich ihm die präzise Position zeigen. Auch die ermittelten Werte für Entfernung und Geschwindigkeit sollen möglichst präzise sein. Wenn der Benutzer später die Map wieder aufruft (und wir reden jetzt gerade über den Autofahrer, nicht über den Sportler) dann ist eine Map mit einer Koordinate alle 1km halb so wild. Deshalb dieses Zwischenspiel. Deshalb überlasse ich das auch dem Benutzer.


    Grundsätzlich kann ich Dir nur empfehlen einen Service zur Aufzeichnung zu verwenden. Services werden vom System nur im äußersten Notfall abgeschossen und Deine Anwendung muss überhaupt nicht laufen damit aufgezeichnet wird.

    Meine Services blenden eine Notification ein damit der Benutzer jederzeit wieder zur Anwendung springen kann, speichern autark in die Datenbank und kommunizieren mit der Activity über Broadcasts. Ich könnte auch Binder verwenden habe mich aber dagegen entschieden. Da meine Services selbst speichern und die MapActivity mit ihren Overlays nur anzeigt - reicht m.E. ein Broadcast aus. Die können nämlich mal verloren gehen ;-)

    Der Service ist aber gleichzeitig auch ein Receiver damit er Pause, Resume und Stopp Anweisungen erhalten kann.

    Ich mag das Konzept. Es läuft in den betreffenden Anwendungen völlig unproblematisch und zuverlässig. Ich habe in den Settings zwar noch einen NotAus-Knopf (falls mal doch der Service abgeschossen wird und die Notification hängen bleibt) - aber bisher habe ich das noch nie benötigt (außer während des Debuggens).

    Das mit den verschiedenen Werten für die Datenbank und zur Anzeige habe ich mir ausgedacht. Das habe ich bisher noch nirgends gesehen. Für mich sind die Datenbanken im /data/data/<packagename>/databases (internal memory) ein kritischer Pfad deshalb versuche ich so effizient wie möglich zu speichern. Einen Akku kann ich nachladen, Speicher der zur Neige geht ist aber futsch.

    Aufgefallen ist mir das bei unserem GaCoMo. Es gibt Sportler mit weit über 1500 Trainingseinheiten, jede davon mit 1-4 Stunden Länge. Professionelles Equipment zieht alle 2sec eine Koordinate mit Höhe, Herzfrequenz, Trittfrequenz, Links-/Rechts-Pedalbelastung, Geschwindigkeit, ...

    Ich hatte da schnell eine 50MB Datenbank zusammen - nach 500 Übungen. Das kneift bei einer internen Karte von 128MB ganz gewaltig. Deshalb versuche ich immer den Goldenen Mittelweg zwischen Featurities und dem was dem Benutzer wirklich wichtig sein könnte.

    Deshalb zeigen wir im Auto alle 2sec/7m an, speichern für die Historie aber nur alle 10sec/1000m (durch den Benutzer einstellbar).

    Gruß
    Harald
     
    BFK bedankt sich.
  9. BFK, 14.04.2011 #9
    BFK

    BFK Threadstarter Erfahrener Benutzer

    Beiträge:
    160
    Erhaltene Danke:
    10
    Registriert seit:
    08.12.2010
    Dass ich für die Aufzeichnung nen Service benutzen soll habe ich mir auch schon gedacht. Ausser den Vorteilen, die du meintest ist es noch sehr praktisch für den Nutzer, der ja noch andere "Sachen" aufm handy erledigen kann während er aufzeichnet..!

    Ich danke dir mehrmals für deine Aufklärung, hast mir sehr geholfen..!

    Nochmals DANKE..!

    -MFG BFK-
     
  10. r4in, 18.04.2011 #10
    r4in

    r4in Android-Hilfe.de Mitglied

    Beiträge:
    88
    Erhaltene Danke:
    3
    Registriert seit:
    16.09.2010
    Hallo Leute,

    ich möchte einen Service bauen der mit im Hintergrund die aktuellen Positionsdaten in eine Datenbank schreibt. Im Moment fliegt mir aber sobald ich GPS Empfang hab, mein Programm um Ohren.

    Hier der Quellcode des Service.


    Code:
    public class GpsService extends Service implements LocationListener {
    
        
         SQLiteDatabase db = null;
         private String TABLE_NAME = "gps";
         boolean gps = false;
    
         public static MainActivity MAIN_ACTIVITY;
    
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
        
        
        
          /* Use the LocationManager class to obtain GPS locations */
    
        @Override
        public void onCreate() {
    
    
                LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
                LocationListener mlocListener = new GpsService();
                mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 10000, 0, mlocListener);
    
              
            super.onCreate();
    
            }
         
    
        @Override
        public void onDestroy() {
            
            
        }
        
        @Override
        public void onStart(Intent intent, int startid) {
    
              
    
        }
    
    
        public static void setMainActivity(MainActivity activity)
        {
          MAIN_ACTIVITY = activity;
        }
    
        public void onLocationChanged(Location arg0) {
    
    
    
               db = ObjectPool.getContext().openOrCreateDatabase(ObjectPool.getDBName(),0, null);
               db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME+ "(acc varchar ,alt varchar, bearing varchar, extras varchar, lat varchar , long varchar, speed varchar)");
    
           
               try {
                db.execSQL("INSERT INTO  " + TABLE_NAME
                        + "(acc, alt, bearing, extras, lat  , long , speed) "
                        + "Values('"
                        + arg0.getAccuracy() + "','"
                        + arg0.getAltitude() + "','"
                        + arg0.getBearing() + "','"
                        + arg0.getExtras() + "','"
                        + arg0.getLatitude() + "','"
                        + arg0.getLongitude() + "','"
                        + arg0.getSpeed() + "');");
            } catch (SQLException sQLException) {
                
            }
          
            try {
                db.close();
            } catch (Exception e) {
            }
    
          //  Toast.makeText(this, "GPS", Toast.LENGTH_LONG).show();
    
        }
    
        public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
           
        }
    
        public void onProviderEnabled(String arg0) {
           
        }
        public void onProviderDisabled(String arg0) {
            
        }
     }
    Hat jemand eine Idee woran es liegt bin gerade echt am verzweifeln. Da die Tutorials in über Sevice alle nach diesem Schema laufen.

    Danke
     
  11. aslkoeln, 18.04.2011 #11
    aslkoeln

    aslkoeln Neuer Benutzer

    Beiträge:
    13
    Erhaltene Danke:
    1
    Registriert seit:
    13.04.2011
    Guck Dir das doch mal bitte im Debugger an. Wo kommt der Fehler? Welchen Fehler erhälst Du? Ich denke dann wirst Du schon selbst einen tiefen Einblick bekommen.

    Ich weiß nicht was Du da alles machst. Du scheinst alles ein wenig durcheinanderzuwürfeln.

    Fang doch mal mit einer eigenen SQLiteOpenHelper Klasse für die Datenbank an. Dort wird dann im onCreate eine Tabelle angelegt. Dort stellst Du dann auch die Methode zum Einfügen von Rows Verfügung.

    Der onCreate im Service spielt nicht eine so große Rolle wie in der Activity, verlagere also das Öffnen der Datenbank in den onStartCommand, der onDestroy schließt sie wieder.

    Sobald ein onLocationChanged reinkommt konzentrierst Du Dich aus Zeitgründen ausschließlich um das Verarbeiten dieser einen Koordinate.

    ... und was, wenn ich fragen darf, macht denn die statische Activity Variable da?

    Gruß
    Harald
     
  12. r4in, 18.04.2011 #12
    r4in

    r4in Android-Hilfe.de Mitglied

    Beiträge:
    88
    Erhaltene Danke:
    3
    Registriert seit:
    16.09.2010
    Hi Harald,

    danke für die schnelle Antwort. Die static war noch ein überbleibsel und ist jetzt weg ;-) Ich verwende im Moment Netbeans und das Problem ist ich hab bis heute nicht gefunden wo netbeans Fehler abspeichert die eine Activity oder Service zum absturz bringen. Ich werde aber mal deine Tipps mit der Datenbank in onStart() benutzen. Es werden, das hab ich gerade gesehen auch schon Daten in die Datenbank abgespeichert. Aber stürzt dann ab.
     
  13. aslkoeln, 18.04.2011 #13
    aslkoeln

    aslkoeln Neuer Benutzer

    Beiträge:
    13
    Erhaltene Danke:
    1
    Registriert seit:
    13.04.2011
    onStartCommand(), nicht onStart()

    Gruß
    Harald
     

Diese Seite empfehlen