Why am I getting "Attempt to invoke interface method 'int android.database.Cursor.getCount()' on a null object reference"?

riceplant :

So I am getting Attempt to invoke interface method 'int android.database.Cursor.getCount()' on a null object reference when trying to get into my MovieDetailActivity to see MovieDetails with a Favourite Button. Based on the state of the movie (if it's favourited or not) the button should change its text accordingly to add or remove the movie to the favourites list. But all I am getting is a crash when trying to entering the screen.

screenshot from the Logs

Here is my isMovieFavourited method:

public boolean isMovieFavourited(String id){
    mSelectionClause = FavouritesContract.FavouritesAdd.COLUMN_MOVIE_ID + " = ?";
    mSelectionArgs[0] = id;
    Cursor mCursor = getContentResolver().query(
            FavouritesContract.FavouritesAdd.CONTENT_URI,
            mProjection,
            mSelectionClause,
            mSelectionArgs,
            null);

    if(mCursor.getCount() <= 0){
        mCursor.close();
        mFavourites.setText(getString(R.string.add_to_favourites));
        return false;
    }
    mCursor.close();
    mFavourites.setText(getString(R.string.remove_from_favourites));
    return true;
}

Here is my FavouritesContract class:

public class FavouritesContract {
public static final String AUTHORITY = "com.riceplant.popularmovies";
public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + AUTHORITY);
public static final String PATH_FAVOURITES = "favourites";

public static final class FavouritesAdd implements BaseColumns {
    public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon()
            .appendPath(PATH_FAVOURITES)
            .build();

    public static final String TABLE_NAME = "favorites";

    public static final String COLUMN_MOVIE_ID = "movieId";
    public static final String COLUMN_MOVIE_NAME = "movieName";
    public static final String COLUMN_MOVIE_POSTER = "moviePoster";
    public static final String COLUMN_MOVIE_RATE = "movieRate";
    public static final String COLUMN_MOVIE_RELEASE = "movieRelease";
    public static final String COLUMN_MOVIE_OVERVIEW = "movieOverview";
}

}

EDIT: Here is my Content Provider class:

public class FavouritesContentProvide extends ContentProvider{

    public static final int FAVOURITES = 700;
    public static final int FAVOURITES_WITH_ID = 701;
    private static final UriMatcher sUriMatcher = buildUriMatcher();

    private static UriMatcher buildUriMatcher() {
        UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(FavouritesContract.AUTHORITY, FavouritesContract.PATH_FAVOURITES, FAVOURITES);
        uriMatcher.addURI(FavouritesContract.AUTHORITY, FavouritesContract.PATH_FAVOURITES + "/#", FAVOURITES_WITH_ID);
        return uriMatcher;
    }

    private FavouritesDbHelper mFavouritesDbHelper;

    @Override
    public boolean onCreate() {
        Context context = getContext();
        mFavouritesDbHelper = new FavouritesDbHelper(context);
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        final SQLiteDatabase db = mFavouritesDbHelper.getReadableDatabase();
        int match = sUriMatcher.match(uri);
        Cursor returnCursor;

        switch (match){
            case FAVOURITES:
                returnCursor = db.query(TABLE_NAME,
                        projection,
                        selection,
                        selectionArgs,
                        null,
                        null,
                        sortOrder);
                break;

            case FAVOURITES_WITH_ID:
                String id = uri.getPathSegments().get(1);
                String mSelection = "_id=?";
                String[] mSelectionArgs = new String[]{id};

                returnCursor = db.query(TABLE_NAME,
                        projection,
                        mSelection,
                        mSelectionArgs,
                        null,
                        null,
                        sortOrder);
                break;

            default:
                throw new UnsupportedOperationException("Unknown uri: "+ uri);
        }
        returnCursor.setNotificationUri(getContext().getContentResolver(), uri);
        return returnCursor;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        int match = sUriMatcher.match(uri);

        switch (match){
            case FAVOURITES:
                return "vnd.android.cursor.dir" + "/" + FavouritesContract.AUTHORITY + "/" + FavouritesContract.PATH_FAVOURITES;
            case FAVOURITES_WITH_ID:
                return "vnd.android.cursor.item" + "/" + FavouritesContract.AUTHORITY + "/" + FavouritesContract.PATH_FAVOURITES;
            default:
                throw new UnsupportedOperationException("Unknown uri: " + uri);
        }
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        final SQLiteDatabase db = mFavouritesDbHelper.getWritableDatabase();
        int match = sUriMatcher.match(uri);
        Uri returnUri; //Uri to be returned

        switch (match){
            case FAVOURITES:
                long id = db.insert(TABLE_NAME, null, values);
                if (id > 0 ){
                    returnUri = ContentUris.withAppendedId(FavouritesContract.FavouritesAdd.CONTENT_URI, id);
                } else {
                    throw new android.database.SQLException("Failed to insert row into" + uri);
                }
                break;
            default:
                throw new UnsupportedOperationException("Unknow uri: " +uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return returnUri;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        final SQLiteDatabase db = mFavouritesDbHelper.getWritableDatabase();
        int match = sUriMatcher.match(uri);
        int favoritesDeleted;

        switch (match) {
            case FAVOURITES:
                favoritesDeleted = db.delete(TABLE_NAME, selection, selectionArgs);
                break;
            default:
                throw new UnsupportedOperationException("Unknown uri: " + uri);
        }

        if (favoritesDeleted != 0){
            getContext().getContentResolver().notifyChange(uri,null);
        }
        return favoritesDeleted;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        int favoriteUpdated;
        int match = sUriMatcher.match(uri);

        switch (match){
            case FAVOURITES_WITH_ID:
                String id = uri.getPathSegments().get(1);
                favoriteUpdated = mFavouritesDbHelper.getWritableDatabase()
                        .update(TABLE_NAME, values, "_id=?", new String[]{id});
                break;
            default:
                throw new UnsupportedOperationException("Unknown uri: " + uri);
        }

        if (favoriteUpdated != 0){
            getContext().getContentResolver().notifyChange(uri, null);
        }
        return favoriteUpdated;
    }

}

Here is the Dbhelper class:

public class FavouritesDbHelper extends SQLiteOpenHelper {

private static final String DATABASE_NAME = "favourites.db";
private static final int DATABASE_VERSION = 3;

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

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
    final String SQL_CREATE_FAVOURITES_TABLE = "CREATE TABLE " +
            FavouritesAdd.TABLE_NAME + " (" +
            FavouritesAdd._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
            FavouritesAdd.COLUMN_MOVIE_ID + " INTEGER NOT NULL," +
            FavouritesAdd.COLUMN_MOVIE_NAME + " TEXT NOT NULL," +
            FavouritesAdd.COLUMN_MOVIE_POSTER + " TEXT NOT NULL," +
            FavouritesAdd.COLUMN_MOVIE_RATE + " TEXT NOT NULL," +
            FavouritesAdd.COLUMN_MOVIE_RELEASE + " TEXT NOT NULL," +
            FavouritesAdd.COLUMN_MOVIE_OVERVIEW + " TEXT NOT NULL" +
            "); ";
    sqLiteDatabase.execSQL(SQL_CREATE_FAVOURITES_TABLE);
}

@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + FavouritesAdd.TABLE_NAME);
    onCreate(sqLiteDatabase);
}

}

I am pretty new to this, so please don't hesitate to ask if you need more code samples or anything else.

Thanks in advance!

Andy :

There are 3 circumstances where the ContentResolver.query method can return null (and yes it is documented that it can return null):

  1. The Uri provider cannot be acquired.
  2. The provider query returned null.
  3. A RemoteException occurred executing the query.

(You can see for yourself in source of ContentResolver.java)

(2) seems unlikely given your code posted. (I glanced at it and it seems like a null result would not be possible - and in theory an SQLiteDatabase.query() can never return null and even if it did you'd get a null pointer at the setNotificationUri call which you didn't.)

(3) cannot comment based on info provided - most likely would mean your provider is accessed across a network or other link.

However

(1) Is worth investigating - does the URI provided actually define a configured provider. Specifically - did you define a <provider> element in your manifest file - reference here . If so then add that portion of the manifest to your post. Have you done anything with the provider successfully? If yes then perhaps the particular URI is not quite right.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=170837&siteId=1