entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

1voto

Android: Clase generica para la localización

Hola.

En mi aplicación mas de una Activity necesita conocer la ubicación actual del usuario y en base a ese dato realiz distintas acciones (dependiendo de la activity).

El caso es que me gustaría no tener que estar escribiendo continuamente el código y he pensado que lo mejor sería realizar una clase la cual se encargue de la localización. Pero en este apartado estoy un poco bloqueado.

Por ejemplo, para algo parecido pero con las bases de datos Google nos indica que debemos de crear una nueva clase que extienda de SQLiteOpenHelper (o por lo menos así lo entiendo y así lo hago).

Para la localización como me aconsejáis que lo plantee?

Saludos.

3 Respuestas

2votos

egoitz_gonzalez Puntos10050

Creo que la respuesta exacta que buscaba es la siguiente. Es una clase usada en el código de appunta aunque hay algunas cosas que no las entiendo bien, el código funciona.

/***
 * This class is a helper to work with the Location Providers (both GPS and
 * Network)
 * 
 * @author Sergi Mart�nez
 * 
 */

public class LocationReader implements LocationListener {
    private LocationManager locManager;
    private Context context;
    private boolean gpsProviderActive = false;
    private boolean networkProviderActive = false;
    private OnLocationObtainedListener onLocationObtainedListener;
    private OnNoProvidersListener onNoProvidersListener;

    /**
     * Class constructor, it needs the current context in order to work with the
     * services
     * 
     * @param context
     *            The current context
     */
    public LocationReader(Context context) {
        this.context = context;
    }

    /***
     * Class constructor that allows stablish if the server should start or not
     * 
     * @param context
     *            The current context
     * @param start
     *            A value indicating if the service should start automatically
     *            or not
     */
    public LocationReader(Context context, boolean start) {
        this.context = context;
        if (start) {
            start();
        }

    }

    /***
     * This method starts the subscription to the location providers (both GPS
     * and Network)
     */
    public void start() {

        gpsProviderActive = true;
        networkProviderActive = true;
        loadLocationManager(); 
        locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 5,
                this);

        locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000,
                5, this);

    }

    /**
     * Loads the LocationManager service into locManager if not loaded previously
     */
    private void loadLocationManager() {
        if (locManager == null) {
            locManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        }
    }

    /**
     * Removes all subscriptions
     */
    public void stop() {
        locManager.removeUpdates(this);
    }

    /**
     * Gets the current status for the GpsProvider flag
     * 
     * @return A boolean value indicating if GPS is active
     */
    public boolean isGpsProviderActive() {
        return gpsProviderActive;
    }

    /**
     * Sets the flag of the current GPS status
     * 
     * @param gpsProviderActive
     *            A boolean value indicating if GPS is active
     */
    private void setGpsProviderActive(boolean gpsProviderActive) {
        this.gpsProviderActive = gpsProviderActive;
    }

    /**
     * Gets the current status for the NetworkProvider flag
     * 
     * @return A boolean value indicating if NEtwork is active
     */
    public boolean isNetworkProviderActive() {
        return networkProviderActive;
    }

    /**
     * Sets the flag of the current Netowork status
     * 
     * @param networkProviderActive
     *            A boolean value indicating if Network is active
     */
    private void setNetworkProviderActive(boolean networkProviderActive) {
        this.networkProviderActive = networkProviderActive;
    }

    /***
     * 
     * @return The current onNoProviders Listener
     */
    public OnNoProvidersListener getOnNoProvidersListener() {
        return onNoProvidersListener;
    }

    /**
     * Sets a listener to throw when no providers are working
     * 
     * @param onNoProvidersListener
     */
    public void setOnNoProvidersListener(
            OnNoProvidersListener onNoProvidersListener) {
        this.onNoProvidersListener = onNoProvidersListener;
    }

    /**
     * 
     * @return the current onLocationObtainedLister
     */
    public OnLocationObtainedListener getOnLocationObtainedListener() {
        return onLocationObtainedListener;
    }

    /**
     * Sets a listener to warn when location is obtained
     * 
     */
    public void setOnLocationObtainedListener(
            OnLocationObtainedListener onLocationObtainedListener) {
        this.onLocationObtainedListener = onLocationObtainedListener;
    }

    @Override
    public void onLocationChanged(Location loc) {
        if (onLocationObtainedListener != null) {
            onLocationObtainedListener.onLocationObtained(loc);
        }

    }

    /**
     * Gets the las location received by the phone, whatever the provider is
     * @return
     *      The last known location 
     */
    public Location getLastKnownLocation() {
        loadLocationManager();
        List<String> providers = locManager.getProviders(true);

        /*
         * Loop over the array backwards, and if you get an accurate location,
         * then break out the loop
         */
        Location lastLocation = null;

        for (int i = providers.size() - 1; i >= 0 && lastLocation==null; i--) {
            lastLocation = locManager.getLastKnownLocation(providers.get(i));
        }

        return lastLocation;
    }

    @Override
    public void onProviderDisabled(String provider) {
        if (LocationManager.GPS_PROVIDER.equals(provider)) {
            setGpsProviderActive(false);
        }
        if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
            setNetworkProviderActive(false);
        }
        if (!isNetworkProviderActive() && !isGpsProviderActive()
                && onNoProvidersListener != null) {
            onNoProvidersListener.onNoProviders();
        }
    }

    @Override
    public void onProviderEnabled(String provider) {
        if (LocationManager.GPS_PROVIDER.equals(provider)) {
            setGpsProviderActive(true);
        }
        if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
            setNetworkProviderActive(true);
        }
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

    /**
     * This interface should implemented in order to receive new locations
     * 
     * @author Sergi Mart�nez
     * 
     */
    public interface OnLocationObtainedListener {
        /**
         * This listener is called when we receive a location from any provider
         * 
         * @param loc
         *            The location received
         */
        public void onLocationObtained(Location loc);

    }

    /**
     * This interface should be implemented in order to receive a warning when
     * no providers are working
     * 
     * @author Sergi Mart�nez
     * 
     */
    public interface OnNoProvidersListener {
        /**
         * This listener is called when no providers are working
         */
        public void onNoProviders();
    }

}

Para usar esta clase en cualquier sitio de la aplicación es muy sencillo. Creamos una instancia de la clase LocationReader

locReader = (LocationReader) new LocationReader(this, true);

            OnLocationObtainedListener locationObtainedListener = new OnLocationObtainedListener() {

                @Override
                public void onLocationObtained(Location loc) {
                    // TODO Auto-generated method stub
                    mostrarPosicion(loc);
                }
            };
locReader.setOnLocationObtainedListener(locationObtainedListener);

Me cuesta entender la lógica que existe entre OnLocationObtainedListener y onLocationChanged. Tal vez alguien nos lo pueda explicar.

0voto

Peter comentado

Por favor seleccionala como correcta si lo es.

Saludos.

4votos

Hola que tal pues te puedo mostrar una clase que yo eh utilizado en mis proyectos de pruebas... esta muy completa y muy bien explicada... Pero en tu pregunta algo me causa ruido, no se si sea factible estar obteniendo la localización cada vez que cambias de activity en cuanto al gasto de datos, pero bueno eso es otra historia.. te dejo el link del tutorial:

Cuando quieras Llamar la clase solo tienes que hacer esto desde tu activity:

gps = new GPSTracker(tuActivity.this);

y puedes acceder al objeto de esta manera:

double latitude = gps.getLatitude();
double longitude = gps.getLongitude();

LINK
http://www.androidhive.info/2012/07/android-gps-location-manager-tutorial/

0voto

egoitz_gonzalez comentado

Gracias. Justo después de escribir la pregunta encontré la web que mencionas.

Sobre lo que te causa ruido. No entiendo muy bien el porque. Es decir. En mi app hay Activitys que necesitan la localización del usuario y hay otras que no. Cuando digo que mas de una activity debe de realizar la localizaciópn me refiero por si se da el siguiente caso.

1- En usuario entra a una Activity que requiere de localización.
2- El usuario sale de esa Activity y entra en una que no necesita la localización.
3- después de unos minutos a pie o en coche, el usuario entra a una tercera Activity (o a la primera) que sí necesita localización.

Ese es un caso que se puede dar en mi app. Que opinión te merece?

Gracias y saludos!

0voto

Novus Ordo Seclorum comentado

Pues de echo.. ahora que lo pienso bien ,todas las aplicaciones que usan geolocation son muy dadas a gastar "considerablemente" los datos.. y para mi esta correctamente planteada la lógica de tu aplicación, pero que pasa si estas en la misma Acftivity y te has movido en el carro ya 5km, en teoría aperecerias en el mismo lugar que cuando abriste el activity.. Debes idear alguna manera de hacer un refresh cada cierto tiempo.

0voto

egoitz_gonzalez comentado

Claro. Ahí es donde tengo duda a la hora de realizar una clase genérica. Sin la clase genérica es sencillo. Llamando al método requestLocationUpdate el cual recibe 4 parámetros. (Nombre del proveedor de localización, Tiempo en milisegundos entre actualizaciones, distancia en metros entre actualizaciones e instancia de un objeto LocationListener ). Por ejemplo:

locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,this);

Después, usando el método onLocationChanged del obejto LocationListener programamamos lo que deseamos realizar.

La duda es, como implementar este método si la clase de localización es genérica y cada activity realiza una acción distinta a la hora de registrarse un cambio de posición.

Se debería de instanciar un objeto LocationListener en cada activity?

0voto

Novus Ordo Seclorum comentado

así es como dices deberías implementar en cada Activity

NombreClase extends Activity implements LocationListener

para poder hacer uso de los métodos propios de esa interface.

te dejo un link que lo explica mas detalladamente

http://androidexample.com/GPS_Basic__-__Android_Example/index.php?view=article_discription&aid=68&aaid=93

0voto

así es como dices deberías implementar en cada Activity

NombreClase extends Activity implements LocationListener

para poder hacer uso de los métodos propios de esa interface.

te dejo un link que lo explica mas detalladamente

http://androidexample.com/GPS_Basic__-__Android_Example/index.php?view=article_discription&aid=68&aaid=93

0voto

egoitz_gonzalez comentado

Sí pero justo eso es lo que hace GPSTracker.java. Estas sobrescribiendo código con lo cual no consigues lo que yo deseo. Que es tener una única clase dedicada a la localización.

0voto

Novus Ordo Seclorum comentado

Lo que se me ocurre y que yo aria en este caso es usar la clase que te pase en el primer link, y usar un AsyncTask para estar ejecutando en background la petición de las coordenadas cada cierto tiempo..

Así podrías estar refrescando mientras te muestres inactivo en tu Activity.

de esta manera ejecutarias el AsyncTask cada determinado tiempo:

http://stackoverflow.com/questions/18025686/running-an-asynctask-on-a-set-interval

y esta es la forma en que se usa el Asynctask:

http://www.sgoliver.net/blog/?p=3099

http://developer.android.com/reference/android/os/AsyncTask.html

http://androideity.com/2011/09/21/trabajando-con-threads-en-android-iii/

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta