-1

I am developing an application and after I enter the login details the app crashes.I think the error is due to the problem of database linking and fetching and tried few solutions posted online, but nothing worked. What can i do to solve this?

06-21 13:21:04.590 1913-1913/in.co.arrow E/AndroidRuntime: FATAL EXCEPTION: main
Process: in.co.arrow, PID: 1913
java.lang.IllegalStateException: Couldn't read row 0, col 4 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
    at android.database.CursorWindow.nativeGetString(Native Method)
    at android.database.CursorWindow.getString(CursorWindow.java:438)
    at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
    at in.co.arrow.sql.SqliteHelper.Authenticate(SqliteHelper.java:140)
    at in.co.arrow.LoginActivity$1.onClick(LoginActivity.java:55)
    at android.view.View.performClick(View.java:6367)
    at android.view.View$PerformClick.run(View.java:25032)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6753)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:482)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

here are my SqliteHelper and LoginActivity classes

package in.co.arrow;


public class LoginActivity extends AppCompatActivity {

    EditText editTextEmail;
    EditText editTextPassword;

    TextInputLayout textInputLayoutEmail;
    TextInputLayout textInputLayoutPassword;

    Button buttonLogin;

    SqliteHelper sqliteHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        sqliteHelper = new SqliteHelper(this);
        initCreateAccountTextView();
        initViews();

        buttonLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (validate()) {

                    String Email = editTextEmail.getText().toString();
                    String Password = editTextPassword.getText().toString();

                    User currentUser = sqliteHelper.Authenticate(new User(null,null,null,null,null,Email,Password,null,null,null,null,null,null));


                    if (currentUser != null) {
                        Snackbar.make(buttonLogin, "Successfully Logged in!", Snackbar.LENGTH_LONG).show();

                       /* Intent intent=new Intent(LoginActivity.this,HomeScreenActivity.class);
                        startActivity(intent);
                        finish(); */
                    } else {


                        Snackbar.make(buttonLogin, "Failed to log in , please try again", Snackbar.LENGTH_LONG).show();

                    }
                }
            }
        });


    }

    private void initCreateAccountTextView() {
        TextView textViewCreateAccount = (TextView) findViewById(R.id.textViewCreateAccount);
        textViewCreateAccount.setText(fromHtml("<font color='#ffffff'>I don't have account yet. </font><font color='#0c0099'>create one</font>"));
        textViewCreateAccount.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(LoginActivity.this, RegisterActivity.class);
                startActivity(intent);
            }
        });
    }

    private void initViews() {
        editTextEmail = (EditText) findViewById(R.id.editTextEmail);
        editTextPassword = (EditText) findViewById(R.id.editTextPassword);
        textInputLayoutEmail = (TextInputLayout) findViewById(R.id.textInputLayoutEmail);
        textInputLayoutPassword = (TextInputLayout) findViewById(R.id.textInputLayoutPassword);
        buttonLogin = (Button) findViewById(R.id.buttonLogin);

    }

    @SuppressWarnings("deprecation")
    public static Spanned fromHtml(String html) {
        Spanned result;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            result = Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
        } else {
            result = Html.fromHtml(html);
        }
        return result;
    }

    public boolean validate() {
        boolean valid = false;

        String Email = editTextEmail.getText().toString();
        String Password = editTextPassword.getText().toString();


        if (!android.util.Patterns.EMAIL_ADDRESS.matcher(Email).matches()) {
            valid = false;
            textInputLayoutEmail.setError("Please enter valid email!");
        } else {
            valid = true;
            textInputLayoutEmail.setError(null);
        }


        if (Password.isEmpty()) {
            valid = false;
            textInputLayoutPassword.setError("Please enter valid password!");
        } else {
            if (Password.length() > 5) {
                valid = true;
                textInputLayoutPassword.setError(null);
            } else {
                valid = false;
                textInputLayoutPassword.setError("Password is to short!");
            }
        }

        return valid;
    }


}

SqliteHelper.java

package in.co.arrow.sql;



public class SqliteHelper extends SQLiteOpenHelper {


    public static final String DATABASE_NAME = "arrow";

    public static final int DATABASE_VERSION = 1;

    public static final String TABLE_USERS = "users";

    public static final String KEY_ID = "id";

    public static final String KEY_USER_NAME = "username";

    public static final String KEY_FIRST_NAME="firstname";

    public static final String KEY_LAST_NAME="lastname";

    public static final String KEY_MOBILE_NO="mobileno";

    public static final String KEY_EMAIL = "email";


    public static final String KEY_PASSWORD = "password";

    public static final String KEY_FATHERS_NAME="fathersname";

    public static final String KEY_GENDER="gender";

    public static final String KEY_INST_NAME="instname";

    public static final String KEY_DOB="dob";

    public static final String KEY_BRANCH="branch";

    public static final String KEY_YOP="yop";


    public static final String SQL_TABLE_USERS = " CREATE TABLE " + TABLE_USERS
            + " ( "
            + KEY_ID + " INTEGER PRIMARY KEY, "
            + KEY_USER_NAME + " TEXT, "
            + KEY_FIRST_NAME + " TEXT,"
            + KEY_LAST_NAME + " TEXT,"
            + KEY_MOBILE_NO + " TEXT,"
            + KEY_EMAIL + " TEXT, "
            + KEY_PASSWORD + " TEXT, "
            + KEY_FATHERS_NAME + " TEXT,"
            + KEY_GENDER + " TEXT,"
            + KEY_INST_NAME + " TEXT,"
            + KEY_DOB + " TEXT,"
            + KEY_BRANCH + " TEXT,"
            + KEY_YOP + " TEXT "
            + " ) ";


    public SqliteHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {

        sqLiteDatabase.execSQL(SQL_TABLE_USERS);

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

        sqLiteDatabase.execSQL(" DROP TABLE IF EXISTS " + TABLE_USERS);
    }

    public void addUser(User user) {

        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();

        values.put(KEY_USER_NAME, user.userName);

        values.put(KEY_FIRST_NAME, user.firstname);

        values.put(KEY_LAST_NAME, user.lastname);

        values.put(KEY_GENDER, user.gender);

        values.put(KEY_FATHERS_NAME, user.fathersname);

        values.put(KEY_MOBILE_NO, user.mobileno);

        values.put(KEY_EMAIL, user.email);

        values.put(KEY_PASSWORD, user.password);

        values.put(KEY_DOB, user.dob);

        values.put(KEY_INST_NAME,user.instname);

        values.put(KEY_BRANCH, user.branch);

        values.put(KEY_YOP, user.yop);

        long todo_id = db.insert(TABLE_USERS, null, values);
    }

    public User Authenticate(User user) {
        SQLiteDatabase db = this.getReadableDatabase();
        @SuppressLint("Recycle") Cursor cursor = db.query(TABLE_USERS,
                new String[]{KEY_ID, KEY_USER_NAME, KEY_EMAIL, KEY_PASSWORD},
                KEY_EMAIL + "=?",
                new String[]{user.email},
                null, null, null);

        if (cursor != null && cursor.moveToFirst()&& cursor.getCount()>0) {

            User user1;
            user1 = new User(cursor.getString(0), cursor.getString(1), cursor.getString(2), cursor.getString(3),cursor.getString(4), cursor.getString(5), cursor.getString(6),cursor.getString(7),cursor.getString(8),cursor.getString(9),cursor.getString(10),cursor.getString(11),cursor.getString(12));

            if (user.password.equalsIgnoreCase(user1.password)) {
                return user1;
            }
        }

        return null;
    }

    public boolean isEmailExists(String email) {
        SQLiteDatabase db = this.getReadableDatabase();
        @SuppressLint("Recycle") Cursor cursor = db.query(TABLE_USERS,// Selecting Table
                new String[]{KEY_ID, KEY_USER_NAME, KEY_EMAIL, KEY_PASSWORD},
                KEY_EMAIL + "=?",
                new String[]{email},
                null, null, null);

        if (cursor != null && cursor.moveToFirst()&& cursor.getCount()>0) {

            return true;
        }


        return false;
    }
}
Armali
  • 18,255
  • 14
  • 57
  • 171
  • "Make sure the Cursor is initialized correctly before accessing data from it" -> at the line 140 of your class SqliteHelper, you are accessing a cursor. But this cursor wasn't initialize correctly before. – vincrichaud Jun 21 '18 at 08:19
  • Please Take reference from this tutorial http://coderzpassion.com/android-simple-login-example-using-sqlite/ – Hitesh Anshani Jun 21 '18 at 08:22
  • Possible duplicate of [Unfortunately MyApp has stopped. How can I solve this?](https://stackoverflow.com/questions/23353173/unfortunately-myapp-has-stopped-how-can-i-solve-this) – 2Dee Jun 21 '18 at 08:23
  • Review|Help and Improvement: corrected code formatting – Armali Jun 21 '18 at 09:43

2 Answers2

0

Your cursor has only 4 columns:

new String[]{KEY_ID, KEY_USER_NAME, KEY_EMAIL, KEY_PASSWORD}

but you are trying to read 13 columns out of it. It fails on the first non-existing one at index 4.

You can add all the columns you're reading to your projection.

laalto
  • 150,114
  • 66
  • 286
  • 303
0

Your isssue is that you have only specified 4 columns to be extracted into the cursor, yet you are trying to get data from 13 columns.

You could change :-

Cursor cursor = db.query(TABLE_USERS,
                new String[]{KEY_ID, KEY_USER_NAME, KEY_EMAIL, KEY_PASSWORD},
                KEY_EMAIL + "=?",
                new String[]{user.email},
                null, null, null);

to either :-

Cursor cursor = db.query(TABLE_USERS,
                null, // <<<< gets all columns from the table
                KEY_EMAIL + "=?",
                new String[]{user.email},
                null, null, null);

or :-

Cursor cursor = db.query(TABLE_USERS,
                new String[]{KEY_ID, KEY_USER_NAME, KEY_EMAIL, KEY_PASSWORD, KEY_FIRST_NAME, KEY_LAST_NAME, KEY_GENDER, KEY_FATHERS_NAME, KEY_MOBILE_NO, KEY_DOB, KEY_INST_NAME, KEY_BRANCH, KEY_YOP},
                KEY_EMAIL + "=?",
                new String[]{user.email},
                null, null, null);

The above two assuming that you want data from all columns.

or you could reduce the number of columns from which you retrieve data but that would depend upon what constructors are available for a User object.

MikeT
  • 51,415
  • 16
  • 49
  • 68