How to get the points of the coordinates near me on android?

7

I have an android application that has some georeferenced points and shows certain points that the user requests with a spinner, it is a query to the local base. The question is: How to show the points that are within a radius of 1km from my location?

criaderosMap = criaderoDao.queryBuilder()
                .where(CtlPlCriaderoDao.Properties.Latitud.isNotNull()).list();

That code brings me all the points of the Database, there I could filter by a field that is related but I need to consult the nearby ones in 1 km.

I would think it could be done with a between.

    
asked by Igmer Rodriguez 14.09.2018 в 23:58
source

5 answers

9

A way to filter them can be from the query SQL and get those that are less than 1000 meters away ( distance < 1000 ):

select
    latitud ,
    longitude,
    ( 3959 * acos(  cos( radians(37) )
                  * cos( radians( latitud ) )
                  * cos( radians( longitude) - radians(YourLongitude) )
                  + sin( radians(YourLatitude) ) * sin( radians( latitud ) )
                 )
    ) AS distance
FROM
    ctlCriadero
HAVING
    distance < 1000 
ORDER BY
    distance
LIMIT
    0 , 50

Also by means of Android SDK you can also make the comparison of the geolocation values by means of the method distanceTo ()

    //Device Location
    Location locationDevice = new Location("Android Device Location.");
    locationDevice.setLatitude(deviceLatitude);
    locationDevice.setLongitude(deviceLongitude);
    //Location to compare
    Location locationValue = new Location("location value.");
    locationValue.setLatitude(rLatitude); //Latitud
    locationValue.setLongitude(rLongitude); //Longitud

    //Obtiene distancia en metros.
    float distanceInMeters =  locationDevice.distanceTo(locationValue);

This would be an example,

where the comparePrintInfo() method performs the comparison to print which locations are in the range of one kilometer.

You must modify the getListOfPostitions() method to obtain the list of positions to compare, probably from a service.

import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Locale;

public class MainActivity extends AppCompatActivity implements LocationListener {

    private static final String TAG = "MainActivity";
    private static final int ONE_KM = 1000; //1 km

    private static final long MIN_TIME_BETWEEN_UPDATES = 1000 * 60 * 1; // 1 minute.
    private static final long MIN_DISTANCE_FOR_UPDATES = (long) 1.5; // 1.5 meters
    private LocationManager mLocationManager;
    private ArrayList<Address> listOfGeoPositions;
    private TextView myTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myTextView = findViewById(R.id.myTextView);
        mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            //    ActivityCompat#requestPermissions
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 225);
        }else{

            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BETWEEN_UPDATES,
                    MIN_DISTANCE_FOR_UPDATES, this);
            mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BETWEEN_UPDATES,
                    MIN_DISTANCE_FOR_UPDATES, this);

            Location location = mLocationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
            comparePrintInfo(location);

        }


    }


    @Override
    public void onLocationChanged(Location location) {
        Log.i(TAG, "onLocationChanged Latitude: " + location.getLatitude() + " Longitude: " + location.getLongitude());

        comparePrintInfo(location);
    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {
        Log.i(TAG, "onStatusChanged("  + s +")");
    }

    @Override
    public void onProviderEnabled(String s) {
        Log.i(TAG, "onProviderEnabled("  + s +")");
    }

    @Override
    public void onProviderDisabled(String s) {
        Log.i(TAG, "onProviderDisabled("  + s +")");
    }

    //This method uses distanceTo() that returns the approximate distance in meters between this location and the given location.
    private float getDistance(double deviceLatitude, double deviceLongitude, double rLatitude, double rLongitude){

        //Device Location
        Location locationDevice = new Location("Android Device Location.");
        locationDevice.setLatitude(deviceLatitude);
        locationDevice.setLongitude(deviceLongitude);
        //Location to compare
        Location locationValue = new Location("location value.");
        locationValue.setLatitude(rLatitude); //Latitud
        locationValue.setLongitude(rLongitude); //Longitud

        //distanceTo()
        //https://developer.android.com/reference/android/location/Location.html#distanceTo(android.location.Location)
        //Returns the approximate distance in meters between this location and the given location.
        return locationDevice.distanceTo(locationValue);
    }

    /*TODO: Jorgesys, * Very important to change this method to get your geolocation points to be compared with the position of your device*/
    private ArrayList<Address> getListOfPostitions(){

        listOfGeoPositions = new ArrayList<Address>();
        Address geoPosition;
        geoPosition = new Address(Locale.getDefault());
        geoPosition.setFeatureName("Palas Ice Skating Rink.");
        geoPosition.setLatitude(47.156116);
        geoPosition.setLongitude(27.5864219);
        listOfGeoPositions.add(geoPosition);
        geoPosition = new Address(Locale.getDefault());
        geoPosition.setFeatureName("Gradina publica IASI.");
        geoPosition.setLatitude(25.6723275);
        geoPosition.setLongitude(-100.3101152);
        listOfGeoPositions.add(geoPosition);
        geoPosition = new Address(Locale.getDefault());
        geoPosition.setFeatureName("Platz Bierhaus.");
        geoPosition.setLatitude(25.667943);
        geoPosition.setLongitude(-100.3103716);
        listOfGeoPositions.add(geoPosition);
        geoPosition = new Address(Locale.getDefault());
        geoPosition.setFeatureName("Palatul Cultura.");
        geoPosition.setLatitude(47.1557913);
        geoPosition.setLongitude(27.5861617);
        listOfGeoPositions.add(geoPosition);
        geoPosition = new Address(Locale.getDefault());
        geoPosition.setFeatureName("Equestrian statue of Stefan cel Mare.");
        geoPosition.setLatitude(47.1573927);
        geoPosition.setLongitude(27.5863307);
        listOfGeoPositions.add(geoPosition);

        return listOfGeoPositions;
    }


    private void comparePrintInfo(Location deviceLocation){

        //Get positions to compare with Device position.
        //The method getListOfPostitions() must have the query to get the locations to compare with the device location.
        listOfGeoPositions = getListOfPostitions();
        //Print info.
        String myData= "";
        myData += "<font color=#6ef442>Android</font> Device position:<br><b>Downtown IASI.</b><br>Latitude: " + deviceLocation.getLatitude() + " Longitude: " + deviceLocation.getLongitude() + "<br><br>";
        float distance;
        for(int i = 0 ;i<listOfGeoPositions.size();i++) {
            distance = getDistance(deviceLocation.getLatitude(), deviceLocation.getLongitude(), listOfGeoPositions.get(i).getLatitude(), listOfGeoPositions.get(i).getLongitude());
            Log.i(TAG, "Distance calculated: " + distance);
            if(distance < ONE_KM) {
                myData += "<b>" + listOfGeoPositions.get(i).getFeatureName() + "</b><br>latitude: " + listOfGeoPositions.get(i).getLatitude() + ", longitude: " + listOfGeoPositions.get(i).getLongitude() +"<br><font color=#0000FF>Distance in range : " + distance + " mts.</font><br>";
            }else{
                myData += "<b>" +listOfGeoPositions.get(i).getFeatureName() + "</b><br>latitude: " + listOfGeoPositions.get(i).getLatitude() + ", longitude: " + listOfGeoPositions.get(i).getLongitude() +"<br><font color=#FF0000>Distance out of range : " + distance + " mts.</font><br>";
            }
        }
        myTextView.setText(Html.fromHtml(myData));

    }

}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/myTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Compare locations to device position!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>
    
answered by 19.09.2018 / 18:29
source
5

Android has a Location class that allows you, among other things, to calculate the distance between two points.

The method that will help you in your case is distanceTo that returns the distance in meters between two points. Here you have an example of this class in action:

Location madrid = new Location(40.416775, -3.703790); //Centro de Madrid
Location laLatina = new Location(40.411804, -3.708070); //Metro La Latina, Madrid
Location barcelona = new Location(41.385063, 2.173404); // Centro de Barcelona
double distMax = 1000; // 1KM en metros

if( madrid.distanceTo( laLatina ) <= distMax ){
    System.out.println("La distancia entre el centro de Madrid y la Latina es de 1KM ou menos");
}

if( madrid.distanceTo( barcelona ) > distMax ){
    System.out.println("La distancia entre el centro de Madrid y Barcelona es de más de 1KM");
}
    
answered by 17.09.2018 в 17:39
1

The closest thing I could find and work is the following:

 select nombre,
        latitud ,
        longitud,
        ( 3959 * acos(  cos( radians(37) )
              * cos( radians( latitud ) )
              * cos( radians( longitud) - radians(-89.29239250) )
              + sin( radians(13.67259696) ) * sin( radians( latitud ) )
             )
) AS distance
FROM
ctl_establecimiento
   GROUP BY LATITUD
   HAVING
   distance < 3000

ORDER BY
distance
 LIMIT
  0 , 5

I have taken it from: English Stackoverflow

    
answered by 19.09.2018 в 15:41
1

The distanceBetween method can help you, it returns the distance in meters between two points. You just have to iterate between the list and the starting point.

void distanceBetween(double lat1, double lon1, double lat2, double lon2, float[] results)

The method calculates the approximate distance in meters between two locations, and optionally the initial and final links of the shortest path between them.

Reference:

link

    
answered by 19.09.2018 в 17:59
0

First, bring all the markers from your database, then calculate the distance between one marker and another with the following code:

 public static double calcularDistancia(LatLng a, LatLng b) {
    if (a != null && b != null) {
        // pasamos las diferencias de las coordenadas a radianes
        double difLat = toRadianes(b.latitude - a.latitude);
        double difLong = toRadianes(b.longitude - a.longitude);

        double dato1 = Math.sin(difLat / 2) * Math.sin(difLat / 2) + Math.cos(toRadianes(a.latitude)) *
                Math.cos(toRadianes(b.latitude)) * Math.sin(difLong / 2) * Math.sin(difLong / 2);

        double dato2 = 2 * Math.atan2(Math.sqrt(dato1), Math.sqrt(1 - dato1));

        double dato3 = RADIO_TIERRA * dato2;

        Log.v(TAG, "Resutlado final (metros) " + dato3 * 1000);

        return dato3 * 1000;// lo pasamos a metros
    }

    return 0.0;// si a y b son nulos
}

private static double toRadianes(double coord) {
    return ((coord * Math.PI) / 180);
}

And to finish what you do is ask:

if(calcularDistancia(miposicion,mipunto)=>1000){
//aqui llamas la funcion markeroption y le pasas como parametro de newLatLng mi punto

}

Certainly if you do not know how to traverse your points, use a for and with the if you will compare. So you can show all the points in 1km around.

    
answered by 19.09.2018 в 17:00