日历提供程序:Android 8上的权限拒绝 [英] Calendar Provider: Permission Denial on Android 8

查看:98
本文介绍了日历提供程序:Android 8上的权限拒绝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用日历提供程序时,我在Oreo Android 8.0/8.1设备上遇到应用程序崩溃.在运行牛轧糖及以下版本的设备上没有显示该问题.

I'm experiencing app crashes on Oreo Android 8.0/8.1 devices when using the calendar provider. The problem does not show on my devices running Nougat and below.

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()

让我感到困惑的是,即使系统在运行时请求权限,也会发生崩溃,这些崩溃已由用户确认,并且可以在系统设置中进行验证.即使在访问之前检查权限(请参阅下面的代码)也无济于事.确认访问权限-然后拒绝访问.

What puzzles me is that crashes happen even though the system requests persmissions in runtime, they are confirmed by the user, and they can be verified in the system settings. Even checking permissions before access (see my code below) does not help. Access is confirmed - and then denied.

在我的AndroidManifest中:

In my AndroidManifest:

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

作为一个示例(其他查询也会出现此问题),我使用以下方法创建日历:

As an example (the problem occurs also for other queries), I create a calendar using this method:

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来检查日历权限,但由于缺少权限而导致查询失败(权限请求是在此功能之外完成的,但是在运行查询之前已在此处验证了权限).

Despite checking calendar permissions with result GRANTED the query fails due to lack of permissions (the request for permissions is done outside this function but the permissions are verified here before running the query).

为什么会发生这种情况,为什么它似乎开始在Android版本8中发生?

Why is this happening, and why does it seem to start happening with Android Version 8?

推荐答案

为什么会这样

您正在检查错误的权限.该错误表明您需要READ_CALENDAR;您正在检查WRITE_CALENDAR.虽然您没有显示requestPermissions()呼叫,但是我猜您只是在请求WRITE_CALENDAR.

You are checking for the wrong permission. The error says that you need READ_CALENDAR; you are checking for WRITE_CALENDAR. While you do not show the requestPermissions() call, my guess is that you are only requesting WRITE_CALENDAR.

为什么它似乎始于Android版本8?

why does it seem to start happening with Android Version 8?

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

They tightened up security. Quoting the documentation:

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

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.

对于针对Android 8.0的应用,此问题已得到纠正.仅向该应用授予已明确请求的权限.但是,一旦用户向该应用授予权限,该权限组中所有随后的权限请求都将自动被授予.

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.

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

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.

这篇关于日历提供程序:Android 8上的权限拒绝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆