Search code examples
androidindexingnullcursor

Index 0 requested, with a size of 0 / SQLite Database and Cursor


I am currently working on an App which gets Data from different EditText Fields and Spinners. The Values are saved within a SQL Database. Another Activity is aimed to load those Data into a ListView. Actually, I am able to write Data into my SQL Database, so I can see the table within SQL Browser, but when I am pressing the Button for saving the Data, my App crashes. My first thought is that something with the cursor etc. is not working.

The logcat says this

09-16 11:52:09.811  30916-30916/uni_hannover.sportapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: uni_hannover.sportapp, PID: 30916
android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
        at android.database.AbstractCursor.checkPosition(AbstractCursor.java:426)
        at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
        at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
        at uni_hannover.sportapp.CyclingMemoDataSource.cursorToCyclingMemo(CyclingMemoDataSource.java:93)
        at uni_hannover.sportapp.CyclingMemoDataSource.createCyclingMemo(CyclingMemoDataSource.java:68)
        at uni_hannover.sportapp.Cycling_Create$1.onClick(Cycling_Create.java:101)
        at android.view.View.performClick(View.java:4780)
        at android.view.View$PerformClick.run(View.java:19866)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

This is my activity which should save the values into the DB and it actually works, because my SQLite Browser shows Values...

package uni_hannover.sportapp;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

import android.view.inputmethod.InputMethodManager;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;


public class Cycling_Create extends AppCompatActivity {

    public static final String LOG_TAG = MainActivity.class.getSimpleName();

    private CyclingMemoDataSource dataSource;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cycling__create);

        Log.d(LOG_TAG, "Das Datenquellen-Objekt wird angelegt.");
        dataSource = new CyclingMemoDataSource(this);
        dataSource.open();

        activateCreateButton();


    }


    @Override
    protected void onResume() {
        super.onResume();

        Log.d(LOG_TAG, "Die Datenquelle wird geöffnet.");
        dataSource.open();


    }

    @Override
    protected void onPause() {
        super.onPause();

        Log.d(LOG_TAG, "Die Datenquelle wird geschlossen.");
        dataSource.close();
    }

    private void activateCreateButton() {

        Button buttonCreateCyclingActivity = (Button) findViewById(R.id.create_cycling_activity);

        final EditText editNDA  = (EditText) findViewById(R.id.editNDA);
        final EditText editText2 = (EditText) findViewById(R.id.editText2);
        final Spinner spinner_alter = (Spinner) findViewById(R.id.spinner_alter);
        final Spinner spinner_geschlecht = (Spinner) findViewById(R.id.spinner_geschlecht);
        final Spinner spinner_dauer = (Spinner) findViewById(R.id.spinner_dauer);
        final Spinner spinner_geschwindigkeit = (Spinner) findViewById(R.id.spinner_geschwindigkeit);
        final Spinner spinner_streckenprofil = (Spinner) findViewById(R.id.spinner_streckenprofil);
        final Spinner spinner_distanz_cycling = (Spinner) findViewById(R.id.spinner_distanz_cycling);

        buttonCreateCyclingActivity.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                String NDAString = editNDA.getText().toString();
                String Startpunkt = editText2.getText().toString();

                if (TextUtils.isEmpty(NDAString)) {
                    editNDA.setError(getString(R.string.editText_errorMessage));
                    return;
                }
                if (TextUtils.isEmpty(Startpunkt)) {
                    editText2.setError(getString(R.string.editText_errorMessage));
                    return;
                }

                editNDA.setText("");
                editText2.setText("");

                String Age = spinner_alter.getSelectedItem().toString();
                String Geschlecht = spinner_geschlecht.getSelectedItem().toString();
                String Dauer = spinner_dauer.getSelectedItem().toString();
                String Geschwindigkeit = spinner_geschwindigkeit.getSelectedItem().toString();
                String Streckenprofil = spinner_streckenprofil.getSelectedItem().toString();
                String Distanz = spinner_distanz_cycling.getSelectedItem().toString();



                dataSource.createCyclingMemo (NDAString, Startpunkt, Age, Geschlecht, Dauer, Geschwindigkeit, Streckenprofil, Distanz);

                InputMethodManager inputMethodManager;
                inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
                if (getCurrentFocus() != null) {
                    inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
                }



            }
        });

            }



            @Override
            public boolean onCreateOptionsMenu(Menu menu) {
                // Inflate the menu; this adds items to the action bar if it is present.
                getMenuInflater().inflate(R.menu.menu_main, menu);
                return true;
            }

            @Override
            public boolean onOptionsItemSelected(MenuItem item) {
                // Handle action bar item clicks here. The action bar will
                // automatically handle clicks on the Home/Up button, so long
                // as you specify a parent activity in AndroidManifest.xml.
                int id = item.getItemId();

                //noinspection SimplifiableIfStatement
                if (id == R.id.action_settings) {
                    return true;
                }

                return super.onOptionsItemSelected(item);
            }
        }

And last but not least I got my DataSource Activity, where I think the mistake is.

package uni_hannover.sportapp;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import android.content.ContentValues;
import android.database.Cursor;
import java.util.ArrayList;
import java.util.List;


public class CyclingMemoDataSource {

    private static final String LOG_TAG =
            CyclingMemoDataSource.class.getSimpleName();

    private SQLiteDatabase database;
    private CyclingMemoDBHelper dbHelper;

    private String[] columns = {
            CyclingMemoDBHelper.COLUMN_NDA,
            CyclingMemoDBHelper.COLUMN_Startpunkt,
            CyclingMemoDBHelper.COLUMN_Age,
            CyclingMemoDBHelper.COLUMN_Geschlecht,
            CyclingMemoDBHelper.COLUMN_Dauer,
            CyclingMemoDBHelper.COLUMN_Geschwindigkeit,
            CyclingMemoDBHelper.COLUMN_Streckenprofil,
            CyclingMemoDBHelper.COLUMN_Distanz

    };

    public CyclingMemoDataSource (Context context){
        dbHelper = new CyclingMemoDBHelper(context);
    }

    public void open() {
        Log.d(LOG_TAG, "Eine Referenz auf die Datenbank wird jetzt angefragt.");
        database = dbHelper.getWritableDatabase();
        Log.d(LOG_TAG, "Datenbank-Referenz erhalten. Pfad zur Datenbank: " + database.getPath());
    }

    public void close() {
        dbHelper.close();
        Log.d(LOG_TAG, "Datenbank mit Hilfe des DbHelpers geschlossen.");
    }

    public CyclingMemo createCyclingMemo(String NDA, String Startpunkt, String Age, String Geschlecht, String Dauer,
                                         String Geschwindigkeit, String Streckenprofil, String Distanz) {
        ContentValues values = new ContentValues();
        values.put(CyclingMemoDBHelper.COLUMN_NDA, NDA);
        values.put(CyclingMemoDBHelper.COLUMN_Startpunkt, Startpunkt);
        values.put(CyclingMemoDBHelper.COLUMN_Age, Age);
        values.put(CyclingMemoDBHelper.COLUMN_Geschlecht, Geschlecht);
        values.put(CyclingMemoDBHelper.COLUMN_Dauer, Dauer);
        values.put(CyclingMemoDBHelper.COLUMN_Geschwindigkeit, Geschwindigkeit);
        values.put(CyclingMemoDBHelper.COLUMN_Streckenprofil, Streckenprofil);
        values.put(CyclingMemoDBHelper.COLUMN_Distanz, Distanz);


        long insertNDA = database.insert(CyclingMemoDBHelper.TABLE_CYCLING, null, values);

        Cursor cursor = database.query(CyclingMemoDBHelper.TABLE_CYCLING,
                columns, CyclingMemoDBHelper.COLUMN_NDA + "=" + insertNDA,
                null, null, null, null);


        cursor.moveToFirst();
        CyclingMemo cyclingMemo = cursorToCyclingMemo(cursor);
        cursor.close();

        return cyclingMemo;
    }

    private CyclingMemo cursorToCyclingMemo(Cursor cursor) {


        int idNDA =
                cursor.getColumnIndex(CyclingMemoDBHelper.COLUMN_NDA);
        int idStartpunkt =
                cursor.getColumnIndex(CyclingMemoDBHelper.COLUMN_Startpunkt);
        int idAge =
                cursor.getColumnIndex(CyclingMemoDBHelper.COLUMN_Age);
        int idGeschlecht =
                cursor.getColumnIndex(CyclingMemoDBHelper.COLUMN_Geschlecht);
        int idDauer =
                cursor.getColumnIndex(CyclingMemoDBHelper.COLUMN_Dauer);
        int idGeschwindigkeit =
                cursor.getColumnIndex(CyclingMemoDBHelper.COLUMN_Geschwindigkeit);
        int idStreckenprofil =
                cursor.getColumnIndex(CyclingMemoDBHelper.COLUMN_Streckenprofil);
        int idDistanz =
                cursor.getColumnIndex(CyclingMemoDBHelper.COLUMN_Distanz);

        String NDA = cursor.getString(idNDA);
        String Startpunkt = cursor.getString(idStartpunkt);
        String Age = cursor.getString(idAge);
        String Geschlecht = cursor.getString(idGeschlecht);
        String Dauer = cursor.getString(idDauer);
        String Geschwindigkeit = cursor.getString(idGeschwindigkeit);
        String Streckenprofil = cursor.getString(idStreckenprofil);
        String Distanz = cursor.getString(idDistanz);



        CyclingMemo cyclingMemo = new CyclingMemo(NDA, Startpunkt, Age, Geschlecht, Dauer, Geschwindigkeit, Streckenprofil, Distanz );

        return cyclingMemo;
    }

    public List<CyclingMemo> getAllCyclingMemos() {
        List<CyclingMemo> cyclingMemoList = new ArrayList<>();

        Cursor cursor = database.query(CyclingMemoDBHelper.TABLE_CYCLING,
                columns, null, null, null, null, null);

        cursor.moveToFirst();
        CyclingMemo cyclingMemo;

        while(!cursor.isAfterLast()) {
            cyclingMemo = cursorToCyclingMemo(cursor);
            cyclingMemoList.add(cyclingMemo);
            Log.d(LOG_TAG, "ID: " + cyclingMemo.getNDA() + ", Inhalt: " + cyclingMemo.toString());
            cursor.moveToNext();
        }

        cursor.close();

        return cyclingMemoList;
    }


}

I really tried a lot of different things but was not able to finde the mistake. I would really appreciate if there is someone who is experienced and is able to see the mistake really quick...

Edit: Here you can see my structure of my table.

public static final String SQL_CREATE =
            "CREATE TABLE " + TABLE_CYCLING +
                    "(" + COLUMN_NDA + " TEXT PRIMARY KEY , " +
                    COLUMN_Startpunkt + " TEXT NOT NULL, " +
                    COLUMN_Age + " TEXT NOT NULL, " +
                    COLUMN_Geschlecht + " TEXT NOT NULL, " +
                    COLUMN_Dauer + " TEXT NOT NULL, " +
                    COLUMN_Geschwindigkeit + " TEXT NOT NULL, " +
                    COLUMN_Streckenprofil + " TEXT NOT NULL, " +
                    COLUMN_Distanz + " TEXT NOT NULL);";

Finally here you can see my get and set data, in which I think is a mistake, because most of the definitions are not highlighted...

I just went through my Data activity and saw that there is probably another or the main mistake, when I tried to enter the new ID values:package uni_hannover.sportapp;


public class CyclingMemo {

    private long id;
    private String NDA;
    private String Startpunkt;
    private String Age;
    private String Geschlecht;
    private String Dauer;
    private String Geschwindigkeit;
    private String Streckenprofil;
    private String Distanz;
    private long id;

    public CyclingMemo(String NDA, String Startpunkt, String Age, String Geschlecht, String Dauer,
                       String Geschwindigkeit, String Streckenprofil, String Distanz, long id){


        this.NDA = NDA;
        this.Startpunkt = Startpunkt;
        this.Age = Age;
        this.Geschlecht = Geschlecht;
        this.Dauer = Dauer;
        this.Geschwindigkeit = Geschwindigkeit;
        this.Streckenprofil = Streckenprofil;
        this.Distanz = Distanz;
        this.id = id;


    }

    public String getNDA() {
        return NDA;
    }

    public void setNDA(String NDA) {
        this.NDA = NDA;
    }



    public String getStartpunkt() {
        return Startpunkt;
    }

    public void setStartpunkt(String Startpunkt) {
        this.Startpunkt = Startpunkt;
    }



    public String getAge() {
        return Age;
    }

    public void setAge(String Age) {
        this.Age = Age;
    }



    public String getGeschlecht() {
        return Geschlecht;
    }

    public void setGeschlecht(String Geschlecht) {
        this.Geschlecht = Geschlecht;
    }



    public String getDauer() {
        return Dauer;
    }

    public void setDauer(String Dauer) {
        this.Dauer = Dauer;
    }



    public String getGeschwindigkeit() {
        return Geschwindigkeit;
    }

    public void setGeschwindigkeit(String Geschwindigkeit) {
        this.Geschwindigkeit = Geschwindigkeit;
    }



    public String getStreckenprofil() {
        return Streckenprofil;
    }

    public void setStreckenprofil(String Streckenprofil) {
        this.Streckenprofil = Streckenprofil;
    }



    public String getDistanz() {
        return Distanz;
    }

    public void setDistanz(String Distanz) {
        this.Distanz = Distanz;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }


    @Override
    public String toString() {
        String output = NDA + Startpunkt + Age + Geschlecht + Dauer + Geschwindigkeit + Streckenprofil + Distanz;

        return output;
    }
}

Solution

  • Note that the return value of insert in SQLiteDatabase is the row ID of the newly inserted row rather than CyclingMemoDBHelper.COLUMN_NDA as in your code. So this line database.query(CyclingMemoDBHelper.TABLE_CYCLING,columns, CyclingMemoDBHelper.COLUMN_NDA + "=" + insertNDA,null, null, null, null); will return an empty cursor.

    I suggest you firstly add a column named _id to your table, that is

    public static final String SQL_CREATE =
            "CREATE TABLE " + TABLE_CYCLING +
                    "(" + "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                    COLUMN_NDA + " TEXT, " +
                    COLUMN_Startpunkt + " TEXT NOT NULL, " +
                    COLUMN_Age + " TEXT NOT NULL, " +
                    COLUMN_Geschlecht + " TEXT NOT NULL, " +
                    COLUMN_Dauer + " TEXT NOT NULL, " +
                    COLUMN_Geschwindigkeit + " TEXT NOT NULL, " +
                    COLUMN_Streckenprofil + " TEXT NOT NULL, " +
                    COLUMN_Distanz + " TEXT NOT NULL);";
    

    Then make some changes in createCyclingMemo as:

    Cursor cursor = database.query(CyclingMemoDBHelper.TABLE_CYCLING,
                columns,  "_id =" + insertNDA,
                null, null, null, null);
    CyclingMemo cyclingMemo;
    if (cursor != null && cursor.moveToFirst()) {
        cyclingMemo = cursorToCyclingMemo(cursor);
        cursor.close();
    }
    return cyclingMemo;// Be careful cyclingMemo might be null!