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
:
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 notcontent://
or the Uri does not have an authority string portion (Uri.getAuthority() == null).The acquired provider's query method itself returns
null
.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 ContentProvider
s 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
Cannot Catch Toolbar Home Button Click Event
How to Get the Position Selected in a Recyclerview
How to Know the Size of a File Before Downloading It
Activity Not Started, Its Current Task Has Been Brought to the Front
Starting Frame-By-Frame Animation
Sign APK Without Putting Keystore Info in Build.Gradle
Android Room: Insert Relation Entities Using Room
How to Set Cursor Position in Edittext
Redirecting Audio/Creating Alternate Sound Paths in Android
Get Focused View from Viewpager
Android: Unable to Instantiate Activity/Classnotfoundexception
Viewpager Detect When User Is Trying to Swipe Out of Bounds
Does the Web View on Android Support Ssl
Configuration with Name 'Default' Not Found. Android Studio
How to Display Map in Android with Marker
How to Use and Style New Alertdialog from Appcompat 22.1 and Above
Application Installation Failed in Android Studio
How to Set "Android:Layout_Below" at Runtime Programmatically