0

I've stored latitude and longitude value into my sqlite table. Eg: latitude = 16.840064 and longitude = 96.120286.My question is how can I check and retrieve data from sqlite database for nearest location based on device current GPS location?

PPShein
  • 13,309
  • 42
  • 142
  • 227
  • http://stackoverflow.com/questions/3695224/android-sqlite-getting-nearest-locations-with-latitude-and-longitude ? – Blackbelt Jun 13 '13 at 08:40

3 Answers3

1

The best thing you could do is using a Haversine formula (http://en.wikipedia.org/wiki/Haversine_formula) in your query.

This accepted answer seems to be your question, so take a look there: SQlite Getting nearest locations (with latitude and longitude)

Community
  • 1
  • 1
Marco Veenendaal
  • 186
  • 1
  • 12
1

Whlile The answer given already (Harversine formula) is correct, but may be I simpler solution works for you: I am using this solution to reverse geocode the nearest airfield for the given position (used in a flight logger application of mine):

  1. query the database for all rows where the coordinated of the location stored in the row are 0.1 degrees smaller or larger than the given solution. This is about 11 km to either side at the equator and about 6 km in Germany.

  2. For each element answered for the above query compute the distance to the given location. If there is none try a larger range for the query (e.g. 0.5 degrees).

  3. Answer the element with minimal distance

For my application step one answers only one row, because airfields usually are distributed rather sparsely.

EDIT Here is some code from the content provider, the location is part of the query URI

@Override
public Cursor query(final Uri uri, final String[] projection, final String selection, final String[] selectionArgs, String sortOrder) {
    String pathSegment;
    Location loc;
    Object[] result;
    MatrixCursor result_cursor;
    final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
    qb.setTables(AirfieldsTable.TABLE_NAME);

    final SQLiteDatabase dbCon = this.db.getReadableDatabase();
    switch( URI_MATCHER.match(uri) ) {
    // ... the location is encoded in the URI used to query the provider
    case NRST_AIRFIELD:
        pathSegment = uri.getPathSegments().get(1);
        if( DEBUG )
            Log.d( TAG, "Query nearest airfield: " + pathSegment);
        loc = this.parsePosition(pathSegment);
        if( loc == null )
            return null;
        // try a range query first
        result = this.rangeQuery(dbCon, loc.getLatitude(), loc.getLongitude());
        if( result == null )
            // range query had no hits, try a full table scan
                            // **Here you could enlarge the range as suggested in the text before the EDIT**
            return this.nearestBruteForce(dbCon, loc.getLatitude(), loc.getLongitude());

        result_cursor = new MatrixCursor(AirfieldsTable.allColumnNames());
        result_cursor.addRow(result);
        return result_cursor;
    // ...
    default:
        throw new IllegalArgumentException("Unknown URI: " + uri);
    }
}

And here is the range query:

/**
 * Query the airfields table for airfields near the given position.
 * @param dbCon DB connection
 * @param ref_lat latitude
 * @param ref_lon longitude
 * @return Answer the airfield nearest to the given position as array
 *          of objects: id, designator, latitude, longitude.
 *          Answer <code>null</code> if their is no airfield near the
 *          given position plus or minus 0.1 degrees.
 */
private Object[] rangeQuery(final SQLiteDatabase dbCon, final double ref_lat, final double ref_lon) {
    if( DEBUG )
        Log.d( TAG, "rangeQuery lat=" + ref_lat + ", lon=" + ref_lon);
    final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
    qb.setTables(AirfieldsTable.TABLE_NAME);
    final String[] whereArgs = new String[] {
            Double.toString(ref_lat - 0.1d), Double.toString(ref_lat + 0.1d),
            Double.toString(ref_lon - 0.1d), Double.toString(ref_lon + 0.1d)
    };
    final Cursor crsr = qb.query(dbCon, allFields(), AirfieldsTable.RANGE_CLAUSE, whereArgs, null, null, null);
    final Object[] val = this.scanForNearest(crsr, ref_lat, ref_lon);
    crsr.close();
    if( DEBUG )
        Log.d( TAG, "scanForNearest returned " + val);
    return val;
}

And here is the search for the airfield of minimum distance:

/**
 * Select the airfield nearest to the given position from the
 * given cursor.
 * @param crsr a cursor
 * @param ref_lat latitude
 * @param ref_lon longitude
 * @return Answer the airfield nearest to the given position as array
 *          of objects: id, designator, latitude, longitude.
 *          Answer <code>null</code> if the cursor is empty.
 */
private Object[] scanForNearest(final Cursor crsr, final double ref_lat, final double ref_lon) {
    String designator = null;
    long id = -1;
    double lat = 0.0f, lon = 0.0f, dist = Float.MAX_VALUE;
    int ctr = 0;
    final float[] results = new float[1];
    if( ! crsr.moveToFirst() ) {
        if( DEBUG )
            Log.d( TAG, "scan for nearest with empty cursor");
        return null;
    }
    do {
        ctr += 1;
        final double tmp_lat = crsr.getDouble(AirfieldColumns.IDX_LATITUDE);
        final double tmp_lon = crsr.getDouble(AirfieldColumns.IDX_LONGITUDE);
        Location.distanceBetween(tmp_lat, tmp_lon, ref_lat, ref_lon, results);
        final float tmp_dist = results[0];
        if( tmp_dist < dist ) {
            // first element or nearer element
            designator = crsr.getString(AirfieldColumns.IDX_DESIGNATOR);
            id = crsr.getLong(AirfieldColumns.IDX_ID);
            lat = tmp_lat;
            lon = tmp_lon;
            dist = tmp_dist;
        }
    } while( crsr.moveToNext() );
    if( DEBUG )
        Log.d( TAG, "nearest is " + designator + ", dist=" + dist + ", ctr=" + ctr + ", id=" + id);
    final Object[] val = {
            id,
            designator,
            lat,
            lon };
    return val;
}

nearestBruteForce() is straightforward: Get a cursor from a full table scan and call scanForNearest().

Stefan
  • 4,645
  • 1
  • 19
  • 35
0
Location.distanceTo (Location locationFromDb)

Looks like you will need to create a Location object out of each of the entries in your database and use the above function

Rohan
  • 428
  • 5
  • 10