0

I am trying to populate a listview from a database. When I try to use a cursor to do it I get an error:

android.database.sqlite.SQLiteException: no such column: _id (code 1): , while compiling: SELECT _id FROM contacts WHERE _id ORDER BY name DESC

Here is my code:

MainActivity.java

package com.boggs.barr.barrboggscontactlist;

import android.content.ContentValues;
import android.content.Loader;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

public class MainActivity extends AppCompatActivity {

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

    }
    public static final String KEY_ID = "_id";


    private void populateListView() {

        String[] projection = {
                KEY_ID
        };

        FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getApplicationContext());
        SQLiteDatabase db = mDbHelper.getWritableDatabase();

        String sortOrder =
                FeedReaderContract.FeedEntry.COLUMN_NAME_NAME + " DESC";

        Cursor cursor = db.query(
                FeedReaderContract.FeedEntry.TABLE_NAME,  // The table to query
                projection,                               // The columns to return
                KEY_ID,                                // The columns for the WHERE clause
                null,                            // The values for the WHERE clause
                null,                                     // don't group the rows
                null,                                     // don't filter by row groups
                sortOrder                                 // The sort order
        );
        String[] fromColumns = new String[] {FeedReaderContract.FeedEntry.COLUMN_NAME_NAME, FeedReaderContract.FeedEntry.COLUMN_NAME_PHONE};
        int[] toViews = {R.id.name, R.id.phone};

        SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
                R.layout.name_and_number, cursor, fromColumns, toViews, 0);

        ListView listView = (ListView) findViewById(R.id.listView);
        listView.setAdapter(adapter);


}

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

FeedReaderDbHelper.java

    package com.boggs.barr.barrboggscontactlist;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.sql.RowId;

/**
 * Created by adnroid developer site
 */
public class FeedReaderDbHelper extends SQLiteOpenHelper {
    // If you change the database schema, you must increment the database version.
    public static final int DATABASE_VERSION = 1;
    public static final String DATABASE_NAME = "FeedReader.db";
    public static final String LONG_TYPE = " Long";
    public static final String STRING_TYPE = " STRING";
    public static final String BYTE_TYPE = " BYTE";
    private static final String COMMA_SEP = ",";
    private static final String SQL_CREATE_ENTRIES =
            "CREATE TABLE " + FeedReaderContract.FeedEntry.TABLE_NAME + " (" +
                    FeedReaderContract.FeedEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                    FeedReaderContract.FeedEntry.COLUMN_NAME_PICTURE + STRING_TYPE + COMMA_SEP +
                    FeedReaderContract.FeedEntry.COLUMN_NAME_NAME + STRING_TYPE + COMMA_SEP +
                    FeedReaderContract.FeedEntry.COLUMN_NAME_EMAIL + STRING_TYPE + COMMA_SEP +
                    FeedReaderContract.FeedEntry.COLUMN_NAME_PHONE + STRING_TYPE +
                    ")";


    private static final String SQL_DELETE_ENTRIES =
            "DROP TABLE IF EXISTS " + FeedReaderContract.FeedEntry.TABLE_NAME;

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

    public void onCreate(SQLiteDatabase db) {
        db.execSQL(SQL_CREATE_ENTRIES);
    }

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // This database is only a cache for online data, so its upgrade policy is
        // to simply to discard the data and start over
        db.execSQL(SQL_DELETE_ENTRIES);
        onCreate(db);
    }
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        onUpgrade(db, oldVersion, newVersion);
    }
}

FeedReaderContract.java

    package com.boggs.barr.barrboggscontactlist;

import android.provider.BaseColumns;
import android.support.annotation.Nullable;

/**
 * Created by android developer site.
 * attempted to do database ran out of time
 */
public final class FeedReaderContract {
    // To prevent someone from accidentally instantiating the contract class,
    // give it an empty constructor.
    public FeedReaderContract() {}

    /* Inner class that defines the table contents */
    public static abstract class FeedEntry implements BaseColumns {
        public static final String TABLE_NAME = "contacts";
        public static final String _ID = "_id";
        public static final String COLUMN_NAME_PICTURE = "picture";
        public static final String COLUMN_NAME_NAME = "name";
        public static final String COLUMN_NAME_EMAIL = "email";
        public static final String COLUMN_NAME_PHONE = "phone";
        public static  final Nullable COLUMN_NAME_NULLABLE = null;

    }
}

Ive read that I need to pass the ID to the cursor? But I am not sure what that means. To me it should work since I am include the ID in the list of columns to include in the cursor. Any help is appreciated!

Edit: I asked this because people that had the same problem were proposed solutions that did not work for me. They kept suggesting to try and use RowId or .moveToFirst to include the ID. Laalto was proposed a solution that worked for me.

1 Answers1

0

As user laalto pointed out, I needed to uninstall the app from the emulator because I made a schema change. Once I did that, the app started working.