在使用日历提供程序时,我在Oreo Android 8.0 / 8.1设备上遇到应用程序崩溃。我在运行Nougat及以下设备的设备上没有显示此问题。
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()
让我感到困惑的是,即使系统在运行时请求延迟,也会发生崩溃,用户会确认这些崩溃,并且可以在系统设置中验证它们。甚至在访问之前检查权限(参见下面的代码)也无济于事。访问被确认 - 然后被拒绝。
在我的AndroidManifest中:
<manifest ...>
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<application>
...
</application>
</manifest>
作为示例(对于其他查询也会出现问题),我使用此方法创建日历:
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();
}
}
}
}
尽管使用结果GRANTED检查日历权限,但由于缺少权限,查询失败(权限请求在此函数之外完成,但在运行查询之前已在此处验证权限。)
为什么会发生这种情况,为什么它似乎开始发生在Android版本8上?
答案 0 :(得分:9)
为什么会发生这种情况
您正在检查错误的权限。错误表明您需要WRITE_CALENDAR
;你正在检查requestPermissions()
。虽然您没有显示WRITE_CALENDAR
来电,但我猜您只是要求READ_EXTERNAL_STORAGE
。
为什么它似乎开始发生在Android版本8上?
他们加强了安全性。引用the documentation:
在Android 8.0(API级别26)之前,如果应用程序在运行时请求了权限并且授予了权限,则系统也会错误地向应用程序授予属于同一权限组的其他权限,并且在清单中登记。
对于定位到Android 8.0的应用,此行为已得到纠正。该应用程序仅被授予其明确请求的权限。但是,一旦用户授予应用程序权限,将自动授予该权限组中所有后续权限请求。
例如,假设某个应用在其清单中列出了
WRITE_EXTERNAL_STORAGE
和READ_EXTERNAL_STORAGE
。应用请求WRITE_EXTERNAL_STORAGE
,用户授予它。如果应用程序的目标是API级别25或更低,系统也会同时授予READ_EXTERNAL_STORAGE
,因为它属于同一个STORAGE权限组,并且也在清单中注册。如果该应用针对Android 8.0(API级别26),则系统此时仅授予WRITE_EXTERNAL_STORAGE
;但是,如果应用程序稍后请求{{1}},系统会立即授予该权限,而不会提示用户。
答案 1 :(得分:0)
我对相同的权限有相同的例外,但我不理解解决方案。
我的应用请求清单中的READ_CALENDAR权限,并且我在第一次启动应用时获得了权限。
我有这个例外:
java.lang.SecurityException:Permission Denial:read com.android.providers.calendar.CalendarProvider2 uri 内容://com.android.calendar/calendars
我错过了什么?
在我的清单中,我有:
chkconfig cassandra on
执行时会出现异常:
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
(最后一行的例外)