繁体   English   中英

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

[英]Calendar Provider: Permission Denial on Android 8

我在使用日历提供程序时遇到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一起发生?

为什么会这样呢?

您正在检查错误的权限。 错误说你需要READ_CALENDAR ; 你正在检查WRITE_CALENDAR 虽然您没有显示requestPermissions()调用,但我的猜测是您只是请求WRITE_CALENDAR

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

他们加强了安全性。 引用文档

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

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

例如,假设某个应用程序在其清单中列出了READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE 应用程序请求READ_EXTERNAL_STORAGE ,用户授予它。 如果应用程序的目标是API级别25或更低,系统也会同时授予WRITE_EXTERNAL_STORAGE ,因为它属于同一个STORAGE权限组,并且也在清单中注册。 如果该应用针对Android 8.0(API级别26),则系统此时仅授予READ_EXTERNAL_STORAGE ; 但是,如果应用程序稍后请求WRITE_EXTERNAL_STORAGE ,则系统会立即授予该权限,而不会提示用户。

对于相同的权限,我有相同的例外,但我不理解解决方案。

我的应用程序在清单中请求READ_CALENDAR权限,并在第一次启动应用程序时授予了权限。

我有这个例外:

java.lang.SecurityException:Permission Denial:读取com.android.providers.calendar.CalendarProvider2 uri内容://com.android.calendar/calendars

我错过了什么?

在我的清单中,我有:

    <uses-permission android:name="android.permission.READ_CALENDAR" />
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />

我执行时会出现异常:

        Cursor cur;
        ContentResolver cr = getContentResolver();
        Uri uri = Calendars.CONTENT_URI;
        cur = cr.query(uri, EVENT_PROJECTION, null, null, null);

(最后一行例外)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM