问题
I'm experiencing app crashes on Oreo Android 8.0/8.1 devices when using the calendar provider. The problem does not show on my devices running Nougat and below.
Permission Denial: reading com.android.providers.calendar.CalendarProvider2 uri content://com.android.calendar/calendars from pid=8522, uid=10197 requires android.permission.READ_CALENDAR, or grantUriPermission()
What puzzles me is that crashes happen even though the system requests persmissions in runtime, they are confirmed by the user, and they can be verified in the system settings. Even checking permissions before access (see my code below) does not help. Access is confirmed - and then denied.
In my AndroidManifest:
<manifest ...>
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<application>
...
</application>
</manifest>
As an example (the problem occurs also for other queries), I create a calendar using this method:
public static void createCalendarIfNotExists(android.app.Activity activity) throws SecurityException {
ContentResolver contentResolver = activity.getContentResolver();
// Check if calendar already exists.
String[] projection = new String[]{
CalendarContract.Calendars._ID,
CalendarContract.Calendars.CALENDAR_DISPLAY_NAME};
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_CALENDAR) == PackageManager.PERMISSION_GRANTED) {
Cursor cursor = contentResolver.query(CalendarContract.Calendars.CONTENT_URI,
projection,
CalendarContract.Calendars.CALENDAR_DISPLAY_NAME + " = ?",
new String[]{CALENDAR_NAME},
null);
if (cursor != null) {
if (cursor.getCount() == 0) {
final ContentValues cv = buildNewCalContentValues(activity);
Uri calUri = buildCalUri();
// Insert the calendar into the database.
contentResolver.insert(calUri, cv);
}
if (!cursor.isClosed()) {
cursor.close();
}
}
}
}
Despite checking calendar permissions with result GRANTED the query fails due to lack of permissions (the request for permissions is done outside this function but the permissions are verified here before running the query).
Why is this happening, and why does it seem to start happening with Android Version 8?
回答1:
Why is this happening
You are checking for the wrong permission. The error says that you need READ_CALENDAR
; you are checking for WRITE_CALENDAR
. While you do not show the requestPermissions()
call, my guess is that you are only requesting WRITE_CALENDAR
.
why does it seem to start happening with Android Version 8?
They tightened up security. Quoting the documentation:
Prior to Android 8.0 (API level 26), if an app requested a permission at runtime and the permission was granted, the system also incorrectly granted the app the rest of the permissions that belonged to the same permission group, and that were registered in the manifest.
For apps targeting Android 8.0, this behavior has been corrected. The app is granted only the permissions it has explicitly requested. However, once the user grants a permission to the app, all subsequent requests for permissions in that permission group are automatically granted.
For example, suppose an app lists both
READ_EXTERNAL_STORAGE
andWRITE_EXTERNAL_STORAGE
in its manifest. The app requestsREAD_EXTERNAL_STORAGE
and the user grants it. If the app targets API level 25 or lower, the system also grantsWRITE_EXTERNAL_STORAGE
at the same time, because it belongs to the same STORAGE permission group and is also registered in the manifest. If the app targets Android 8.0 (API level 26), the system grants onlyREAD_EXTERNAL_STORAGE
at that time; however, if the app later requestsWRITE_EXTERNAL_STORAGE
, the system immediately grants that privilege without prompting the user.
回答2:
I have the same exception for the same permission, but I don't understand the solution.
My app request READ_CALENDAR permission in manifest, and I gave the permission when launching the app the first time.
I have this exception :
java.lang.SecurityException: Permission Denial: reading com.android.providers.calendar.CalendarProvider2 uri content://com.android.calendar/calendars
What did I missed ?
In my manifest, I have :
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
The exception comes when I execute :
Cursor cur;
ContentResolver cr = getContentResolver();
Uri uri = Calendars.CONTENT_URI;
cur = cr.query(uri, EVENT_PROJECTION, null, null, null);
(exception on last line)
来源:https://stackoverflow.com/questions/47855036/calendar-provider-permission-denial-on-android-8