我在 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 中?
最佳答案
Why is this happening
您正在检查错误的权限。错误提示您需要 READ_CALENDAR
;您正在检查 WRITE_CALENDAR
。虽然您没有显示 requestPermissions()
调用,但我猜您只是在请求 WRITE_CALENDAR
。
why does it seem to start happening with Android Version 8?
他们加强了安全措施。引用 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.
关于java - 日历提供程序 : Permission Denial on Android 8,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47855036/