Android Cursor Illegal state exception crash - android

I am having some issues with a piece of android code, the crash seems to be occurring here c.moveToFirst(). I have tried to get a count, and if the cursor result is greater than 0; then execute that code, but that doesn't help.
I am unable to reproduce this error on my apps (I have tried several scenarios), However, through Google Dev Console, I am seeing that other people that are using my app are getting this error.
Thanks in advance
Crash error:
java.lang.IllegalStateException:
at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked (SQLiteConnectionPool.java:1198)
at android.database.sqlite.SQLiteConnectionPool.waitForConnection (SQLiteConnectionPool.java:808)
at android.database.sqlite.SQLiteConnectionPool.acquireConnection (SQLiteConnectionPool.java:534)
at android.database.sqlite.SQLiteSession.acquireConnection (SQLiteSession.java:904)
at android.database.sqlite.SQLiteSession.executeForCursorWindow (SQLiteSession.java:834)
at android.database.sqlite.SQLiteQuery.fillWindow (SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow (SQLiteCursor.java:152)
at android.database.sqlite.SQLiteCursor.getCount (SQLiteCursor.java:141)
at com.andre3.wzlimitdistraction.dao.Dao.read (Dao.java:101)
at com.andre3.wzlimitdistraction.utils.MonitorService$2.run (MonitorService.java:201)
at java.util.TimerThread.mainLoop (Timer.java:555)
at java.util.TimerThread.run (Timer.java:505)
Code thats causing it:
ArrayList<UserApps> arr = new ArrayList<UserApps>();
int profileId = 0;
SQLiteDatabase getDb = db.getReadableDatabase();
if(getDb.isOpen()) {
String[] columns = {Dbinfo.app.toString(), Dbinfo.app_name.toString(), Dbinfo.start_duration.toString(), Dbinfo.active_duration.toString(), Dbinfo.start_time.toString(), Dbinfo.profile_id.toString()};
String selection = Dbinfo.app.toString() + " =? and " + Dbinfo.profile_id.toString() + " <=?";
String[] selectionArgs = {id, String.valueOf(profileId)};
Cursor c = getDb.query("user_apps", columns, selection, selectionArgs, null, null, null);
if((c.getCount() > 0) && (c !=null)) {
if (c.moveToFirst()) {
do {
UserApps form = new UserApps();
form.setPkg(c.getString(c.getColumnIndex(Dbinfo.app.toString())));
form.setName(c.getString(c.getColumnIndex(Dbinfo.app_name.toString())));
arr.add(form);
} while (c.moveToNext());
}
}
getDb.close();
c.close();
}
return arr;

This is possibly because getColumnIndex can not find the column you specified . You can Refer this Question

Related

SQL query is returning one result less than expected

my query keeps returning one result less than expected. Initialy I had 6 rows that needed to be returned, it kept returning only 5, I decided to add another one and now it is returning 6 instead of 7, It is always the last one.
I tested the same query in SQLite Admin and it worked just fine.
Cursor cursor = database.rawQuery("SELECT DISTINCT * FROM Activities JOIN
UserMakesActivities ON UserMakesActivies.ActivityID =
Activities.intID WHERE UserMakesActivies.UserID = " + ID, null);
Any ideas are welcome. If for some reason the sql is not correct it is because I changed it to make it clearer here.
Edit: as requested this is where I am moving my cursor.
cursor.moveToFirst();
Log.i("tag", "contagem " + cursor.getCount());
while (!cursor.isAfterLast()) {
Atividade atividade = cursorToAtividade(cursor);
atividades.add(atividade);
cursor.moveToNext();
}
private static Atividade cursorToAtividade(Cursor cursor) {
Atividade atividade = new Atividade();
atividade.setNum(cursor.getInt(0));
atividade.setNome(cursor.getString(1));
atividade.setInformacao(cursor.getString(2));
atividade.setAtividadeFeita((cursor.getInt(3) == 1) ? true : false);
atividade.setAtividadeMonitorada((cursor.getInt(4) == 1) ? true : false);
atividade.setTempo(cursor.getInt(5));
atividade.setTipo(cursor.getString(6));
return atividade;
}
This may not fix your issue, but I see a few suspicious things in there.
First, it would be better to use selectionArgs for your query:
String[] selectionID = new String[] {ID};
Cursor cursor = database.rawQuery("SELECT DISTINCT * FROM Activities JOIN
UserMakesActivities ON UserMakesActivies.ActivityID =
Activities.intID WHERE UserMakesActivies.UserID = ?", selectionID );
Also make sure that you close your cursor to avoid memory leaks.
if (cursor != null){
Log.i("tag", "contagem " + cursor.getCount());
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
Atividade atividade = cursorToAtividade(cursor);
atividades.add(atividade);
}
cursor.close();
}
After some research I found a way to check my DB using SQLite Manager plugin for android that I got from here
There was an error in the database and with that info I understood what I was doing wrong when submiting info to the DB

Skip deleted/empty rows sqlite

I am populating AChartEngine from sqlite database and I need all of the data to be displayed. The problem I'm having is when I delete a record the graph series stops populating at the deleted record. I need to find a way to skip over deleted/empty records and continue populating my graph. I need it to do it the same way listview skips over deleted records and keeps on displaying all rows. I am very new to a lot of this and am having a very difficult time with this. I have tried to write if statements in order to skip deleted/empty rows but nothing seems to work. Thank you for helping!
in my graphing activity:
for (int i = 1; !c.isAfterLast(); i++) {
String value1 = db.getValue1(i);
String value2 = db.getValue2(i);
c.moveToNext();
double x7 = Double.parseDouble(value1);
double y7 = Double.parseDouble(value2);
myseries.add(x7, y7);
}
I am getting error: CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
If I surround with try and catch it will populate rows up until the deleted record.
"EDIT"
in my sqlite database:
public String getValue1(long l) {
String[] columns = new String[]{ EMP_DEPT };
Cursor c = db.query(EMP_TABLE, columns, EMP_ID + "=" + l, null, null, null, null);
if (c != null){
c.moveToFirst();
String value1 = c.getString(0);
return value1;
}
return null;
}
public String getValue2(long l) {
String[] columns = new String[]{ EMP_DATE1 };
Cursor c = db.query(EMP_TABLE, columns, EMP_ID + "=" + l, null, null, null, null);
if (c != null){
c.moveToFirst();
String value2 = c.getString(0);
return value2;
}
return null;
}
Your issue is that your safety net for commands on rows that don't exist is to use if (c != null){ and then perform your commands inside that block, but a Cursor request from a query will never come up null, it will instead result in a cursor object with no rows.
A more appropriate solution to use this as your safety net instead if (c.moveToFirst()){ Because the method itself returns a boolean for if the method actually carried itself out in the first place - true if it moved and false if not (which occurs when there's no rows to move into). another check, if you wish, would be to see how many rows the cursor has with c.getCount().
Additionally, you should combine your methods so that you don't make redundant queries to the database:
public String[] getValues(long l) {
String[] results = new String[2];
String[] columns = new String[]{ EMP_DEPT, EMP_DATE1 };
Cursor c = db.query(EMP_TABLE, columns, EMP_ID + "=" + l, null, null, null, null);
if (c.moveToFirst()) {
results[0] = c.getString(0);
results[1] = c.getString(1);
} else {
Log.d("GET_VALUES", "No results formed from this query!");
}
return results;
}
You should use a single query to get all values at once:
SELECT Date1 FROM MyTable WHERE id BETWEEN 1 AND 12345
or:
db.query(EMP_TABLE, columns, EMP_ID + " BETWEEN 1 AND " + ..., ...);
Then missing values will just not show up when you iterate over the cursor.

Check if cursor has results

I am using a database to store date and want a single column returned based on which id is given in the where claus.
public String getPmax(String serial) {
String[] columns = new String[]{KEY_SERIAL, KEY_PMAX};
Cursor c = ourDatabase.query(DATABASE_TABLE, columns, "serial = " + serial,
null, null, null, null);
String result = "nothing found";
if(c != null) {
int iPmax = c.getColumnIndex(KEY_PMAX);
c.moveToFirst();
result = c.getString(iPmax);
}
return result;
}
This code works if I use a serial that is in the database but it gives me a force close when i am using a serial that's not in the database!
it says:
04-11 16:31:19.423: E/AndroidRuntime(21226): java.lang.RuntimeException: Unable to start activity ComponentInfo{nl.janjanus.solardetect/nl.janjanus.solardetect.DatabaseView}: android.database.sqlite.SQLiteException: no such column: g: , while compiling: SELECT serial, pmax FROM SolareCel WHERE serial = g
So my question is: How do I check if there is result? or do I need to check if the serial given is a serial that is in the database?
if (!(mCursor.moveToFirst()) || mCursor.getCount() ==0){
//cursor is empty
}
If you look closely, the error is that the SQL is faulty.
It reads the g as a column. You have to encase it in apostrophes like so 'g'.
In your case, the line where you get the cursor should be:
Cursor c = ourDatabase.query(DATABASE_TABLE, columns, "serial = '" + serial + "'",
null, null, null, null);
As to checking whether the cursor has no results, look at Samir Mangroliya's answer.
You can check if the Cursor has elements:
boolean isEmpty = cursor.getCount() < 1;
AFAIK, the Cursor never returns null when there is no row which the requested conditions, just return a empty Cursor.
int x = cursor.getCount(); //this will return number of records in current cursor
if ( x == 0 ) {
// there are no records
} else {
// do your stuff
}

Getting random contact numbers in Android

I'm trying to use the following code to grab a random mobile phone number from the contacts:
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, "DISPLAY_NAME = '" + "NAME" + "'", null, null);
cursor.moveToFirst();
String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
Cursor phones = cr.query(Phone.CONTENT_URI, null, Phone.CONTACT_ID + " = " + contactId, null, null);
List numbers = new ArrayList();
while (phones.moveToNext()) {
String number = phones.getString(phones.getColumnIndex(Phone.NUMBER));
int type = phones.getInt(phones.getColumnIndex(Phone.TYPE));
switch (type) {
case Phone.TYPE_MOBILE:
numbers.add(number);
break;
}
}
Random randGen = new Random();
return (String) numbers.get(randGen.nextInt(numbers.size()));
However, running this code produces a crash on line 4, with a message saying "CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0". The crash seems to be caused by the cursor.getString() method. Does anyone know where I'm going wrong? This is using the ContactsContract in Android 2.1. Eclipse gives no errors.
Thanks!
The moveToFirst() method returns a boolean. It returns true if it was able to move to the first row and false otherwise, indicating that the query returned an empty set.
When using a cursor, you should follow something like:
if (cursor.moveToFirst()) {
do {
// do some stuff
} while (cursor.moveToNext());
}
cursor.close();

How do you get the members of a contact group?

I have the ID of a contact group, and I'd like to list its members. Here's the code I'm trying:
String[] projection = new String[]{
ContactsContract.CommonDataKinds.GroupMembership.CONTACT_ID
};
Cursor contacts = getContentResolver().query(
Data.CONTENT_URI,
projection,
ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID + "=" + gid,
null,
null
);
String result = "";
do {
result += contacts.getString(contacts.getColumnIndex(ContactsContract.CommonDataKinds.GroupMembership.CONTACT_ID)) + " ";
} while (contacts.moveToNext());
But this throws an Exception:
03-24 17:11:33.097: ERROR/AndroidRuntime(10730): android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 2
...
03-24 17:11:33.097: ERROR/AndroidRuntime(10730): at myapp.MultiSend$1.onItemClick(MultiSend.java:83)
which is the line starting result +=. Can anyone tell me what I'm doing wrong, or suggest a better way to get the same information?
Try this code snippet
String[] projection = new String[]{
ContactsContract.CommonDataKinds.GroupMembership.CONTACT_ID
};
Cursor contacts = getContentResolver().query(
Data.CONTENT_URI,
projection,
ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID + "=" + gid,
null,
null
);
startManagingCursor(contacts);
String result = "";
if (contacts.moveToFirst()) {
do {
try {
result += contacts.getString(contacts.getColumnIndex(ContactsContract.CommonDataKinds.GroupMembership.CONTACT_ID)) + " ";
} catch (Exception ex) {
ex.printStackTrace();
}
} while (contacts.moveToNext());
}
Cursor.getColumnIndex(String column) returns -1 when the column does not exist, and that is causing Cursor.getString(int colidx) to throw the exception.
I'd start testing by passing null for the third argument of the query call to see if you get a valid Cursor from the call.
If you don't get a valid Cursor, then I'd check to make sure that Data.CONTENT_URI is the right CONTENT_URI to call. It's hard to tell what the fully qualified path is without seeing your imports. (Edit: It looks like ContactsContract.Data.CONTENT_URI must be the constant there.)
If you do get a valid Cursor, then there might be an issue with that third argument.

Categories

Resources