0
votes

I'm trying to populate a ListView in my activity using a ContentProvider that I created, but when the onLoadFinished() method is called, it receives a null Cursor. (The CursorLoader is not null though).
I'm trying to debug the ContentProvider, but the debugger doesn't stop on the query() method (it stops when the URI doesn't match, when I fix that, it doesn't stop!!!). So without debug I'm having a hard time to find out why my cursor returns as null on the onLoadFinished() method.
Here is the code for the activity:

    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.support.v4.app.FragmentActivity;
    import android.support.v4.app.LoaderManager;
    import android.support.v4.content.CursorLoader;
    import android.support.v4.content.Loader;
    import android.support.v4.widget.SimpleCursorAdapter;
    import android.view.Menu;
    import android.widget.ListView;

    public class PicturesListActivity extends FragmentActivity  
            implements LoaderManager.LoaderCallbacks<Cursor> {


        SimpleCursorAdapter myAdapter;

        String[] projection = {"_id", "name"};
        String[] from = {"name"};
        String orderBy = "year DESC";

        @Override
        protected void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_pictures_list);
            final ListView listview = (ListView) findViewById(R.id.lv_pictures_list);
            // The TextView in simple_list_item_1
            int[] toViews = {android.R.id.text1};
            // Prepare the loader.  Either re-connect with an existing one, or         start a new one.
            getSupportLoaderManager().initLoader(0, null, this);
            myAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, from, toViews, 0);
            listview.setAdapter(myAdapter);
        }

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

        @Override
        // Called when a new Loader needs to be created (initLoader)
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            Uri uri = Uri.parse(DatabaseContentProvider.AUTHORITY + DatabaseContentProvider.TABLE_PATH_PICTURE);
            CursorLoader cl = new CursorLoader(this, uri, projection, null, null, orderBy);
            return cl;
        }

        @Override
        // Called automatically when a previously created loader has finished loading
        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
             myAdapter.swapCursor(data);
                                }

        @Override
        // Called when a previously created loader is reset, making the data unavailable
        public void onLoaderReset(Loader<Cursor> loader) {
            myAdapter.swapCursor(null);
                }

    }  

And here is the ContentProvider that I created:

    import android.content.ContentProvider;
    import android.content.ContentValues;
    import android.content.UriMatcher;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteQueryBuilder;
    import android.net.Uri;
    import android.text.TextUtils;

    public class DatabaseContentProvider extends ContentProvider {

        //database
        private DatabaseAssetHelper dbhelper;
        //stuff
        public static final String AUTHORITY = "com.frlnrl.myapp.DatabaseContentProvider";
        public static final String TABLE_PATH_PICTURE = DatabaseContract.Pictures.TABLE_PICTURE;

        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);

        //UriMatcher
        private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        static {
            sURIMatcher.addURI(AUTHORITY, TABLE_PATH_PICTURE , 37);
        }   

        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            // TODO Auto-generated method stub
            int numberOfLinesDeleted = 0;
            return numberOfLinesDeleted;
        }

        @Override
        public String getType(Uri uri) {
            return null;
        }

        @Override
        public Uri insert(Uri uri, ContentValues values) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public boolean onCreate() {
            dbhelper = new DatabaseAssetHelper(getContext());
            return true;
        }

        @Override
        public Cursor query(Uri uri, String[] projection, String selection,
                String[] selectionArgs, String sortOrder) {
            SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
            SQLiteDatabase db = dbhelper.getReadableDatabase();
            int uriReceived = sURIMatcher.match(uri);
            switch (uriReceived) {
                case 37:
                    if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC";
                    queryBuilder.setTables(DatabaseContract.Pictures.TABLE_PICTURE);
                    break;  
                        default:
                            throw new IllegalArgumentException("Unknown oh eu aqui URI");
            }
            Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
            cursor.setNotificationUri(getContext().getContentResolver(), uri);
            return cursor;
        }

        @Override
        public int update(Uri uri, ContentValues values, String selection,
                String[] selectionArgs) {
            // TODO Auto-generated method stub
            int numberOfLineUpdated = 0;
            return numberOfLineUpdated;
        }

    }  

Does anyone got any idea why is returns a empty cursor?

1

1 Answers

2
votes

First you should fix the CONTENT_URI for your path. Change

public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);

to

public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + TABLE_PATH_PICTURE);

You weren't including the path on your Uri.

Then when creating your cursor loader you can use the CONTENT_URI instead of trying to parse the Uri each time (Which you were doing wrong resulting in your cursor loader trying to query a Uri that didn't exist and returning a null cursor )

@Override
// Called when a new Loader needs to be created (initLoader)
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    Uri uri = DatabaseContentProvider.CONTENT_URI;
    CursorLoader cl = new CursorLoader(this, uri, projection, null, null, orderBy);
    return cl;
}