How to set a timer to the "LocationListener"

34 views
Skip to first unread message

rdvg...@gmail.com

unread,
Jan 4, 2019, 1:12:15 PM1/4/19
to CodenameOne Discussions
Hi,

I have read other posts on this topic but I do not see a clear solution. How do I set a time of 15 minutes (for example) to separate each reading of the gps ?.

As an alternative I thought about using the UITimer api and using the "Location" (Location position = LocationManager.getLocationManager (). GetCurrentLocationSync ();) But I do not know if this works or can run in the background.

My Code

    class Localizacion implements LocationListener, Runnable {

        private boolean inactivo = false; 
        private int status;
        private long sesion;
        private Location loc2;
        private boolean primeraVez = true;

        public Localizacion(long sesion) {
            super();
            this.sesion = sesion;
        }

        public void inactivaRastreo() {
            this.inactivo = true;
        }

        public void activaRastreo() {
            this.inactivo = false;
        }

        public void locationUpdated(Location loc) {
            while (!inactivo) {
                if (primeraVez) {
                    loc2 = loc;
                    primeraVez = false;
                }
                adicionTransaccion(loc, loc2, sesion);
                loc2 = loc;
            }
        }

        @Override
        public void providerStateChanged(int newState) {
            // check for unavailable errors etc.
            status = newState;
        }

        public void run() {
            while (!inactivo) {
                try {
                    Thread.sleep(10000); // Después de cumplir este tiempo se envia el error
                } catch (InterruptedException err) {
                    Dialog.show("Error", "No se pudo ejecutar la lectura del GPS", "Continuar", null);
                    inactivo = true;
                }
            }
        }
    }

Shai Almog

unread,
Jan 5, 2019, 12:18:37 AM1/5/19
to CodenameOne Discussions
Hi,
This is how you do it:

     LocationManager.getLocationManager().setLocationListener(myListener, new LocationRequest(LocationRequest.PRIORITY_MEDIUM_ACCUARCY, 15 * 6000));

myListener is an implementation of the LocationListener callback interface.

rdvg...@gmail.com

unread,
Jan 5, 2019, 2:02:27 PM1/5/19
to CodenameOne Discussions
Hi,

I must be doing something wrong because it does not work for me.

Create a small method to start this way:

    private void geoLocalizacion() {
        sesion = System.currentTimeMillis();
        LocationManager locationManager = LocationManager.getLocationManager();
        localizacionConductor = new Localizacion(sesion);
//        locationManager.setLocationListener(localizacionConductor); 
        locationManager.setLocationListener(localizacionConductor, new LocationRequest(LocationRequest.PRIORITY_MEDIUM_ACCUARCY, 15 * 6000));
    }

Shai Almog

unread,
Jan 5, 2019, 11:34:32 PM1/5/19
to CodenameOne Discussions
Hi,
what isn't working?
is it calling you too often or something else?

rdvg...@gmail.com

unread,
Jan 6, 2019, 1:13:56 AM1/6/19
to CodenameOne Discussions
HI,

It seems that nothing has changed because it constantly repeats the GPS call about one second at a time.

Shai Almog

unread,
Jan 6, 2019, 10:25:24 PM1/6/19
to CodenameOne Discussions
In the simulator or a device?

Notice that these are hints to the GPS. You might get more events depending on the strategy for location polling. Your device tracks where you are all the time and very rarely uses the GPS as it works well only with a clear sky. So you might get a lot of events but no battery drain. You can ignore these events and only access the data once every 15 minutes if that's what you want.

rdvg...@gmail.com

unread,
Jan 7, 2019, 9:54:35 PM1/7/19
to CodenameOne Discussions
Hi,

In the simulator and in the device, the same problem occurs.
   I thank you if you have a suggestion to solve this.

In the middle of my desperation I made another code that in the simulator is repeated in the exact time, but in the device it is only executed once.

        UITimer uit = new UITimer(() -> {
            if (iDt.getPrimeraVez()) {
                iDt.setLocation(LocationManager.getLocationManager().getCurrentLocationSync());
                iDt.setPrimeraVez(false);
            }
            Location loc = LocationManager.getLocationManager().getCurrentLocationSync();
            adicionTransaccion(loc, iDt.getLocation(), sesion);
            iDt.setLocation(loc);
        });

        Button btGps = new Button("GPS");
        btGps.addActionListener((e) -> {
            iDt.setPrimeraVez(true);
            sesion = System.currentTimeMillis();
            uit.schedule(1000 * 60 * TIEMPO_CLICLO_LECTURA_GPS, true, Display.getInstance().getCurrent());
        });

Going back to the beginning ... How do I make it work?

Shai Almog

unread,
Jan 7, 2019, 10:41:15 PM1/7/19
to CodenameOne Discussions
Hi,
getLocationSync will consume more battery than the listener approach as it binds/unbinds the listener. I don't understand the problem with ignoring overly verbose event callbacks?
Why can't you just use an if statement in the listener?

Notice you can set the location listener to null if you want to remove it so you can remove it once you get a location and re-add it 15 minutes later.

rdvg...@gmail.com

unread,
Jan 8, 2019, 9:32:47 AM1/8/19
to CodenameOne Discussions
Hi,

I did another test by simplifying the code as much as possible and placing the listener in a minute and in each cycle let a sound occur.
Both the simulator and the device repeat the reading in approximately one second.
Step to copy the simplified code and I appreciate being told that I am doing wrong.

    private void geoLocalizacion() {
        localizacionConductor = new Localizacion();
        LocationManager.getLocationManager().setLocationListener(localizacionConductor, new LocationRequest(LocationRequest.PRIORITY_MEDIUM_ACCUARCY, 1 * 6000));
    }

    class Localizacion implements LocationListener, Runnable {

        private boolean activo = true; 
        private int status;

        public Localizacion() {
            super();
        }

        public void inactivaRastreo() {
            this.activo = false;
        }

        public void activaRastreo() {
            this.activo = true;
        }

        public void locationUpdated(Location loc) {
            while (activo) {
                reproduceSonido("/lectura.wav");
            }
        }

        @Override
        public void providerStateChanged(int newState) {
            // check for unavailable errors etc.
            status = newState;
        }

        public void run() {
            while (activo) {
                try {
                    Thread.sleep(10000); 
                } catch (InterruptedException err) {
                    Dialog.show("Error", "No se pudo ejecutar la lectura del GPS", "Continuar", null);
                    activo = false;
                }
            }
        }
    }

rdvg...@gmail.com

unread,
Jan 8, 2019, 2:33:45 PM1/8/19
to CodenameOne Discussions
Hi,

Change the activation code of the gps in the following way:

    private void geoLocalizacion() {
        sesion = System.currentTimeMillis();
        localizacionConductor = new Localizacion(sesion);
        LocationManager.getLocationManager().setLocationListener(localizacionConductor, new LocationRequest(LocationRequest.PRIORITY_MEDIUM_ACCUARCY, iUr.getTiempoGps() * 6000));
        uit = new UITimer(() -> {
            if (localizacionConductor != null) {
                localizacionConductor.activaLectura();
            }
        });
        uit.schedule(6000 * iUr.getTiempoGps(), true, Display.getInstance().getCurrent());
    }

This works very well but I am worried about the battery wear as the listener of the location runs every second, additional there is a new thread that is also running. Is there another way to implement this?

rdvg...@gmail.com

unread,
Jan 8, 2019, 6:49:45 PM1/8/19
to CodenameOne Discussions
Hi,

Again change the code of the location, timing the update of my tables to "n" minutes. In the simulator this works well. In the device I have the problem that every time the device goes into power saving the screen turns off and the GPS cycle also stops working.
I appreciate any support.

My new change:

    class Localizacion implements LocationListener, Runnable {

        private boolean activo = true; // Indicador del estado de la clase GPSLoc
        private int status;
        private long sesion;
        private Location loc2;
        private boolean primeraVez = true;
        private long tiempoTranscurrido;
        private long CicloGps;

        public Localizacion(long sesion, long CicloGps) {
            super();
            this.sesion = sesion;
            this.CicloGps = CicloGps;
            tiempoTranscurrido = System.currentTimeMillis();
        }

        public void activaLectura() {
            this.activo = true;
        }

        public void locationUpdated(Location loc) {

            long t = System.currentTimeMillis();
            System.out.println("Tiempo Trans: " + tiempoTranscurrido + " Tiempo Actual: " + t);
            System.out.println("Diferencia: " + Long.toString(t - tiempoTranscurrido));
            System.out.println("CicloGPS: " + Long.toString(CicloGps));
            if (t - tiempoTranscurrido >= CicloGps) {
                if (primeraVez) {
                    loc2 = loc;
                    primeraVez = false;
                }
                adicionTransaccion(loc, loc2, sesion);
                loc2 = loc;
                tiempoTranscurrido = t;
            }
        }

        @Override
        public void providerStateChanged(int newState) {
            // check for unavailable errors etc.
            status = newState;
        }

        public void run() {
            while (activo) {
                try {
                    Thread.sleep(10000); // Después de cumplir este tiempo se envia el error

Shai Almog

unread,
Jan 8, 2019, 10:52:02 PM1/8/19
to CodenameOne Discussions
Hi,
if you need location information while the app is in the background this isn't the way to go at all. I still have no idea what you are trying to accomplish.
The original listing I mentioned will keep the battery usage low, the fact that it will invoke you more frequently is irrelevant.  You can further reduce accuracy to reduce battery usage.

For background GPS usage check out the developer guide here: https://www.codenameone.com/manual/misc-features.html under "Location In The Background - Geofencing".

rdvg...@gmail.com

unread,
Jan 8, 2019, 11:28:52 PM1/8/19
to CodenameOne Discussions
Hi,

First I want to apologize for so many post in a row.
Detect that I set a time of "n" * 6000 which made the listener very fast.
I corrected the code and put it to repeat for a minute.
I try to load a table with the GPS data every time the indicated time is reached.

imagen.png


The attached image shows 5 transactions. The first 2 show a difference of about one minute, which for me is quite good. After the second registration, the device entered energy saving mode and the screen went off. From that moment on, the following transactions were recorded at an average of 10 minutes apart.
How do I keep the transactions recording in the time I need?

    private void geoLocalizacion() {
        sesion = System.currentTimeMillis();
        localizacionConductor = new Localizacion(sesion);
        LocationManager.getLocationManager().setLocationListener(localizacionConductor, new LocationRequest(LocationRequest.PRIORITY_MEDIUM_ACCUARCY, iUr.getTiempoGps() * 60 * 1000));
    }

Shai Almog

unread,
Jan 9, 2019, 10:39:10 PM1/9/19
to CodenameOne Discussions
Hi,
no problem.

In the location listener just add a threshold of time and assume you will be invoked more than once. Just save the updated location and use a 15 minute timer to save to the database if location changed.

rdvg...@gmail.com

unread,
Jan 10, 2019, 2:29:31 PM1/10/19
to CodenameOne Discussions
Hi,
Thanks for answering. I did another test.
Run the LocationManager in the following way (do not set repeat time):

           LocationManager.getLocationManager (). SetLocationListener (localizacionConductor);

The attached image shows the results executed from a Samsung J7 device.
The red box shows the last transactions from the beginning of the process until before the device arrives as an energy saving (difference of approximately one second between each record).
The yellow box shows the transaction at the moment when the screen is black (difference of 2 seconds with respect to the previous record).
The blue box shows the transactions in energy saving mode "black screen" (11-minute difference approximately).
The green box shows the transactions after you activate the device and pass the application to the foreground (difference of one second).

imagen.png


My app must allow to identify every 15 minutes (it may be another time according to the client's decision) the user's location. My headache is in the transactions of the blue box, because surely my app will spend more time in energy saving mode and I will have impressions when reporting the location.

How do I correct this situation?

Shai Almog

unread,
Jan 10, 2019, 10:24:49 PM1/10/19
to CodenameOne Discussions
Hi,
as I explained before. If you want to run when the app is in the background you need to use background location which is a completely different thing...
Location doesn't work as one value. It constantly refines itself even when you don't move by taking input from multiple sensors (not just GPS). So you'd get noisy events. The events in the blue box are once ever 11 minutes and you wanted events once every 15 minutes so I don't see the problem.

Reply all
Reply to author
Forward
0 new messages