I have a Google Map’s based application on android.
In short the application works by: first entering some sample data (containing latitude/longitude pairs into a database), reads them and finally plots them on a map overlay.
This app works fine when I run it on Android 2.3.3 (Gingerbread) emulator as well as on my HTC Desire S.
But when I try the same application in a Android 4.0.3 (ICS) emulator (after making changes in manifest file for sdk version) I get an error Cursor Finalized without Prior Close() when I try to execute the activity. With a NullPointer Exception and the app crashes.
StackTrace pastebin is here
Updated Method(s)
public int getAllEntries() {
//int entryCount;
Cursor cursorE = db.rawQuery("SELECT COUNT(LATS) FROM myPROmapData",
null);
try {
if (cursorE.moveToFirst()) {
return cursorE.getInt(0);
}
return cursorE.getInt(0);
} finally {
cursorE.close();
}
}
--
public Double[] PopulateLats() {
//id = getAllEntries();
int LatcolumnIndex = 0;
Cursor cursor = db.rawQuery("SELECT LATS FROM myPROmapData", null);
try {
Double myLats[] = new Double[cursor.getCount()];;
if (cursor.moveToFirst()) {
for (int i = 0; i < cursor.getCount(); i++)
{
myLats[i] = cursor.getDouble(LatcolumnIndex);
cursor.moveToNext();
//cursor.close();
}
}
return myLats;
} finally {
cursor.close();
}
}
--
public Double[] PopulateLons(){
int LoncolumnIndex = 0;
Cursor cursor2 = db.rawQuery("SELECT LONS FROM myPROmapData", null);
try {
Double myLons[] = new Double[cursor2.getCount()];;
if (cursor2.moveToFirst()) {
for (int i = 0; i < cursor2.getCount(); i++)
{
myLons[i] = cursor2.getDouble(LoncolumnIndex);
cursor2.moveToNext();
//cursor.close();
}
}
return myLons;
} finally {
cursor2.close();
}
}
Here’s my activity code:
public class MapMaster extends MapActivity {
/** Called when the activity is first created. */
private List mapOverlays;
private Projection projection;
private MapController mc;
private MapView mapView;
private GeoPoint gP;
// private GeoPoint gP2;
private MyOverlay myoverlay;
//Author: Kanishk
DBAdapter db = new DBAdapter(this);
public Double GetStartLat4gp()
{
Double Lat1 = null;
db.open();
//db.insertQuote(); //INSERTING SAMPLE DATA INTO TABLE
Double[] dtaStartLat = null;
dtaStartLat = db.PopulateLats();
for(int z=0;z<(dtaStartLat.length);z++)
{
//System.out.println("START_LAT:");
//System.out.println(dtaStartLat[z]);
Lat1 = dtaStartLat[z];
break;
}
db.close();
return Lat1;
}
public Double GetStartLon4gp()
{
Double Lon1 = null;
db.open();
//db.insertQuote(); //INSERTING SAMPLE DATA INTO TABLE
Double[] dtaStartLon = null;
dtaStartLon = db.PopulateLons();
for(int z=0;z<(dtaStartLon.length);z++)
{
//System.out.println("START_LAT:");
//System.out.println(dtaStartLon[z]);
Lon1 = dtaStartLon[z];
break;
}
db.close();
return Lon1;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_master);
//Double myStartLat = null;
//Double myStartLon = null;
mapView = (MapView) findViewById(R.id.mapview1);// Creating an instance
// of MapView
mapView.setBuiltInZoomControls(true);// Enabling the built-in Zoom
// Controls
//mapView.setTraffic(true);
//mapView.setStreetView(true);
GeoPoint gP = new GeoPoint((int)(GetStartLat4gp() * 1E6), (int)(GetStartLon4gp() * 1E6));
//gP = new GeoPoint(28570000, 77320000);// Creating a GeoPoint
System.out.println("v START CORDS v");
System.out.println(GetStartLat4gp());
System.out.println(GetStartLon4gp());
System.out.println("^ START CORDS ^");
mc = mapView.getController();
mc.setCenter(gP);
mc.setZoom(15);// Initializing the MapController and setting the map to
// center at the
// defined GeoPoint
mapOverlays = mapView.getOverlays();
projection = mapView.getProjection();
myoverlay = new MyOverlay();
mapOverlays.add(myoverlay);
db.open();
//db.CreateSampleData(); //create sample data
//db.SyncNclean(); //SYNC - CLEAN
if(db.doesDatabaseExist(this, "PROdb")){
Toast.makeText(this, "EXISTS", Toast.LENGTH_SHORT).show();
db.SyncNclean();
Toast.makeText(this, "CLEANING..CREATING SAMPLE DATA..", Toast.LENGTH_SHORT).show();
db.CreateSampleData();
Toast.makeText(this, "Sample Data Created", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(this, "DOES NOT EXISTS", Toast.LENGTH_SHORT).show();
db.SyncNclean();
Toast.makeText(this, "CLEANING..CREATING SAMPLE DATA..", Toast.LENGTH_SHORT).show();
db.CreateSampleData();
Toast.makeText(this, "Sample Data Created", Toast.LENGTH_SHORT).show();
}
long id = 0;
id = db.getAllEntries();
CharSequence text = "The data was added successfully!\nData Totals = " + id + "Records";
System.out.println(text);
db.close();
}
public Double[] GetLats()
{
db.open();
//db.insertQuote(); //INSERTING SAMPLE DATA INTO TABLE
Double[] dtaMyLats = null;
dtaMyLats = db.PopulateLats();
for(int z=0;z<(dtaMyLats.length);z++)
{
System.out.println("LATS:");
System.out.println(dtaMyLats[z]);
}
db.close();
return dtaMyLats;
}
public Double[] GetLons()
{
db.open();
Double[] dtaMyLons = null;
dtaMyLons = db.PopulateLons();
for(int z=0;z<(dtaMyLons.length);z++)
{
System.out.println("LONS:");
System.out.println(dtaMyLons[z]);
}
db.close();
return dtaMyLons;
}
@Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
class MyOverlay extends Overlay {
public MyOverlay() {
}
//Author: Kanishk
public void draw(Canvas canvas, MapView mapv, boolean shadow) {
super.draw(canvas, mapv, shadow);
// Configuring the paint brush
Paint mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(4);
Double[] LatArr = GetLats();
Double[] LonArr = GetLons();
//generate geopoints dynamically based on coordinates from index @ array
//author: Kanishk
int count = LatArr.length;
//System.out.println(count);
for(int i=0;i<count-1;i++)
{
Double lat1;
Double lon1;
Double lat2;
Double lon2;
lat1 = LatArr[i];
lon1 = LonArr[i];
//System.out.println(LatLon[i][j]);
/*System.out.println("<< BREAK >>");
System.out.println(lat1);
System.out.println(lon1);
*/
lat2=LatArr[i+1];
//lat1 = null;
lon2=LonArr[i+1];
//lon1 = null;
//i++;
if(lat2!=null){
GeoPoint gp1 = new GeoPoint((int)(lat1 * 1E6), (int)(lon1 * 1E6)); //
GeoPoint gp2 = new GeoPoint((int)(lat2 * 1E6), (int)(lon2 * 1E6)); //
System.out.println("<< coord1 >>");
System.out.println(lat1);
System.out.println(lon1);
System.out.println("<< coord2 >>");
System.out.println(lat2);
System.out.println(lon2);
Point p11 = new Point();
Point p22 = new Point();
Path mypath = new Path();
projection.toPixels(gp1, p11);
projection.toPixels(gp2, p22);
mypath.moveTo(p22.x, p22.y);// *
mypath.lineTo(p11.x, p11.y);// *
canvas.drawPath(mypath, mPaint);
}
}
// logic end
}
}
}
DBAdapter Class:
public class DBAdapter {
int id = 0;
//public static final String KEY_ROWID = "_id";
public static final String KEY_PHID = "phID";
public String KEY_LAT = "LATS";
public String KEY_LON = "LONS";
private static final String TAG = "DBAdapter";
private static final String DATABASE_NAME = "PROdb";
private static final String DATABASE_TABLE = "myPROmapData";
private static final int DATABASE_VERSION = 9;
//private static final String DATABASE_CREATE = "create table myPROmapData (_id integer primary key autoincrement, phID integer, LATS real not null, LONS real not null);";
private static final String DATABASE_CREATE = "create table myPROmapData (phID integer, LATS real not null, LONS real not null);";
private final Context context;
private DatabaseHelper DBHelper;
private SQLiteDatabase db;
public DBAdapter(Context ctx) {
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(DATABASE_CREATE);
}
catch (Exception e){
Log.e(TAG,"Error: onCreate db");
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
try {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS myPROmapData");
onCreate(db);
}
catch (Exception e){
Log.e(TAG,"Error: onUpgrade db");
}
}
}
// ---opens the database---
public DBAdapter open() throws SQLException {
db = DBHelper.getWritableDatabase();
return this;
}
// ---closes the database---
public void close() {
DBHelper.close();
}
// ---insert sample data into the database---
public long CreateSampleData() {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_PHID, 100);
initialValues.put(KEY_LAT, 28.4588);
initialValues.put(KEY_LON, 77.0725);
db.insert(DATABASE_TABLE, null, initialValues);
initialValues.put(KEY_LAT, 28.4719);
initialValues.put(KEY_LON, 77.0722);
db.insert(DATABASE_TABLE, null, initialValues);
/*initialValues.put(KEY_LAT, 28.5700);
initialValues.put(KEY_LON, 77.3200);*/
initialValues.put(KEY_LAT, 28.4795);
initialValues.put(KEY_LON, 77.0800);
db.insert(DATABASE_TABLE, null, initialValues);
/*initialValues.put(KEY_LAT, 28.4700);
initialValues.put(KEY_LON, 77.0300);*/
initialValues.put(KEY_LAT, 28.4813);
initialValues.put(KEY_LON, 77.0931);
db.insert(DATABASE_TABLE, null, initialValues);
/*initialValues.put(KEY_LAT, 27.1833);
initialValues.put(KEY_LON, 78.0167);*/
initialValues.put(KEY_LAT, 28.4820);
initialValues.put(KEY_LON, 77.1023);
db.insert(DATABASE_TABLE, null, initialValues);
/*initialValues.put(KEY_LAT, 26.4583);
initialValues.put(KEY_LON, 80.3173);*/
initialValues.put(KEY_LAT, 28.4804);
initialValues.put(KEY_LON, 77.1251);
return db.insert(DATABASE_TABLE, null, initialValues);
}
public int getAllEntries() {
//int entryCount;
Cursor cursorE = db.rawQuery("SELECT COUNT(LATS) FROM myPROmapData",
null);
if (cursorE.moveToFirst()) {
//entryCount = cursorE.getInt(0);
return cursorE.getInt(0);
//return entryCount;
}
// CLOSING CURSOR
cursorE.close();
return cursorE.getInt(0);
//return entryCount;
}
public boolean doesDatabaseExist(ContextWrapper context, String dbName) {
File dbFile = context.getDatabasePath(dbName);
return dbFile.exists();
}
public void SyncNclean(){
Log.w(TAG, "Sync'ing with Master Server..");
//sync master server here
Log.w(TAG, "Sync Complete..");
//Log.w(TAG, "Cleaning old data..");
db.execSQL("DROP TABLE IF EXISTS myPROmapData");
DBHelper.onCreate(db);
Log.w(TAG, "Cleaning completed..");
}
public Double[] PopulateLats() {
//id = getAllEntries();
int LatcolumnIndex = 0;
Cursor cursor = db.rawQuery("SELECT LATS FROM myPROmapData", null);
Double myLats[] = new Double[cursor.getCount()];;
if (cursor.moveToFirst())
{
for (int i = 0; i < cursor.getCount(); i++)
{
myLats[i] = cursor.getDouble(LatcolumnIndex);
cursor.moveToNext();
cursor.close();
}
}
// Original location for cursor.close()
return myLats;
}
public Double[] PopulateLons(){
int LoncolumnIndex = 0;
Cursor cursor2 = db.rawQuery("SELECT LONS FROM myPROmapData", null);
Double myLons[] = new Double[cursor2.getCount()];;
if (cursor2.moveToFirst())
{
for (int i = 0; i < cursor2.getCount(); i++)
{
myLons[i] = cursor2.getDouble(LoncolumnIndex);
cursor2.moveToNext();
cursor2.close(); //third try
}
// second tried here: cursor2.close();
}
// Original location for cursor.close()
//db.close();
return myLons;
}
}
Any help will be appreciated. Thanks for reading.
The solution to the nullpointer exception is:
GetStartLat4gp or GetStartLon4gp returns null.
Apart from that, the code will be more stable whenn you rewrite this method to
In the original draft of it, it did not close the cursor because it did return early.
use try {} finally { close resources } as a good style, to be sure to close all resources in any case (even unexpected exceptions)
Apart from that, move the close() of the other cursor back outside the loop, it will provoke errors inside the loop. (best, use try / finally there, too)