0

I am getting the error shown below, how do I fix this problem?

 FATAL EXCEPTION: main
 java.lang.IllegalArgumentException: column '0' does not exist
 com.example.contentproviderexample.MainActivity.onLoadFinished(MainActivity.java:62)

the stack trace shows the error exists on line 62 of onLoadFinished method of MainActivity

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    adapter.swapCursor(cursor); // <-- stacktrace error
}

here is the code from the ProviderExample class that extends ContentProvider

  public class ProviderExample extends ContentProvider {

 public static final String DATABASE_NAME = "notes.db";
 public static final int DATABASE_VERSION = 1;
 public static final String TABLE_NAME = "notes";
 public static final String AUTHORITY =  "com.example.contentproviderexample.providerexample";
 public static final UriMatcher sUriMatcher;
 private static final int NOTES = 1;
 private static final int NOTES_ID = 2;
 private static HashMap<String, String> notesProjectionMap;

 static {
    sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    sUriMatcher.addURI(AUTHORITY, TABLE_NAME, NOTES);
    sUriMatcher.addURI(AUTHORITY, TABLE_NAME + "/#", NOTES_ID);
 }

  public static interface NoteItems extends BaseColumns {

    // notes in the CONTENT_URI is often plural where the actual table name is often singular version of this word
    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/notes");
    public static final String _ID = "_id";
    public static final String TITLE = "title";
    public static final String TEXT = "text";
    public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/vnd.example.providerexample";
    // static final String SINGLE_RECORD = "vnd.android.cursor.item/vnd.example.providerexample";
    public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/vnd.example.providerexample";
    // static final String MULTIPLE_RECORDS = "vnd.android.cursor.dir/vnd.example.providerexample"; 
    public static final String[] PROJECTION_ALL = {_ID, TITLE, TEXT};
    public static final String SORT_ORDER_DEFAULT = TITLE + " ASC";

  }

  private static class DatabaseHelper extends SQLiteOpenHelper{

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

 @Override
 public void onCreate(SQLiteDatabase db) {
 db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + NoteItems._ID + "  INTEGER PRIMARY KEY AUTOINCREMENT, " +  
         NoteItems.TITLE + " TEXT, " + NoteItems.TEXT + " TEXT);");
 }

 @Override
 public void onUpgrade(SQLiteDatabase db, int previousVersion, int newVersion) {
 db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
 onCreate(db);
 }

 }

 private DatabaseHelper dbHelper;

 @Override
 public boolean onCreate() {
dbHelper = new DatabaseHelper(getContext());
return true;
 }

 @Override
 public String getType(Uri uri) {
switch (sUriMatcher.match(uri)){
    case NOTES:
        return NoteItems.CONTENT_TYPE;
    case NOTES_ID:
        return NoteItems.CONTENT_ITEM_TYPE;
    default:
        throw new IllegalArgumentException("Unknown URI" + uri);
}

}

here is the MainActivity class

   public class MainActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor>{

private SimpleCursorAdapter adapter;
private LoaderManager loaderManager;
private CursorLoader cursorLoader;
private ListView listView;
private int primaryKey;
private String primaryKeyString;
private String testTitle;
private String testText;
private static final int LOADER_ID = 1;

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

    primaryKey = 0;
    testTitle = "test title";
    testText = "test text";

    ProviderExample providerExample = new ProviderExample();

    primaryKeyString = String.valueOf(primaryKey);
    getLoaderManager().initLoader(LOADER_ID, null, this);
    adapter = new SimpleCursorAdapter(this, R.layout.row_layout, null,
            new String[]{primaryKeyString, testTitle, testText}, new int[]{R.id.textView1, R.id.textView2, R.id.textView3},
            Adapter.NO_SELECTION);
    listView = (ListView) findViewById(R.id.listView1);
    listView.setAdapter(adapter);

    // load database with test values
    //loadDatabase();

} // end oncreate

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    String[] projection = {ProviderExample.NoteItems._ID, ProviderExample.NoteItems.TITLE, ProviderExample.NoteItems.TEXT };
    cursorLoader = new CursorLoader(this, ProviderExample.NoteItems.CONTENT_URI, projection, null, null, null);
    return cursorLoader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    adapter.swapCursor(cursor);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    adapter.swapCursor(null);
}
 }

EDIT:

added here is the query method code

  @Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
    qb.setTables(TABLE_NAME);
    qb.setProjectionMap(notesProjectionMap);
         switch(sUriMatcher.match(uri)){
         case NOTES:
             break;
         case NOTES_ID:
             selection = selection + "_id=" + uri.getLastPathSegment();
             break;
         default:
             throw new IllegalArgumentException("Unknown URI" + uri);    
         }
         SQLiteDatabase db = dbHelper.getReadableDatabase();
         Cursor c = qb.query(db, NoteItems.PROJECTION_ALL, selection, selectionArgs, null, null, sortOrder);
         c.setNotificationUri(getContext().getContentResolver(), uri);
         return c;
}
Kevik
  • 9,181
  • 19
  • 92
  • 148
  • use this one and try it primaryKey = 1; – Yogesh Tatwal May 15 '13 at 05:37
  • extract database and see what all it contains, that might help you – Pankaj Kushwaha May 15 '13 at 05:39
  • tried primaryKey = 1, and did not change result – Kevik May 15 '13 at 05:40
  • Did you clear your data? – Hoan Nguyen May 15 '13 at 05:54
  • yes, i did the delete data and delete app also – Kevik May 15 '13 at 05:56
  • tried it again after clearing data and deleting the app. and getting the same stacktrace error on the line, adapter.swapCursor(cursor); – Kevik May 15 '13 at 05:59
  • column 0 means _id, but I never used cursorLoader before so I do not think I can be of much help – Hoan Nguyen May 15 '13 at 06:00
  • You haven't change NoteItems._ID + " ID INTEGER PRIMARY KEY AUTOINCREMENT yet – Hoan Nguyen May 15 '13 at 06:01
  • ok, so it probably means that the _id is not being made. i will look into the database to see what is going on – Kevik May 15 '13 at 06:02
  • i forgot, i did change it in the project, but in the code I posted in the question i forgot to change it, as I cut and pasted that from the other question code, sorry about that. i will fix that now – Kevik May 15 '13 at 06:04
  • I think there is a conflict between your _ID and the baseColumns _ID, just remove yours – Hoan Nguyen May 15 '13 at 06:06
  • Just remove public static final String _ID = "_id"; and you do not have to change any other code – Hoan Nguyen May 15 '13 at 06:07
  • still same problem, for the record, I also tried some other things like changing the name of NoteItems._ID to BaseColumns._ID and removing _ID from the parameters of the db.execSQL() method in the onCreate of DatabaseHelper extends SQLiteOpenHelper class – Kevik May 15 '13 at 06:23
  • You cannot remove the _ID from the CREATE TABLE – Hoan Nguyen May 15 '13 at 06:44
  • Clean your project to see if it make any difference – Hoan Nguyen May 15 '13 at 06:44
  • i found this article of a similar problem, http://stackoverflow.com/questions/3359414/android-column-id-does-not-exist – Kevik May 15 '13 at 06:45
  • You did not include _id in your query? Whenever you deal with listview your query has to include the column _id – Hoan Nguyen May 15 '13 at 07:32
  • i am checking the android notepad sample project for comparisons http://developer.android.com/tools/samples/index.html – Kevik May 15 '13 at 07:37
  • what is your query that give you the cursor? – Hoan Nguyen May 15 '13 at 07:42
  • i added the query code to the question, at the bottom of the other code – Kevik May 15 '13 at 07:50
  • and in that query method it uses this for projection in query, public static final String[] PROJECTION_ALL = {_ID, TITLE, TEXT}; – Kevik May 15 '13 at 07:51
  • and here is the cursor loader method in the main activity: @Override public Loader onCreateLoader(int id, Bundle args) { // String[] projection = {ProviderExample.NoteItems._ID, ProviderExample.NoteItems.TITLE, ProviderExample.NoteItems.TEXT }; String[] projection = {ProviderExample.NoteItems._ID, ProviderExample.NoteItems.TITLE, ProviderExample.NoteItems.TEXT }; cursorLoader = new CursorLoader(this, ProviderExample.NoteItems.CONTENT_URI, projection, null, null, null); return cursorLoader; } – Kevik May 15 '13 at 07:55
  • Why do you use Adapter.NO_SELECTION? – Hoan Nguyen May 15 '13 at 07:58
  • http://helpmeco.de/2012/3/using-an-android-cursor-loader-with-a-content-provider from the tutorial, "The final argument in the SimpleCursorAdapter constructor is a flag for behavior. This example has Adapter.NO_SELECTION. This mean the Cursor will not re-query if the content is changed. You do not want CursorAdapter.FLAG_AUTO_REQUERY as this will make the Cursor requery using the UI thread which is what we avoiding by using a CursorLoader in the first place. The CursorLoader will handle any data changes and then call onLoadFinished so that everything happens in a background thread." – Kevik May 15 '13 at 08:05
  • I do not know where the author get the info but the official document seem to say there are only 2 valid flags or combination of the two. I always use 0. Try 0 see if it makes any difference – Hoan Nguyen May 15 '13 at 08:13
  • tried both 0 and 1, and same result – Kevik May 15 '13 at 08:20
  • I have no idea you should repost the question with title like "Cursor loader error column '0' does not exist" and get people who is familiar with cusor loader to help – Hoan Nguyen May 15 '13 at 08:30
  • that is a good idea, but first i will try to see if I can learn something from google content provider / cursor loader setup in the Notepad example project in the android sdk /tools folder. and I will post another question later. I am confident that I will figure this out. thank you for your help. you have answered multiple questions for me on databases. that really helped me with understanding SQLite. a few weeks ago I finally got an understanding of it. content providers and cursor loaders is the next step. – Kevik May 15 '13 at 08:52

0 Answers0