Cursor Index Issue - android

Can anyone please explain why this method in my database helper class is not working properly. I query a table named Tutorial with a layout column.
public String getLayout(int layout_position)
{
String SQL = "SELECT * FROM Tutorial";
Cursor cursor = database.rawQuery(SQL, null);
cursor.moveToFirst();
cursor.move(layout_position);
String layout = cursor.getString(cursor.getColumnIndex("layout"));
System.out.println(">>>DBhelper->getLayout: "+ layout);
return (layout);
}
The cursor is moved by int layout_position, which is incremented every time before I call the method. Everything actually works just fine until layout_position reaches 2. Then I get this error from logcat
07-20 09:35:41.479: E/AndroidRuntime(4630): android.database.CursorIndexOutOfBoundsException: Index 2 requested, with a size of 2
The Tutorial table is pre-populated with 4 rows, so I'm not sure what is happening here?

cursor.move moves the cursors position by the amount specified in the argument. You are most likely looking for cursor.moveToPosition(layout_position)

Related

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))));
}

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.

Retrieve the contents of first three rows of a android database using a cursor

Currently in my code i'm using a cursor to retrieve the entire database
My code is
public Cursor getAll() {
return (getReadableDatabase().rawQuery(
"SELECT _id, note, amt, dueDate FROM New", null));
}
The function of retrieving the contents is to populate the same in a listview.
Now I want to retrieve the contents of the first three rows of the same database using cursor to display in another listview.
Need Help, Thanks in Advance.
The correct way to do it is to limit the result number to three:
"SELECT _id, note, amt, dueDate FROM New ORDER BY _id LIMIT 3"
Then you just iterate over the cursor (as usual)
Since you've already obtained a Cursor, in order to get the first three rows of the result, you do this:
Cursor cursor = getAll();
cursor.moveToFirst();
int count = 0;
while(!cursor.isAfterLast() && count < 3)
{
// Grab your data here using cursor.getLong(0), cursor.getString(1) etc.
// and store it an array.
count++;
cursor.moveToNext();
}
cursor.close();
You may want to limit the query results to at most three by adding a LIMIT 0,3 statement to your SQL. Having obtained an array of at most three elements containing your records, you can then proceed to place them in the other ListView you are referring to. You do this by adding them to this ListView's source array. Then call the ListView adapter's notifyDataSetChanged method to have it update itself.
So you can do this in two ways:
Create a separate select:
SELECT * FROM Table_Name LIMIT 3;
Select three rows from cursor:
int n = 0;
cursor.moveToFirst();
while (!cur.isAfterLast() && n < 3) {
// Use the data
n++;
cur.moveToNext();
}
cur.close();

Error when accessing cursor elements

I'm trying to get all the IDs in the table by cursor. The table has 4 rows, and when I try to access the cursor by any index aside from 0 , the App crashes.
Guys, the problem still exists and even c.getInt(0) doesn't work...I really dont know where my mistake is???
the logcat also suggests that the error might be comes from
Toast.makeText(getApplicationContext(), "id="+dbd.getIDs()[0], Toast.LENGTH_SHORT).show();
I mean c.getint(0) returns the id, c.getint(2) returns error. Here is the code:
public int []getIDs() {
SQLiteDatabase db = this.getReadableDatabase();
SQLiteCursor c = (SQLiteCursor) db.rawQuery("SELECT " + BaseColumns._ID + " FROM Demo ", null);
int []r = new int[c.getCount()];
c.moveToFirst();
do{
r[c.getPosition()] = c.getInt(0);
}while(c.moveToNext());
c.close();
db.close();
return r;
}
Your select is a projection onto the ID column (select columns from ..., columns are the column ids you are interested in, and you specified just one). Thus the answer just has one column, namely the ID. Any access to columns with index > 0 will not work.
To access the other columns name them in the projection in your query.
c.getInt(0) return only value of first colunn from current row.
try this code:
do{
int r = c.getInt(0);
Log.d("Your class name","id value = "+r);
}while(c.moveToNext());
You can imagine Cursor as a table. There are rows and columns. And a cursor is pointing on a particular row in this table. Thus, to get all id's you should move across all rows.
c.getInt(ind) In this statement index is pointing on the column with index ind. Thus, in your code you try to get the second and third column and according to your code there is no these column.
To get a proper code you should create a loop and traverse all rows of your cursor. Also you should use c.getInt(0) to get the columns values.
Assuming you are selecting the appropriate Data, your problem is that you're not preparing the Cursor to be iterated.
Before iterating, call:
c.moveToFirst();
Like this:
int []r = new int [c.getCount()];
c.moveToFirst();
do{
r[c.getPosition()] = c.getInt(0);
}while(c.moveToNext());
c.close();
db.close();
return r;
This is well indicated in LogCat. I can't remember how it's put, but the message is very suggestive. Please post as much of the Log as possible, especially the good bits.
Also, I modified 'r' to be an array. As it was you were only returning the value of the last row.

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

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

Categories

Resources