Android 3.0 Couldn't read row#, column# from cursor window - android

I have an application that runs fine on android 2.1, but when trying to transition it to 3.0 I get a cursor error that I'm not familar with.
Java.lang.IllegalStateException: Couldn't read row0, column -1 from
cursor window. Make sure cursor is initialized correctly before
accessing data from it.
All the data is storred in a SQLite database and this code works fine in android 2.1. Does a cursor have to be initialized differently in android 3.0?
Listed below is my code.
private void OpenGroupData(){
SQLiteDatabase db = openOrCreateDatabase(DATABASE_NAME,Context.MODE_PRIVATE,null);
Cursor cur = db.rawQuery("SELECT groupid FROM properties GROUP BY GroupID" + ";" , null);
LinearLayout glayout = (LinearLayout) findViewById(R.id.Grouplayout);
LinearLayout gwindow = (LinearLayout) findViewById(R.id.groupwindow);
TextView data = new TextView(this);
glayout.addView(data);
data.setText("");
int ID = cur.getColumnIndex("groupid");
int idvalue;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
try{
// Check if our result was valid.
cur.moveToFirst();
if (cur != null) {
// Loop through all Results
do {data = new TextView(this);
data.setTextSize(20);
data.setClickable(true);
data.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
GroupClick(v);
}
});
glayout.addView(data);
idvalue = cur.getInt(ID);
data.setId(idvalue);
data.setText("Group: " + idvalue);
}while(cur.moveToNext());
}
cur.close();
db.close();
} catch(Exception e) {
Toast.makeText(getApplicationContext(), "Open Group Exception: " + e.toString(), Toast.LENGTH_SHORT).show();
}
}

I ran into the same error message earlier this day. All it turned out to was that I made a typo in the column name. So, if it still applies, you could go and check the column name for typo's. Note that its case sensitive aswell. Error for me was along the lines of:
//Trew error
c.getColumnIndex("ArticleNumber");
//Was correct
c.getColumnIndex("Articlenumber");

Alright I figured it out. For some reason when trying to transistion my application to 3.0 when my cursor goes and gets the column index for a field, in this case ("groupid") it is returning a value of -1. When the Cursor tries to start at -1 it crashes because it can't find a record at row(0), column(-1). So my fix was to just add one to the column index when getting the id. see below.
int ID = cur.getColumnIndex("groupid") + 1;
int idvalue;
By adding 1 to the Column index it seems to have solved the problem.

If getColumnIndex returns -1, then the column doesn't exist.
Otherwize it returnes zero-based column index.

-1 is the _id column which every sqlite table should have as is required by the android framework. If you have to add +1 to the index you are going wrong somewhere.

The -1 value returns form getColumnIndex(columnName) if 'columnName' can't be found. Check the column names

Related

Android Studio - Value must be ≥ 0

I am getting an error in Android Studio to do with my Cursor.
I have the following line in my code
String data = cursor.getString(cursor.getColumnIndex(columnIndex));
columnIndex is being passed into the method.
This part cursor.getColumnIndex(columnIndex) produces the following error
Value must be ≥ 0
Its happening in my DBHelper class and also my recycler adapter when it uses a cursor too.
It shows up as an error in red but the app still builds and runs without issue.
Any ideas?
Thanks for any help.
Update 22-Sep-21
I'm adding some code as requested and also how i have got around this error. Not sure if its the best way though.
So the method im using is this....
public String getTripInfo(String tableName, int tripNo, String columnIndex){
String data = "";
// Select all query
String selectQuery = "SELECT * FROM " + tableName + " WHERE " + TRIP_DETAILS_TRIP_NUMBER + "=" + tripNo;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// Looping through all rows and adding to list
if(cursor.moveToFirst()){
do{
data = cursor.getString(cursor.getColumnIndex(columnIndex));
} while(cursor.moveToNext());
}
// Closing connections
cursor.close();
db.close();
//Returning number plates
return data;
}
The error is in the do while loop. The part in red is "cursor.getColumnIndex(columnIndex))"
The way i have gotten around this error is using the following code instead
public String getTripInfo(String tableName, int tripNo, String columnIndex){
String data = "";
// Select all query
String selectQuery = "SELECT * FROM " + tableName + " WHERE " + TRIP_DETAILS_TRIP_NUMBER + "=" + tripNo;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// Looping through all rows and adding to list
if(cursor.moveToFirst()){
do{
int index = cursor.getColumnIndex(columnIndex);
data = cursor.getString(index);
} while(cursor.moveToNext());
}
// Closing connections
cursor.close();
db.close();
//Returning number plates
return data;
}
I had an error like this.
My solution : change method getColumnIndex into getColumnIndexOrThrow.
The problem is that cursor.getColumnIndex() can return -1, you're passing it as a direct parameter, and the cursor getters need a column index gte 0. The getters' parameter is annotated with #IntRange(from = 0) which is why lint marks it as an error.
So, even though you might have built your project such that it would never produce an invalid column index, the fact that such a possibly could exist is why lint is tagging it.
Your code revision only avoids the issue. It would be best to use cursor.getColumnIndexOrThrow() or test index for gte 0.
You can get away with your changes since you know more about your project than lint does, it just isn't the best practice.
Use This Method Proper Work :-
#SuppressLint("Range") Strong name = cursor.getString(cursor.getColumnIndex(indexNumber));

Initialize SQLite Cursor before accessing data from it

I am trying to insert data into a SQLite DB once a notification is received via FCM. For debugging purpose I am also inserting a dummy data into my DB when SHow Token is clicked on the HomeScreen activity.
However am getting
"I am getting "Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it."
Link to my code: - GitHub
Can someone please go through my code and let me know where I am going wrong.
Note - I added below in HomeScreen.java,MyFirebaseMessagingService.java and NotificationDetails.java
private SQLiteDB dbHelper = new SQLiteDB(this);
since the suggested
private SQLiteDB dbHelper;
did not work for me
When I used above I kept on getting Nullpointer exception, so I figured since the SQLiteDB class constructor is accepting a context, so let me pass one, post which I did not get NullPointer Exception.
Now I did this without being fully aware of the concept on context which I have been trying to wrap my head around, but since am an extreme noob to android I am not able to grasp it just yet. I suspect it might have something to do with the context I am passing.
Can someone please help me here with detailed instructions on how to fix this issue, I have been through many other threads on this but was not able to fix hence after 5 hrs of going through multiple SO questions, I am posting this one.
Thanks in advance to everyone in the community for the help. :)
Edit
Upon suggestion by admins, I am including below snippet of my code.
Where I am calling the cursor
dbHelper.insertNotification("This is a notification");
//Check if the message contains data
Cursor rs = dbHelper.getAllNotifications();
rs.moveToFirst();
token_text.setText("Token: " +rs.getString((rs.getColumnIndex("NOTIFICATION_DETAILS"))));
Insert Notification Function in SQLiteDB.java
public boolean insertNotification(String notification){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(NOTIFICATION_DETAILS,notification);
db.insert(NOTIFICATION_TABLE_NAME,null,contentValues);
return true;
}
getAllNotifications function
public Cursor getAllNotifications() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor res = db.rawQuery( "SELECT * FROM " + NOTIFICATION_TABLE_NAME, null );
return res;
}
Couldn't read row 0, col -1 from CursorWindow.
Is saying that you are attempting to get the column at offset -1 from row 0 (the first row). So you have provided an invalid offset (it cannot be an offset of -1, the offset must be 0 or greater and the maximum value will be 1 less than the number of columns in the Cursor).
The most likely cause, is that Cursor method getColumnIndex(the_column_name_as_a_string) will return -1 when the column passed to the method cannot be found in the Cursor. Noting that due to a bug column name is case sensitive.
As such your issue is that the Cursor does not contain a column name NOTIFICATION_DETAILS and as you have used * (all columns) then that column does not exist in the table.
By the looks of it you should be using the String variable NOTIFICATION_DETAILS so you probably need to use :-
token_text.setText("Token: " +rs.getString((rs.getColumnIndex(NOTIFICATION_DETAILS)))); //<<<<<<<<<< double quotation marks removed.
Additional
You should NEVER assume that moveToFirst (or any Cursor move???? method) actually does the move. You should ALWAYS check the returned value. It will be true if the move was successful otherwise it would be false.
Again note that the column name passed to the getColumnIndex method is case dependant.
As such you should use something like
:-
dbHelper.insertNotification("This is a notification");
//Check if the message contains data
Cursor rs = dbHelper.getAllNotifications();
if (rs.moveToFirst()) {
token_text.setText("Token: " +rs.getString((rs.getColumnIndex(NOTIFICATION_DETAILS))));
} else {
........ code here if anything need to be done if there are no rows extracted
}
Addition re comment :-
Cursor rs = dbHelper.getAllNotifications(); rs.moveToFirst(); do{ for
(int i = 0; i < rs.getColumnCount(); i++) {
notification_array.add(rs.getString((rs.getColumnIndex(NOTIFICATION_DETAILS))));
} }while (rs.moveToNext());
using the following is much simpler :-
Cursor rs = dbHelper.getAllNotifications();
while (rs.moveToNext()) {
notification_array.add(rs.getString((rs.getColumnIndex(NOTIFICATION_DETAILS))));
}

Android Studio - Cursor.getString() throwing exception

I'm new to Android Studio and this is my first application in general where I'm working with database connectivity, so I may just be fundamentally misunderstanding how the cursor works.
I'm querying my database, and tests show that the query is successful, specifically the getCount() method returns 2 as the number of rows the cursor object contains. However when I call the getString() method it throws an exception instead of returning the column data.
Anything pop out right away that could be wrong with this code?
public void GetFacts(View v) {
Cursor cursor = database.query(ExternalDbOpenHelper.TABLE_NAME,
null, "valueRange = 'MEDIUM'", null, null, null, null);
// Log number of rows from query
Log.d("CursorTest", "Row count: " + cursor.getCount());
try {
// get data from "factName" column of database
String columnName = cursor.getColumnName(0);
Log.d("CursorTest", "Column Name: " + columnName);
String data = cursor.getString(cursor.getColumnIndex(columnName));
} catch(Exception e) {
// Log exception thrown
Log.d("CursorTest", "Error getting data: " + e.getMessage());
}
}
And the log gives me the following:
D/CursorTest: Row count: 2
D/CursorTest: Column Name: factName
D/CursorTest: Error getting data: Index -1 requested, with a size of 2
Try to move the cursor to the first position first example
cursor.moveToPosition(0);
Your cursor initializes at index -1. You need to call moveToNext() or moveToPosition(int) to set it to a position with data in it.

Getting all database entries from android database

I have an android project, with a database where entries are logged as pairs with the same ID.
I have two for loops, one to get all entries of a certain ID, and one to get all entries in the table. These are then automatically populated into a listview.
The problem I have is that the program crashes when I attempt to use the forloop that gets all entries from the database, but it works perfectly fine when I use the for loop that wants all entries with the same ID. I have been commenting out the for loop im not using.
The for loops:
List<Assignment> list = db.getPickupDelivery(1);
for (int i = 0; i < list.size();i++)
{
allDeliveries.add(list.get(i));
}
List<Assignment> list = db.getAllAssignments();
for (int i = 0; i < list.size();i++)
{
allDeliveries.add(list.get(i));
}
The methods they call:
public List<Assignment> getPickupDelivery(int i) {
List<Assignment> assignments = new LinkedList<Assignment>();
//bygg query
String query = "SELECT * FROM " + TABLE_ASSIGNMENTS + " WHERE id = " + i;
//fa referens
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
//iterera och bygg och lagg till
Assignment assignment = null;
if (cursor.moveToFirst()) {
do {
assignment = new Assignment();
assignment.setID(Integer.parseInt(cursor.getString(0)));
assignment.setType(cursor.getString(1));
assignment.setSenderreceiver(cursor.getString(2));
assignment.setAdress(cursor.getString(3));
assignment.setTime(cursor.getString(4));
assignment.setZipcode(cursor.getString(5));
assignment.setContact(cursor.getString(6));
assignment.setPhone(cursor.getString(7));
assignment.setInstructions(cursor.getString(8));
//lagg till
assignments.add(assignment);
} while (cursor.moveToNext());
}
cursor.close();
Log.d("getPickupDelivery()", assignments.toString());
return assignments;
}
public List<Assignment> getAllAssignments() {
List<Assignment> assignments = new LinkedList<Assignment>();
//bygg query
String query = "SELECT * FROM " + TABLE_ASSIGNMENTS;
//fa referens
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
//iterera och bygg och lagg till
Assignment assignment = null;
if (cursor.moveToFirst()) {
do {
assignment = new Assignment();
assignment.setID(Integer.parseInt(cursor.getString(0)));
assignment.setType(cursor.getString(1));
assignment.setSenderreceiver(cursor.getString(2));
assignment.setAdress(cursor.getString(3));
assignment.setTime(cursor.getString(4));
assignment.setZipcode(cursor.getString(5));
assignment.setContact(cursor.getString(6));
assignment.setPhone(cursor.getString(7));
assignment.setInstructions(cursor.getString(8));
//lagg till
assignments.add(assignment);
} while (cursor.moveToNext());
}
cursor.close();
Log.d("getAllAssignments()", assignments.toString());
return assignments;
}
The error I get at the time of the crash is a an error that says "...MainActivity}: java.lang.NumberFormatException: Invalid int: "null""
My guess is that in your database definition, you didn't specify the ID column as INTEGER NOT NULL. So when you select every row, one or more of those rows has a null ID, which you're trying to parse as an int here:
assignment.setID(Integer.parseInt(cursor.getString(0)));
Change your database definition to require that the ID column is not null. You'll need to uninstall or clear data on your app so the database is recreated.
Also another tip - Android's SQLITE implementation will enforce that you have a column called "_id", so I'd suggest using that, not "id". Otherwise you'll end up with an extra column you don't need.
In your code:
assignment.setID(Integer.parseInt(cursor.getString(0)));
if cursor.getString(0) returns null, then Integer.parseInt(String str) will throw NumberFormatException.
Check this line or you can use try-catch and print the appropriate message in catch if you'll get NumberFormatException.
The exception is the hint. It says that a string null is being parsed as a number and this fails.
In your code there the place where it happens is:
assignment.setID(Integer.parseInt(cursor.getString(0)));
First you get a string from the cursor and then you pass it to Integer.parseInt for parsing.
So the cause of the problem is that you expect there to be no null values in the first column but there is at least one.
Also, your code is unnecessarily complex and inefficient. Instead of Integer.parseInt(cursor.getString(0)) you could write cursor.getInt(0) to directly get an int. This is also likely to throw an error on the null value though (but the error message might be more informative).

sqlite cursorindexoutofbound exception

in my android application i used the following function to retrieve the column from the table..the table contains value but it has an exception.
public String[] getactivelist(){
Log.v("ppp","getactivelist");
String[] actname=new String[50];
SQLiteDatabase db = this.getWritableDatabase();
Log.v("ppp","dbcrtd");
Cursor cursor = db.rawQuery("SELECT name FROM activelist ORDER BY time ASC", null);
Log.v("ppp","aftrcurser");
int i=0;
Log.v("ppp crsr",cursor.getString(0));
if (cursor.moveToFirst()) {
do {
actname[i]=cursor.getString(0);
Log.v("ppp crsr",cursor.getString(0));
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return actname;
}
the log cat shows the following error
04-04 01:19:41.170 2581-2601/com.example.pranavtv.loudspeaker V/ppp﹕ tryandroid.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 2
In your line
Log.v("ppp crsr", cursor.getString(0));
You try to get a string from the cursor. If there aren't any lines, it should throw the error observed.
You are calling the following line...
Log.v("ppp crsr",cursor.getString(0));
...before you have moved the position of your Cursor using...
if (cursor.moveToFirst()) {
By default, the position of a Cursor is initially set to be -1 which is before the first valid position as the first position which contains data is position 0.
Simply remove that line (the one before the if(...)) and you should be good to go.
On another note, in your do...while loop you are using...
actname[i]=cursor.getString(0);
...but you never increment i. Consequentially you will only ever modify actname[0] regardless of how many results are returned to the Cursor.

Categories

Resources