日历提供程序:Android 8上的权限拒绝

时间:2017-12-17 12:18:04

标签: 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上?

2 个答案:

答案 0 :(得分:9)

  

为什么会发生这种情况

您正在检查错误的权限。错误表明您需要WRITE_CALENDAR;你正在检查requestPermissions()。虽然您没有显示WRITE_CALENDAR来电,但我猜您只是要求READ_EXTERNAL_STORAGE

  

为什么它似乎开始发生在Android版本8上?

他们加强了安全性。引用the documentation

  

在Android 8.0(API级别26)之前,如果应用程序在运行时请求了权限并且授予了权限,则系统也会错误地向应用程序授予属于同一权限组的其他权限,并且在清单中登记。

     

对于定位到Android 8.0的应用,此行为已得到纠正。该应用程序仅被授予其明确请求的权限。但是,一旦用户授予应用程序权限,将自动授予该权限组中所有后续权限请求。

     

例如,假设某个应用在其清单中列出了WRITE_EXTERNAL_STORAGEREAD_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" />

(最后一行的例外)