Search code examples
androidandroid-cursorloader

The app crashes when start when using cursorloader


The app is crashes when first lanuched and give me those error when using the CursorLoaders callback methods(before that I was loading the DB table in the main UI and nothing happen in this situation but when change to CursorLoader to load and change the UI in Background this problem occured), I didn't know the line of code that makes the app crashes but I think the imports has a hand on it, please help?

   03-30 02:10:06.441    1564-1591/android.process.acore E/DatabaseUtils﹕   Writing exception to parcel
   java.lang.IllegalArgumentException: Invalid column name
        at    android.database.sqlite.SQLiteQueryBuilder.computeProjection(SQLiteQueryBuilder.java:632)
        at android.database.sqlite.SQLiteQueryBuilder.buildQuery(SQLiteQueryBuilder.java:447)
        at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:393)
        at com.android.providers.contacts.ContactsProvider2.query(ContactsProvider2.java:6493)
        at com.android.providers.contacts.ContactsProvider2.queryLocal(ContactsProvider2.java:6443)
        at com.android.providers.contacts.ContactsProvider2.query(ContactsProvider2.java:5038)
        at android.content.ContentProvider$Transport.query(ContentProvider.java:211)
        at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:112)
        at android.os.Binder.execTransact(Binder.java:446)
03-30 02:10:06.446  24098-24122/com.example.android.pets E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
Process: com.example.android.pets, PID: 24098
java.lang.RuntimeException: An error occured while executing doInBackground()
        at android.os.AsyncTask$3.done(AsyncTask.java:304)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
        at java.util.concurrent.FutureTask.run(FutureTask.java:242)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:818)
 Caused by: java.lang.IllegalArgumentException: Invalid column name
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:167)
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137)
        at android.content.ContentProviderProxy.query(ContentProviderNative.java:421)
        at android.content.ContentResolver.query(ContentResolver.java:478)
        at android.content.CursorLoader.loadInBackground(CursorLoader.java:64)
        at android.content.CursorLoader.loadInBackground(CursorLoader.java:42)
        at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:312)
        at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:69)
        at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:57)
        at android.os.AsyncTask$2.call(AsyncTask.java:292)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:818)

this is a link to entire link of the app on https://github.com/NayirMicheal/petsapp , this app creating database of pets and saving those pets into database and then retriving them back from database and displaying the data retrieved into UI using listview throught CursorLoader and CursorAdapter and here is the code of the mainActivity

package com.example.android.pets;

import android.content.ContentValues;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Loader;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;

import com.example.android.pets.data.PetContract;
import com.example.android.pets.data.PetDbHelper;


public class CatalogActivity extends AppCompatActivity implements     LoaderManager.LoaderCallbacks<Cursor> {
private static final int URI_LOADER = 0;
private PetDbHelper mDbHelper;
SQLiteDatabase db;
ListView lvItems;
PetCursorAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_catalog);
 lvItems = (ListView) findViewById(R.id.lstview);
View emptyView = findViewById(R.id.empty_view);
lvItems.setEmptyView(emptyView);

adapter = new PetCursorAdapter(this, null);
lvItems.setAdapter(adapter);

// Setup FAB to open EditorActivity
FloatingActionButton fab = (FloatingActionButton)  findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(CatalogActivity.this,      EditorActivity.class);
        startActivity(intent);
    }
  });
mDbHelper = new PetDbHelper(this);
db=mDbHelper.getWritableDatabase();
getLoaderManager().initLoader(URI_LOADER, null, this);

 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
 // Inflate the menu options from the res/menu/menu_catalog.xml file.
 // This adds menu items to the app bar.
 getMenuInflater().inflate(R.menu.menu_catalog, menu);
 return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
 // User clicked on a menu option in the app bar overflow menu
 switch (item.getItemId()) {
    // Respond to a click on the "Insert dummy data" menu option
    case R.id.action_insert_dummy_data:
        insertdummy();
        return true;
    // Respond to a click on the "Delete all entries" menu option
    case R.id.action_delete_all_entries:
        // Do nothing for now
        return true;
    }
  return super.onOptionsItemSelected(item);
  }

 private void insertdummy() {
 ContentValues values=new ContentValues();
 values.put(PetContract.PetEntry.COLUMN_PET_NAME, "toto");
 values.put(PetContract.PetEntry.COLUMN_PET_BREED,"terrier");
 values.put(PetContract.PetEntry.COLUMN_PET_GENDER,     PetContract.PetEntry.GENDER_MALE);
 values.put(PetContract.PetEntry.COLUMN_PET_WEIGHT, 7);
 Uri URI_ID=   getContentResolver().insert(PetContract.PetEntry.CONTENT_URI, values);
 if(URI_ID==null)
  Toast.makeText(getApplicationContext(),  R.string.fail_save,Toast.LENGTH_LONG).show();
 else
    Toast.makeText(getApplicationContext(), R.string.success_save,   Toast.LENGTH_LONG).show();

  }

@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
String[] projection = {PetContract.PetEntry._ID,
        PetContract.PetEntry.COLUMN_PET_NAME,
        PetContract.PetEntry.COLUMN_PET_BREED};
String selection = null;
String selectionArgs[] =null;
return new CursorLoader(getApplicationContext(),     ContactsContract.Data.CONTENT_URI,
        projection, selection, selectionArgs, null);
 }

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

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

Solution

  • I think you have to use the PetContract here :

    @Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
        String[] projection = {PetContract.PetEntry._ID,
        PetContract.PetEntry.COLUMN_PET_NAME,PetContract.PetEntry.COLUMN_PET_BREED};
        String selection = null;
        String selectionArgs[] =null;
        return new CursorLoader(this, PetContract.CONTENT_URI,
        projection, selection, selectionArgs, null);
    }
    

    I also changed the getApplicationContext() to this in order to get the Activity Context. I'm not sure with that but that's what I do in my loaders. Try it and see if it works but I think the main error would be on the Contract part.