1

Ich erfahre App-Abstürze auf Oreo Android 8.0/8.1-Geräten, wenn Sie den Kalenderanbieter verwenden. Das Problem tritt nicht auf Geräten auf, auf denen Nougat und darunter ausgeführt wird.Kalenderanbieter: Permission Denial auf Android 8

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

Was mir ein Rätsel ist, dass Abstürze passieren, obwohl das System fordert persmissions in Laufzeit, sie vom Benutzer bestätigt werden, und sie können in den Systemeinstellungen überprüft werden. Auch das Überprüfen von Berechtigungen vor dem Zugriff (siehe Code unten) hilft nicht. Der Zugang wird bestätigt - und dann abgelehnt.

In meinem AndroidManifest:

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

Als Beispiel (das Problem tritt bei anderen Abfragen auch), ich erstelle einen Kalender mit dieser Methode:

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

Trotz mit Kalenderberechtigungen Überprüfung ERTEILT Die Abfrage schlägt aufgrund fehlender Berechtigungen fehl (die Anforderung für Berechtigungen erfolgt außerhalb dieser Funktion, die Berechtigungen werden jedoch vor dem Ausführen der Abfrage überprüft).

Warum passiert das und warum scheint es mit Android Version 8 zu geschehen?

Antwort

3

Warum geschieht dies

Sie sind für die falsche Erlaubnis zu überprüfen. Der Fehler besagt, dass Sie READ_CALENDAR benötigen; Sie suchen nach WRITE_CALENDAR. Während Sie den Anruf requestPermissions() nicht anzeigen, ist meine Schätzung, dass Sie nur WRITE_CALENDAR anfordern.

Warum scheint es mit Android Version 8 zu geschehen?

Sie verschärften die Sicherheit. Zitiert the documentation:

Vor Android 8.0 (API-Ebene 26), wenn eine App angefordert wurde eine Genehmigung zur Laufzeit und die Erlaubnis erteilt, das System auch falsch die App des Rest der Berechtigungen erteilt, die zur selben gehörte Berechtigungsgruppe, und diese wurden im Manifest registriert.

Für Apps, die auf Android 8.0 ausgerichtet sind, wurde dieses Verhalten korrigiert. Die App erhält nur die Berechtigungen, die sie explizit angefordert hat. Sobald der Benutzer der App jedoch eine Berechtigung erteilt, werden alle nachfolgenden Anforderungen für Berechtigungen in dieser Berechtigungsgruppe automatisch erteilt.

Angenommen, eine App listet sowohl READ_EXTERNAL_STORAGE als auch WRITE_EXTERNAL_STORAGE in ihrem Manifest auf. Die App fordert READ_EXTERNAL_STORAGE an und der Benutzer gewährt sie. Wenn die App die API-Stufe 25 oder niedriger anwendet, gewährt das System gleichzeitig WRITE_EXTERNAL_STORAGE, da es zur selben STORAGE-Berechtigungsgruppe gehört und auch im Manifest registriert ist. Wenn die App auf Android 8.0 (API-Stufe 26) abzielt, gewährt das System zu diesem Zeitpunkt nur READ_EXTERNAL_STORAGE; Wenn die App jedoch später WRITE_EXTERNAL_STORAGE anfordert, erteilt das System diese Berechtigung sofort, ohne den Benutzer dazu aufzufordern.

+0

Danke. Das macht absolut Sinn. Ich nahm tatsächlich an, dass Schreibberechtigungen wie zuvor Leseberechtigungen enthielten. Es gibt viele Informationen über die Änderungen in API 23, daher muss ich diese Informationen irgendwie verpasst haben. Ich werde versuchen, meine App entsprechend zu aktualisieren und Sie dann zu informieren (Antwort akzeptieren). – jerry

+0

@jerry: "Ich nahm tatsächlich an, dass Schreibberechtigungen wie zuvor Leseberechtigungen enthielten" - vor Android 6.0 und der Umstellung auf das Runtime-Berechtigungsmodell, AFAIK, schreibe * did * lese. Android 6.0 hat das kaputt gemacht ... aber da sie die Berechtigungen in die gleiche Gruppe gesetzt haben, sind Sie mit einem Code fertig geworden, der immer noch funktionierte. Nun, wir müssen genauer sagen, was wir in Bezug auf Berechtigungen wollen. Die UX ändert sich nicht - der Benutzer erhält keine weiteren Berechtigungs-Bestätigungsdialoge. – CommonsWare

+0

Brilliant. Es klappt! – jerry

0

Ich habe die gleiche Ausnahme für die gleiche Erlaubnis, aber ich verstehe die Lösung nicht.

Meine App Anfrage READ_CALENDAR Erlaubnis in Manifest, und ich gab die Erlaubnis beim Starten der App das erste Mal.

Ich habe diese Ausnahme:

java.lang.SecurityException: Permission Denial: Lesen com.android.providers.calendar.CalendarProvider2 uri Inhalt: //com.android.calendar/calendars

Was habe ich verpasst?

In meinem Manifest, ich habe:

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

Die Ausnahme kommt, wenn ich ausführen:

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

(Ausnahme auf letzte Zeile)

+0

Ich weiß nicht warum, aber nachdem ich mehrere saubere und wieder aufgebaut habe, funktioniert meine App wieder gut. So ist es für mich mysteriös ... – Christian

+0

Froh, dass du es gelöst hast. Ich schlage Ihnen jedoch vor, dass Sie Follow-up-Fragen oder Klärungsanfragen entweder als neue Frage oder als Kommentar zu der Antwort, auf die Sie sich beziehen, posten. Es ist wahrscheinlicher, eine Antwort auf diese Weise zu bekommen. – jerry

Verwandte Themen