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

Java 日历提供程序:Android 8上的权限拒绝,java,android,android-permissions,android-calendar,android-8.0-oreo,Java,Android,Android Permissions,Android Calendar,Android 8.0 Oreo,使用日历提供商时,我在Oreo Android 8.0/8.1设备上遇到应用程序崩溃。在我运行牛轧糖及以下产品的设备上没有显示此问题 Permission Denial: reading com.android.providers.calendar.CalendarProvider2 uri content://com.android.calendar/calendars from pid=8522, uid=10197 requires android.permission.READ_CALE

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

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()
让我困惑的是,即使系统在运行时请求任务,崩溃也会发生,用户会确认这些任务,并且可以在系统设置中进行验证。甚至在访问之前检查权限(请参阅下面的代码)也没有帮助。访问被确认,然后被拒绝

在我的清单中:

<manifest ...>
    <uses-permission android:name="android.permission.READ_CALENDAR" />
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />
    <application>
        ...
    </application>
</manifest>
尽管在结果已授予的情况下检查日历权限,但由于权限不足,查询仍会失败(权限请求在此函数之外完成,但在运行查询之前在此验证权限)

为什么会发生这种情况,为什么Android版本8开始出现这种情况

为什么会这样

您正在检查错误的权限。错误表明您需要
读取日历
;您正在检查
写入日历
。虽然您没有显示
requestPermissions()
调用,但我猜您只是在请求
WRITE\u CALENDAR

为什么Android版本8开始出现这种情况

他们加强了安全措施。引述:

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

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

例如,假设一个应用程序在其清单中同时列出了
READ\u EXTERNAL\u STORAGE
WRITE\u EXTERNAL\u STORAGE
。应用程序请求
读取外部存储
,并由用户授予。如果应用程序的目标API级别为25或更低,系统也会同时授予
WRITE\u EXTERNAL\u STORAGE
,因为它属于同一存储权限组,并且也在清单中注册。如果应用程序的目标是Android 8.0(API级别26),则系统当时只授予
读取外部存储
;但是,如果应用程序以后请求
写入外部存储
,系统会立即授予该权限,而不会提示用户


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

我的应用程序请求在清单中读取日历权限,我在第一次启动应用程序时授予了该权限

我有一个例外:

java.lang.SecurityException:权限拒绝:读取 com.android.providers.calendar.CalendarProvider2 uri content://com.android.calendar/calendars

我错过了什么

在我的清单中,我有:

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

(最后一行例外)

谢谢。这完全有道理。我确实假设,和以前一样,写权限包括读权限。关于API 23中的更改,有很多可用信息,所以我一定是错过了这些信息。我会尝试相应地更新我的应用程序,然后让你知道(接受答案)。@jerry:“我确实假设,和以前一样,写权限包括读权限”--在Android 6.0之前,切换到运行时权限模型AFAIK之前,写确实意味着读。安卓6.0打破了这一点。。。但由于他们将权限放在同一个组中,您最终得到的代码仍然有效。现在,我们必须更具体地说明我们想要的权限。用户体验没有改变——用户没有获得更多的权限确认对话框。我不知道为什么,但在尝试了几次清理和重建后,我的应用程序又正常工作了。所以这对我来说很神秘…很高兴你解决了它。不过,我建议您将后续问题或澄清请求作为新问题或对您所指答案的评论发布。它更有可能得到这样的回应。
    <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);