androidandroid-sqliteandroid-cursorjagged-arrays

Only getting first value from a record from cursor when trying to make a method to get a 2d array of strings to represent it


So I've got a database that's got one table, with two fields and one record. I'm using select to retrieve everything from that table, and passing the resulting cursor through this function to try to turn it into a jagged array of strings that will represent the table.

public String[][] cursorTo2dString (Cursor cursor, String[] fields) {

    int columnCount = cursor.getColumnCount();
    int count = cursor.getCount();
    String[][] string2dArray = new String[columnCount][count];

    Log.i("StringLengths", count + " & " + columnCount);
    Log.i("CursorConts", DatabaseUtils.dumpCursorToString(cursor));

    if (cursor.moveToFirst()) {

        for (int j=0; j<count && !cursor.isAfterLast(); j++) {

            for (int i=0; i<columnCount; i++) {

                Log.i("Cursor", cursor.getString(i));

                string2dArray[j][i] = cursor.getString(i);

                Log.i("StringPoint", string2dArray[j][i]);
            }

            cursor.moveToNext();
        }

    }

For reference, whatever appears as the TagIdNo value is currently just a randomly generated number, I'm not actually going to generate this randomly on implementation, I'm just using this for the purposes of testing.

This consistently crashes with the following appearing in the console:

I/StringLengths: 1 & 2
I/CursorConts: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@bd9f011
               0 {
                  TagIdNo=998
                  TagName=No Parental Permission
               }
               <<<<<
I/Cursor: 998
I/StringPoint: 998
I/Cursor: No Parental Permission
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.programming.workingpomproject, PID: 23796
                  java.lang.IllegalStateException: Could not execute method for android:onClick
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
                      at android.view.View.performClick(View.java:5226)
                      at android.view.View$PerformClick.run(View.java:21266)
                      at android.os.Handler.handleCallback(Handler.java:739)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:168)
                      at android.app.ActivityThread.main(ActivityThread.java:5845)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)
                   Caused by: java.lang.reflect.InvocationTargetException
                      at java.lang.reflect.Method.invoke(Native Method)
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
                      at android.view.View.performClick(View.java:5226) 
                      at android.view.View$PerformClick.run(View.java:21266) 
                      at android.os.Handler.handleCallback(Handler.java:739) 
                      at android.os.Handler.dispatchMessage(Handler.java:95) 
                      at android.os.Looper.loop(Looper.java:168) 
                      at android.app.ActivityThread.main(ActivityThread.java:5845) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687) 
                   Caused by: java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
                      at com.example.programming.workingpomproject.DbHelper.cursorTo2dString(DbHelper.java:132)
                      at com.example.programming.workingpomproject.DbHelper.select(DbHelper.java:89)
                      at com.example.programming.workingpomproject.DbHelper.select(DbHelper.java:92)
                      at com.example.programming.workingpomproject.MainActivity.testDbMethodGet(MainActivity.java:66)
                      at com.example.programming.workingpomproject.MainActivity.dbStuff(MainActivity.java:61)
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
                      at android.view.View.performClick(View.java:5226) 
                      at android.view.View$PerformClick.run(View.java:21266) 
                      at android.os.Handler.handleCallback(Handler.java:739) 
                      at android.os.Handler.dispatchMessage(Handler.java:95) 
                      at android.os.Looper.loop(Looper.java:168) 
                      at android.app.ActivityThread.main(ActivityThread.java:5845) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687) 

I've used lots of different methods of taking the contents of the cursor, and no matter what I can only get the first value (the random number in this case) I put into the database. I was wondering if anyone can see why I'm not getting my second value (currently "no parental permission"), and if they could advise me as to how to retrieve it.

Sorry if I've messed up any coding standards; this is my first Android project and my first time in Java but I've been working on this app for a good few months so I'm hoping I'm getting better.

Any and all advice welcome!

EDIT 1: If, as suggested by Giovanni, I swap the columns and rows in the instantiation, I get this instead:

String[][] string2dArray = new String[count][columnCount];

This leads to the following in the console, in the place of the other results:

    I/CursorConts: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@45e64e9
           0 {
              TagIdNo=3259
              TagName=No Parental Permission
           }
           <<<<<
I/Cursor: 3259
I/StringPoint: 3259
I/Cursor: No Parental Permission
I/StringPoint: No Parental Permission
I/MovePos: true & false
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.programming.workingpomproject, PID: 24606
                  java.lang.IllegalStateException: Could not execute method for android:onClick
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
                      at android.view.View.performClick(View.java:5226)
                      at android.view.View$PerformClick.run(View.java:21266)
                      at android.os.Handler.handleCallback(Handler.java:739)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:168)
                      at android.app.ActivityThread.main(ActivityThread.java:5845)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)
                   Caused by: java.lang.reflect.InvocationTargetException
                      at java.lang.reflect.Method.invoke(Native Method)
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
                      at android.view.View.performClick(View.java:5226) 
                      at android.view.View$PerformClick.run(View.java:21266) 
                      at android.os.Handler.handleCallback(Handler.java:739) 
                      at android.os.Handler.dispatchMessage(Handler.java:95) 
                      at android.os.Looper.loop(Looper.java:168) 
                      at android.app.ActivityThread.main(ActivityThread.java:5845) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687) 
                   Caused by: android.database.CursorIndexOutOfBoundsException: Index 1 requested, with a size of 1
                      at android.database.AbstractCursor.checkPosition(AbstractCursor.java:460)
                      at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
                      at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
                      at com.example.programming.workingpomproject.DbHelper.cursorTo2dString(DbHelper.java:155)
                      at com.example.programming.workingpomproject.DbHelper.select(DbHelper.java:89)
                      at com.example.programming.workingpomproject.DbHelper.select(DbHelper.java:92)
                      at com.example.programming.workingpomproject.MainActivity.testDbMethodGet(MainActivity.java:66)
                      at com.example.programming.workingpomproject.MainActivity.dbStuff(MainActivity.java:61)
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
                      at android.view.View.performClick(View.java:5226) 
                      at android.view.View$PerformClick.run(View.java:21266) 
                      at android.os.Handler.handleCallback(Handler.java:739) 
                      at android.os.Handler.dispatchMessage(Handler.java:95) 
                      at android.os.Looper.loop(Looper.java:168) 
                      at android.app.ActivityThread.main(ActivityThread.java:5845) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)

This cursor problem seems to be the root problem, the array index one just being something I messed up in an attempt to avoid the cursor error. Any further help is greatly appreciated!


Solution

  • You got an ArrayIndexOutOfBoundsException, which means that the array you want to assign in, does not have the correct size you are trying to access. For example, if I create an array like:

    String[] array = new String[2];
    int i = 3;
    String s = array[i];
    

    This will throw an exception, since my array has only place for 2 objects, not 3.

    Your array is String[][] string2dArray = new String[columnCount][count];

    I think you can fix it by changing it to:

    String[][] string2dArray = new String[count][columnCount];

    Because here:

    for (int j = 0; j < count && !cursor.isAfterLast(); j++) {
        for (int i = 0; i < columnCount; i++) {
            Log.i("Cursor", cursor.getString(i));
    
            // j should be count size, see the first for loop
    
            string2dArray[j][i] = cursor.getString(i);
            Log.i("StringPoint", string2dArray[j][i]);
        }
        cursor.moveToNext();
    }