What Causes Android's Contentresolver.Query() to Return Null

What causes Android's ContentResolver.query() to return null?

I just stumbled over the same problem due to a user crash report I received today for an app of mine. If the Android documentation is unclear about something it helps looking at the source code. This is what I found about the causes for ContentResolver.query() returning null:

  1. The content provider cannot be acquired. This can be due to a problem with the specified Uri or because it simply does not exist on the system. If the Uri is the problem the causes are: protocol is not content:// or the Uri does not have an authority string portion (Uri.getAuthority() == null).

  2. The acquired provider's query method itself returns null.

  3. The content provider could be acquired but a RemoteException was thrown during a query.

Especially because of (2.) it's pretty much arbitrary what might be the cause for null as a result since there are no rules defined. But usually, if SQLite is the back-end of a ContentProvider you can expect at least some empty Cursor object as a result instead of just null.

Android system ContentProviders do some checks though before they return anything. If the input is not as expected there's the unlikely chance that null may be returned. But to be honest, that never happened to me before. I usually get an IllegalArgumentException in case of query parameter problems. Maybe some ContentProvider implementations return null in case of empty result sets.

Either way. It seems to be necessary to always check for null. Especially reason number (3.) is probably something that can happen on any Android device.

contentResolver returns null

Problem was in ContentProvider. I have changed code and now it works.

  @Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
// Get readable database
SQLiteDatabase database = mDbHelper.getReadableDatabase();

// This cursor will hold the result of the query
Cursor cursor;

// Figure out if the URI matcher can match the URI to a specific code
int match = sUriMatcher.match(uri);
switch (match) {
case PETS:
// For the PETS code, query the pets table directly with the given
// projection, selection, selection arguments, and sort order. The cursor
// could contain multiple rows of the pets table.
cursor = database.query(PetEntry.TABLE_NAME, projection, selection, selectionArgs,
null, null, sortOrder);
break;
case PET_ID:
// For the PET_ID code, extract out the ID from the URI.
// For an example URI such as "content://com.example.android.pets/pets/3",
// the selection will be "_id=?" and the selection argument will be a
// String array containing the actual ID of 3 in this case.
//
// For every "?" in the selection, we need to have an element in the selection
// arguments that will fill in the "?". Since we have 1 question mark in the
// selection, we have 1 String in the selection arguments' String array.
selection = PetEntry._ID + "=?";
selectionArgs = new String[] { String.valueOf(ContentUris.parseId(uri)) };

// This will perform a query on the pets table where the _id equals 3 to return a
// Cursor containing that row of the table.
cursor = database.query(PetEntry.TABLE_NAME, projection, selection, selectionArgs,
null, null, sortOrder);
break;
default:
throw new IllegalArgumentException("Cannot query unknown URI " + uri);
}
return cursor;
}

Does query ever return a null cursor

For ContentResolver queries, yes, the returned Cursor can be null as illustrated by the code you linked.

For SQLiteDatabase queries, no, checking for null Cursor is not necessary. Though it does not hurt much.

Android: getContext().getContentResolver() sometimes gets NullPointerException

If you look in the source of ContentProvider (just hold SHIFT and click on the classname in Android Studio) then you will find that the implementation is holding an object of type Context as mContext.

Your solution is just the same, which means if mContext of ContentProvider is null, your reference will also be null. So there is no need for this.

To help you out, this is just a warning of your IDE if make such a construct yourself. But in this case there will always be context, because the ContentProvider is generated by your system. To avoid the error in your IDE just write @SuppressWarnings("ConstantConditions") above your class definition like:

...
@SuppressWarnings("ConstantConditions")
public class NoteProvider extends ContentProvider {
...

Context.getContentResolver().query() gives null pointer exception

I was finally able to fix my issue, thanks to Nguyen's suggestion. I closed my cursors at all places where I had forgot to do so and finally things worked right.



Related Topics



Leave a reply



Submit