/*
* Geopaparazzi - Digital field mapping on Android based devices
* Copyright (C) 2016 HydroloGIS (www.hydrologis.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.geopaparazzi.core.database;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import android.graphics.drawable.Drawable;
import android.util.Log;
import org.mapsforge.android.maps.overlay.OverlayItem;
import org.mapsforge.core.model.GeoPoint;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import eu.geopaparazzi.library.database.GPLog;
import eu.geopaparazzi.library.database.IImagesDbHelper;
import eu.geopaparazzi.library.database.Image;
import eu.geopaparazzi.library.images.ImageUtilities;
import eu.geopaparazzi.core.GeopaparazziApplication;
import static eu.geopaparazzi.core.database.TableDescriptions.ImageDataTableFields;
import static eu.geopaparazzi.core.database.TableDescriptions.ImageTableFields;
import static eu.geopaparazzi.core.database.TableDescriptions.TABLE_IMAGES;
import static eu.geopaparazzi.core.database.TableDescriptions.TABLE_IMAGE_DATA;
/**
* Data access object for images.
*
* @author Andrea Antonello (www.hydrologis.com)
*/
@SuppressWarnings("nls")
public class DaoImages implements IImagesDbHelper {
/**
* Create the image tables.
*
* @throws IOException if something goes wrong.
*/
public static void createTables() throws IOException {
StringBuilder sB = new StringBuilder();
sB.append("CREATE TABLE ");
sB.append(TABLE_IMAGES);
sB.append(" (");
sB.append(ImageTableFields.COLUMN_ID.getFieldName());
sB.append(" INTEGER PRIMARY KEY AUTOINCREMENT, ");
sB.append(ImageTableFields.COLUMN_LON.getFieldName()).append(" REAL NOT NULL, ");
sB.append(ImageTableFields.COLUMN_LAT.getFieldName()).append(" REAL NOT NULL,");
sB.append(ImageTableFields.COLUMN_ALTIM.getFieldName()).append(" REAL NOT NULL,");
sB.append(ImageTableFields.COLUMN_AZIM.getFieldName()).append(" REAL NOT NULL,");
sB.append(ImageTableFields.COLUMN_IMAGEDATA_ID.getFieldName());
sB.append(" INTEGER NOT NULL ");
sB.append("CONSTRAINT " + ImageTableFields.COLUMN_IMAGEDATA_ID.getFieldName() + " REFERENCES ");
sB.append(TABLE_IMAGE_DATA);
sB.append("(");
sB.append(ImageDataTableFields.COLUMN_ID);
sB.append(") ON DELETE CASCADE,");
sB.append(ImageTableFields.COLUMN_TS.getFieldName()).append(" DATE NOT NULL,");
sB.append(ImageTableFields.COLUMN_TEXT.getFieldName()).append(" TEXT NOT NULL,");
sB.append(ImageTableFields.COLUMN_NOTE_ID.getFieldName()).append(" INTEGER,");
sB.append(ImageTableFields.COLUMN_ISDIRTY.getFieldName()).append(" INTEGER NOT NULL");
sB.append(");");
String CREATE_TABLE_IMAGES = sB.toString();
sB = new StringBuilder();
sB.append("CREATE INDEX images_ts_idx ON ");
sB.append(TABLE_IMAGES);
sB.append(" ( ");
sB.append(ImageTableFields.COLUMN_TS.getFieldName());
sB.append(" );");
String CREATE_INDEX_IMAGES_TS = sB.toString();
sB = new StringBuilder();
sB.append("CREATE INDEX images_x_by_y_idx ON ");
sB.append(TABLE_IMAGES);
sB.append(" ( ");
sB.append(ImageTableFields.COLUMN_LON.getFieldName());
sB.append(", ");
sB.append(ImageTableFields.COLUMN_LAT.getFieldName());
sB.append(" );");
String CREATE_INDEX_IMAGES_X_BY_Y = sB.toString();
sB = new StringBuilder();
sB.append("CREATE INDEX images_noteid_idx ON ");
sB.append(TABLE_IMAGES);
sB.append(" ( ");
sB.append(ImageTableFields.COLUMN_NOTE_ID.getFieldName());
sB.append(" );");
String CREATE_INDEX_IMAGES_NOTEID = sB.toString();
sB = new StringBuilder();
sB.append("CREATE INDEX images_isdirty_idx ON ");
sB.append(TABLE_IMAGES);
sB.append(" ( ");
sB.append(ImageTableFields.COLUMN_ISDIRTY.getFieldName());
sB.append(" );");
String CREATE_INDEX_IMAGES_ISDIRTY = sB.toString();
sB = new StringBuilder();
sB.append("CREATE TABLE ");
sB.append(TABLE_IMAGE_DATA);
sB.append(" (");
sB.append(ImageDataTableFields.COLUMN_ID.getFieldName());
sB.append(" INTEGER PRIMARY KEY AUTOINCREMENT, ");
sB.append(ImageDataTableFields.COLUMN_IMAGE.getFieldName()).append(" BLOB NOT NULL,");
sB.append(ImageDataTableFields.COLUMN_THUMBNAIL.getFieldName()).append(" BLOB NOT NULL");
sB.append(");");
String CREATE_TABLE_IMAGEDATA = sB.toString();
SQLiteDatabase sqliteDatabase = GeopaparazziApplication.getInstance().getDatabase();
if (GPLog.LOG_HEAVY)
Log.i("DAOIMAGES", "Create the images tables.");
sqliteDatabase.beginTransaction();
try {
sqliteDatabase.execSQL(CREATE_TABLE_IMAGES);
sqliteDatabase.execSQL(CREATE_INDEX_IMAGES_TS);
sqliteDatabase.execSQL(CREATE_INDEX_IMAGES_X_BY_Y);
sqliteDatabase.execSQL(CREATE_INDEX_IMAGES_NOTEID);
sqliteDatabase.execSQL(CREATE_INDEX_IMAGES_ISDIRTY);
sqliteDatabase.execSQL(CREATE_TABLE_IMAGEDATA);
sqliteDatabase.setTransactionSuccessful();
} catch (Exception e) {
Log.e("DAOIMAGES", e.getLocalizedMessage(), e);
throw new IOException(e);
} finally {
sqliteDatabase.endTransaction();
}
}
public long addImage(double lon, double lat, double altim, double azim, long timestamp, String text, byte[] image, byte[] thumb, long noteId)
throws IOException {
SQLiteDatabase sqliteDatabase = GeopaparazziApplication.getInstance().getDatabase();
sqliteDatabase.beginTransaction();
try {
// first insert image data
ContentValues imageDataValues = new ContentValues();
imageDataValues.put(ImageDataTableFields.COLUMN_IMAGE.getFieldName(), image);
imageDataValues.put(ImageDataTableFields.COLUMN_THUMBNAIL.getFieldName(), thumb);
long imageDataId = sqliteDatabase.insertOrThrow(TABLE_IMAGE_DATA, null, imageDataValues);
// then insert the image properties and reference to the image itself
ContentValues values = new ContentValues();
values.put(ImageTableFields.COLUMN_LON.getFieldName(), lon);
values.put(ImageTableFields.COLUMN_LAT.getFieldName(), lat);
values.put(ImageTableFields.COLUMN_ALTIM.getFieldName(), altim);
values.put(ImageTableFields.COLUMN_TS.getFieldName(), timestamp);
values.put(ImageTableFields.COLUMN_TEXT.getFieldName(), text);
values.put(ImageTableFields.COLUMN_IMAGEDATA_ID.getFieldName(), imageDataId);
values.put(ImageTableFields.COLUMN_AZIM.getFieldName(), azim);
values.put(ImageTableFields.COLUMN_ISDIRTY.getFieldName(), 1);
values.put(ImageTableFields.COLUMN_NOTE_ID.getFieldName(), noteId);
long imageId = sqliteDatabase.insertOrThrow(TABLE_IMAGES, null, values);
sqliteDatabase.setTransactionSuccessful();
return imageId;
} catch (Exception e) {
GPLog.error("DAOIMAGES", e.getLocalizedMessage(), e);
throw new IOException(e.getLocalizedMessage());
} finally {
sqliteDatabase.endTransaction();
}
}
/**
* Deletes images from the db.
*
* @param ids the ids of the images to remove.
* @throws IOException if something goes wrong.
*/
public static void deleteImages(long... ids) throws IOException {
SQLiteDatabase sqliteDatabase = GeopaparazziApplication.getInstance().getDatabase();
sqliteDatabase.beginTransaction();
try {
String asColumnsToReturn[] = {ImageTableFields.COLUMN_IMAGEDATA_ID.getFieldName()};
String imageIdsWhereStr = "";
int count = 0;
for (long id : ids) {
if (count > 0) {
imageIdsWhereStr = imageIdsWhereStr + " || ";
}
imageIdsWhereStr = imageIdsWhereStr + ImageTableFields.COLUMN_ID.getFieldName() + " = " + id;
count++;
}
Cursor c = sqliteDatabase.query(TABLE_IMAGES, asColumnsToReturn, imageIdsWhereStr, null, null, null, null);
c.moveToFirst();
String imageDataIdsWhereStr = "";
count = 0;
while (!c.isAfterLast()) {
long imageDataId = c.getLong(0);
c.moveToNext();
if (count > 0) {
imageDataIdsWhereStr = imageDataIdsWhereStr + " || ";
}
imageDataIdsWhereStr = imageDataIdsWhereStr + ImageDataTableFields.COLUMN_ID.getFieldName() + " = " + imageDataId;
count++;
}
c.close();
// delete images
String query = "delete from " + TABLE_IMAGES + " where " + imageIdsWhereStr;
SQLiteStatement deleteStmt = sqliteDatabase.compileStatement(query);
deleteStmt.execute();
// delete images data
query = "delete from " + TABLE_IMAGE_DATA + " where " + imageDataIdsWhereStr;
deleteStmt = sqliteDatabase.compileStatement(query);
deleteStmt.execute();
sqliteDatabase.setTransactionSuccessful();
} catch (Exception e) {
GPLog.error("DAOIMAGES", e.getLocalizedMessage(), e);
throw new IOException(e.getLocalizedMessage());
} finally {
sqliteDatabase.endTransaction();
}
}
/**
* Deletes images from the db for given notes.
*
* @param noteIds the ids of the notes for which the images should be removed.
* @throws IOException if something goes wrong.
*/
public static void deleteImagesForNotes(long... noteIds) throws IOException {
SQLiteDatabase sqliteDatabase = GeopaparazziApplication.getInstance().getDatabase();
sqliteDatabase.beginTransaction();
try {
String asColumnsToReturn[] = {ImageTableFields.COLUMN_IMAGEDATA_ID.getFieldName()};
String notesIdsWhereStr = "";
int count = 0;
for (long id : noteIds) {
if (count > 0) {
notesIdsWhereStr = notesIdsWhereStr + " || ";
}
notesIdsWhereStr = notesIdsWhereStr + ImageTableFields.COLUMN_NOTE_ID.getFieldName() + " = " + id;
count++;
}
Cursor c = sqliteDatabase.query(TABLE_IMAGES, asColumnsToReturn, notesIdsWhereStr, null, null, null, null);
c.moveToFirst();
String imageDataIdsWhereStr = "";
count = 0;
while (!c.isAfterLast()) {
long imageDataId = c.getLong(0);
c.moveToNext();
if (count > 0) {
imageDataIdsWhereStr = imageDataIdsWhereStr + " || ";
}
imageDataIdsWhereStr = imageDataIdsWhereStr + ImageDataTableFields.COLUMN_ID.getFieldName() + " = " + imageDataId;
count++;
}
c.close();
// delete images
String query = "delete from " + TABLE_IMAGES + " where " + notesIdsWhereStr;
SQLiteStatement deleteStmt = sqliteDatabase.compileStatement(query);
deleteStmt.execute();
// delete images data
query = "delete from " + TABLE_IMAGE_DATA + " where " + imageDataIdsWhereStr;
deleteStmt = sqliteDatabase.compileStatement(query);
deleteStmt.execute();
sqliteDatabase.setTransactionSuccessful();
} catch (Exception e) {
GPLog.error("DAOIMAGES", e.getLocalizedMessage(), e);
throw new IOException(e.getLocalizedMessage());
} finally {
sqliteDatabase.endTransaction();
}
}
// /**
// * Get the collected notes from the database inside a given bound.
// *
// * @param n north
// * @param s south
// * @param w west
// * @param e east
// * @return the list of notes inside the bounds.
// * @throws IOException if something goes wrong.
// */
// public static List<Image> getImagesInWorldBounds(float n, float s, float w, float e) throws IOException {
//
// SQLiteDatabase sqliteDatabase = GeopaparazziApplication.getInstance().getDatabase();
// String query = "SELECT _id, lon, lat, altim, azim, path, text, ts FROM XXX WHERE (lon BETWEEN XXX AND XXX) AND (lat BETWEEN XXX AND XXX)";
// // String[] args = new String[]{TABLE_NOTES, String.valueOf(w), String.valueOf(e),
// // String.valueOf(s), String.valueOf(n)};
//
// query = query.replaceFirst("XXX", TABLE_IMAGES);
// query = query.replaceFirst("XXX", String.valueOf(w));
// query = query.replaceFirst("XXX", String.valueOf(e));
// query = query.replaceFirst("XXX", String.valueOf(s));
// query = query.replaceFirst("XXX", String.valueOf(n));
//
// // if (Debug.D) Logger.i("DAOIMAGES", "Query: " + query);
//
// Cursor c = sqliteDatabase.rawQuery(query, null);
// List<Image> images = new ArrayList<Image>();
// c.moveToFirst();
// while (!c.isAfterLast()) {
// long id = c.getLong(0);
// double lon = c.getDouble(1);
// double lat = c.getDouble(2);
// double altim = c.getDouble(3);
// double azim = c.getDouble(4);
// String path = c.getString(5);
// String text = c.getString(6);
// String date = c.getString(7);
//
// Image image = new Image(id, text, lon, lat, altim, azim, path, date);
// images.add(image);
// c.moveToNext();
// }
// c.close();
// return images;
// }
/**
* Get the list of {@link eu.geopaparazzi.library.database.Image}s from the db.
*
* @param onlyDirty if true, only dirty notes will be retrieved.
* @param onlyStandalone if true, only pure image notes are returned.
* One example of non pure image notes is the image
* that belongs to a form based note.
* @return list of notes.
* @throws IOException if something goes wrong.
*/
public static List<Image> getImagesList(boolean onlyDirty, boolean onlyStandalone) throws IOException {
SQLiteDatabase sqliteDatabase = GeopaparazziApplication.getInstance().getDatabase();
List<Image> images = new ArrayList<>();
String asColumnsToReturn[] = { //
ImageTableFields.COLUMN_ID.getFieldName(),//
ImageTableFields.COLUMN_LON.getFieldName(),//
ImageTableFields.COLUMN_LAT.getFieldName(),//
ImageTableFields.COLUMN_ALTIM.getFieldName(),//
ImageTableFields.COLUMN_TS.getFieldName(),//
ImageTableFields.COLUMN_AZIM.getFieldName(),//
ImageTableFields.COLUMN_TEXT.getFieldName(),//
ImageTableFields.COLUMN_NOTE_ID.getFieldName(),//
ImageTableFields.COLUMN_IMAGEDATA_ID.getFieldName()//
};
String strSortOrder = "_id ASC";
String whereString = null;
if (onlyDirty) {
whereString = ImageTableFields.COLUMN_ISDIRTY.getFieldName() + " = " + 1;
}
if (onlyStandalone) {
if (whereString != null) {
whereString = whereString + " && ";
} else {
whereString = "";
}
whereString = whereString + ImageTableFields.COLUMN_NOTE_ID.getFieldName() + " < 0";
}
Cursor c = sqliteDatabase.query(TABLE_IMAGES, asColumnsToReturn, whereString, null, null, null, strSortOrder);
c.moveToFirst();
while (!c.isAfterLast()) {
long id = c.getLong(0);
double lon = c.getDouble(1);
double lat = c.getDouble(2);
double altim = c.getDouble(3);
long ts = c.getLong(4);
double azim = c.getDouble(5);
String text = c.getString(6);
long noteId = c.getLong(7);
long imageDataId = c.getLong(8);
Image image = new Image(id, text, lon, lat, altim, azim, imageDataId, noteId, ts);
images.add(image);
c.moveToNext();
}
c.close();
return images;
}
public Image getImage(long imageId) throws IOException {
SQLiteDatabase sqliteDatabase = GeopaparazziApplication.getInstance().getDatabase();
String asColumnsToReturn[] = { //
ImageTableFields.COLUMN_ID.getFieldName(),//
ImageTableFields.COLUMN_LON.getFieldName(),//
ImageTableFields.COLUMN_LAT.getFieldName(),//
ImageTableFields.COLUMN_ALTIM.getFieldName(),//
ImageTableFields.COLUMN_TS.getFieldName(),//
ImageTableFields.COLUMN_AZIM.getFieldName(),//
ImageTableFields.COLUMN_TEXT.getFieldName(),//
ImageTableFields.COLUMN_NOTE_ID.getFieldName(),//
ImageTableFields.COLUMN_IMAGEDATA_ID.getFieldName()//
};
String whereStr = ImageTableFields.COLUMN_ID.getFieldName() + " = " + imageId;
Cursor c = sqliteDatabase.query(TABLE_IMAGES, asColumnsToReturn, whereStr, null, null, null, null);
try {
c.moveToFirst();
if (!c.isAfterLast()) {
long id = c.getLong(0);
double lon = c.getDouble(1);
double lat = c.getDouble(2);
double altim = c.getDouble(3);
long ts = c.getLong(4);
double azim = c.getDouble(5);
String text = c.getString(6);
long noteId = c.getLong(7);
long imageDataId = c.getLong(8);
Image image = new Image(id, text, lon, lat, altim, azim, imageDataId, noteId, ts);
return image;
}
return null;
} finally {
c.close();
}
}
public byte[] getImageData(long imageId) throws IOException {
SQLiteDatabase sqliteDatabase = GeopaparazziApplication.getInstance().getDatabase();
String[] asColumnsToReturn = { //
ImageTableFields.COLUMN_IMAGEDATA_ID.getFieldName()//
};
String whereStr = ImageTableFields.COLUMN_ID.getFieldName() + " = " + imageId;
Cursor c = sqliteDatabase.query(TABLE_IMAGES, asColumnsToReturn, whereStr, null, null, null, null);
c.moveToFirst();
long imageDataId = -1;
if (!c.isAfterLast()) {
imageDataId = c.getLong(0);
}
c.close();
if (imageDataId != -1) {
byte[] imageData = getImageDataById(imageDataId, sqliteDatabase);
return imageData;
}
return null;
}
public byte[] getImageDataById(long imageDataId, SQLiteDatabase sqliteDatabase) throws IOException {
if (sqliteDatabase == null) {
sqliteDatabase = GeopaparazziApplication.getInstance().getDatabase();
}
String[] asColumnsToReturn;
String whereStr;
Cursor c;
asColumnsToReturn = new String[]{ //
ImageDataTableFields.COLUMN_IMAGE.getFieldName()//
};
whereStr = ImageDataTableFields.COLUMN_ID.getFieldName() + " = " + imageDataId;
c = sqliteDatabase.query(TABLE_IMAGE_DATA, asColumnsToReturn, whereStr, null, null, null, null);
byte[] imageData = null;
try {
c.moveToFirst();
imageData = null;
if (!c.isAfterLast()) {
imageData = c.getBlob(0);
}
} catch (Exception ex) {
if (ex.getLocalizedMessage().contains("Couldn't read row")) {
String sizeQuery = "SELECT " + ImageDataTableFields.COLUMN_ID.getFieldName() +//
", length(" + ImageDataTableFields.COLUMN_IMAGE.getFieldName() + ") " +//
"FROM " + TABLE_IMAGE_DATA +//
" WHERE " + whereStr;
//"length(" + ImageDataTableFields.COLUMN_IMAGE.getFieldName() + ") > 1000000";
Cursor sizeCursor = sqliteDatabase.rawQuery(sizeQuery, null);
sizeCursor.moveToFirst();
long blobSize = 0;
if (!sizeCursor.isAfterLast()) {
blobSize = sizeCursor.getLong(1);
}
sizeCursor.close();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
int maxBlobSize = ImageUtilities.MAXBLOBSIZE;
if (blobSize > maxBlobSize) {
for (long i = 1; i <= blobSize; i = i + maxBlobSize) {
long from = i;
long size = maxBlobSize;
if (from + size > blobSize) {
size = blobSize - from + 1;
}
String tmpQuery = "SELECT substr(" + ImageDataTableFields.COLUMN_IMAGE.getFieldName() + //
"," + from + ", " + size + ") FROM " + TABLE_IMAGE_DATA + " WHERE " + whereStr;
if (GPLog.LOG_HEAVY)
GPLog.addLogEntry(this, "ISSUE QUERY: " + tmpQuery);
Cursor imageCunchCursor = sqliteDatabase.rawQuery(tmpQuery, null);
imageCunchCursor.moveToFirst();
if (!imageCunchCursor.isAfterLast()) {
byte[] blobData = imageCunchCursor.getBlob(0);
bout.write(blobData);
}
imageCunchCursor.close();
}
imageData = bout.toByteArray();
bout.close();
}
} else {
GPLog.error(this, null, ex);
}
} finally {
c.close();
}
return imageData;
}
public byte[] getImageThumbnail(long imageId) throws Exception {
SQLiteDatabase sqliteDatabase = GeopaparazziApplication.getInstance().getDatabase();
String[] asColumnsToReturn = { //
ImageTableFields.COLUMN_IMAGEDATA_ID.getFieldName()//
};
String whereStr = ImageTableFields.COLUMN_ID.getFieldName() + " = " + imageId;
Cursor c = sqliteDatabase.query(TABLE_IMAGES, asColumnsToReturn, whereStr, null, null, null, null);
c.moveToFirst();
long imageDataId = -1;
if (!c.isAfterLast()) {
imageDataId = c.getLong(0);
}
c.close();
if (imageDataId != -1) {
byte[] imageData = getImageThumbnailById(sqliteDatabase, imageDataId);
return imageData;
}
return null;
}
public byte[] getImageThumbnailById(SQLiteDatabase sqliteDatabase, long imageDataId) throws Exception {
String[] asColumnsToReturn;
String whereStr;
asColumnsToReturn = new String[]{ //
ImageDataTableFields.COLUMN_THUMBNAIL.getFieldName()//
};
whereStr = ImageDataTableFields.COLUMN_ID.getFieldName() + " = " + imageDataId;
Cursor c = sqliteDatabase.query(TABLE_IMAGE_DATA, asColumnsToReturn, whereStr, null, null, null, null);
byte[] imageData = null;
try {
c.moveToFirst();
imageData = null;
if (!c.isAfterLast()) {
imageData = c.getBlob(0);
}
} finally {
c.close();
}
return imageData;
}
/**
* Get all image overlays.
*
* @param marker the marker to use.
* @param onlyStandalone if true, only pure image notes are returned.
* One example of non pure image notes is the image
* that belongs to a form based note.
* @return the list of {@link OverlayItem}s.
* @throws IOException if something goes wrong.
*/
public static List<OverlayItem> getImagesOverlayList(Drawable marker, boolean onlyStandalone) throws IOException {
SQLiteDatabase sqliteDatabase = GeopaparazziApplication.getInstance().getDatabase();
List<OverlayItem> images = new ArrayList<>();
String asColumnsToReturn[] = {//
ImageTableFields.COLUMN_LON.getFieldName(),//
ImageTableFields.COLUMN_LAT.getFieldName(), //
ImageTableFields.COLUMN_IMAGEDATA_ID.getFieldName(),//
ImageTableFields.COLUMN_TEXT.getFieldName()//
};
String strSortOrder = "_id ASC";
String whereString = null;
if (onlyStandalone) {
whereString = ImageTableFields.COLUMN_NOTE_ID.getFieldName() + " < 0";
}
Cursor c = sqliteDatabase.query(TABLE_IMAGES, asColumnsToReturn, whereString, null, null, null, strSortOrder);
c.moveToFirst();
while (!c.isAfterLast()) {
double lon = c.getDouble(0);
double lat = c.getDouble(1);
long imageDataId = c.getLong(2);
String text = c.getString(3);
OverlayItem image = new OverlayItem(new GeoPoint(lat, lon), text, imageDataId + "", marker);
images.add(image);
c.moveToNext();
}
c.close();
return images;
}
}