java - 日历提供程序 : Permission Denial on Android 8

标签 java android android-permissions android-calendar android-8.0-oreo

我在 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 and WRITE_EXTERNAL_STORAGE in its manifest. The app requests READ_EXTERNAL_STORAGE and the user grants it. If the app targets API level 25 or lower, the system also grants WRITE_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 only READ_EXTERNAL_STORAGE at that time; however, if the app later requests WRITE_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/

相关文章:

android - 如何修复未 protected SMS BroadcastReceiver lint 警告

java - 正则表达式中的标点符号

java - jni本地方法问题

android - Android fragment 之间的阴影分隔符

Android M - 相机权限问题

android - 检查权限并重新加载 Activity

java - 从文件中读取整数并将其重写到新文件中

java - 多线程的情况

android - 在 OpenGL ES 2.0/Rajawali 中,如何避免用户旋转球体时翻转球体?

android - Vevo Video 无法使用 YoutubeAndroidPlayer api android