Calendar Provider – Übersicht

Der Kalenderanbieter ist ein Repository für die Kalendertermine eines Nutzers. Die Mit der Calendar Provider API können Sie Abfragen ausführen, einfügen, aktualisieren und löschen. Operationen zu Kalendern, Terminen, Teilnehmern, Erinnerungen usw.

Die Kalenderanbieter-API kann von Anwendungen und Synchronisierungsadaptern verwendet werden. Die variieren je nachdem, welche Art von Programm die Aufrufe durchführt. In diesem Dokument geht es hauptsächlich um die Verwendung der Calendar Provider API als Anwendung. Informationen zu den Unterschieden zwischen Synchronisatoren finden Sie unter Synchronisatoren.

Normalerweise muss das Manifest einer App die entsprechenden Berechtigungen enthalten, die unter Nutzerberechtigungen beschrieben sind, um Kalenderdaten lesen oder schreiben zu können. Um häufige Vorgänge zu vereinfachen, hat der Kalender Der Anbieter bietet eine Reihe von Intents an, wie in Google Kalender beschrieben. Intents: Diese Intents leiten Nutzer zur Kalenderanwendung weiter, wo sie und Ereignisse bearbeiten. Der Nutzer interagiert mit der Kalenderanwendung und kehrt dann zur ursprünglichen Anwendung zurück. Ihre Anwendung muss also keine Berechtigungen anfordern, Es muss auch keine Benutzeroberfläche zum Anzeigen oder Erstellen von Ereignissen bereitgestellt werden.

Grundlegende Informationen

Inhaltsanbieter speichern Daten und stellen sie für Anwendungen zur Verfügung. Die von der Android-Plattform angebotenen Inhaltsanbieter (einschließlich des Kalenderanbieters) stellen Daten in der Regel als Tabellen bereit, die auf einem relationalen Datenbankmodell basieren. Dabei entspricht jede Zeile einem Datensatz und jede Spalte Daten eines bestimmten Typs und einer bestimmten Bedeutung. Über die Calendar Provider API und Synchronisierungsadapter können Lese-/Schreibzugriff auf die Datenbanktabellen erhalten, die eine die Kalenderdaten des Nutzers.

Jeder Inhaltsanbieter stellt einen öffentlichen URI bereit (als Uri-Objekt verpackt), der seinen Datensatz eindeutig identifiziert. Ein Contentanbieter, der mehrere Datensätze (mehrere Tabellen) verwaltet, stellt für jeden einen separaten URI bereit. Alle URIs für Anbieter beginnen mit dem String „content://“. Damit wird angegeben, dass die Daten von einem Contentanbieter verwaltet werden. Der Kalenderanbieter definiert Konstanten für die URIs für jede seiner Klassen (Tabellen). Diese URIs haben das Format <class>.CONTENT_URI. Beispiel: Events.CONTENT_URI.

Abbildung 1 zeigt eine grafische Darstellung des Datenmodells des Kalenderanbieters. Sie enthält die Haupttabellen und die Felder, die sie miteinander verknüpfen.

Datenmodell des Kalenderanbieters

Abbildung 1: Datenmodell des Kalenderanbieters

Ein Nutzer kann mehrere Kalender haben und verschiedene Kalender können mit verschiedenen Kontotypen verknüpft sein (z. B. Google Kalender, Exchange usw.).

Mit CalendarContract wird das Datenmodell von kalender- und terminbezogenen Informationen definiert. Diese Daten werden in einer Reihe von Tabellen gespeichert, die unten aufgeführt sind.

Tabelle (Klasse) Beschreibung

CalendarContract.Calendars

Diese Tabelle enthält die kalenderspezifischen Informationen. Jede Zeile in dieser Tabelle enthält die Details für einen einzelnen Kalender, z. B. den Namen, die Farbe und Synchronisierungsinformationen.
CalendarContract.Events Diese Tabelle enthält die ereignisspezifischen Informationen. Jede Zeile in dieser Tabelle enthält Informationen zu einer Ereignis (z. B. Titel, Ort, Beginn, Ende) und so weiter. Das Ereignis kann einmalig oder mehrmals stattfinden. Teilnehmer, Erinnerungen und erweiterte Properties werden in separaten Tabellen gespeichert. Jede hat eine EVENT_ID, die auf die _ID in der Tabelle „Ereignisse“ verweist.
CalendarContract.Instances Diese Tabelle enthält den Beginn und das Ende jedes Ereignisses. Jede Zeile in dieser Tabelle für ein einzelnes Ereignis steht. Bei einmaligen Ereignissen wird eine 1:1-Zuordnung von Instanzen zu Ereignissen vorgenommen. Bei wiederkehrenden Terminen werden automatisch mehrere Zeilen hinzugefügt die mehreren Vorkommen dieses Ereignisses entsprechen.
CalendarContract.Attendees Diese Tabelle enthält Informationen zu den Veranstaltungsteilnehmern (Gästen). Jede Zeile steht für einen einzelnen Gast eines . Sie gibt den Gasttyp und seine Teilnahmeantwort an. für das Ereignis.
CalendarContract.Reminders Diese Tabelle enthält die Daten zu Benachrichtigungen. Jede Zeile steht für eine einzelne Benachrichtigung für ein Ereignis. Eine Termin kann mehrere Erinnerungen haben. Die maximale Anzahl an Erinnerungen pro Termin ist angegeben in MAX_REMINDERS, der vom Synchronisierungsadapter festgelegt wird, Eigentümer des angegebenen Kalenders ist. Erinnerungen werden in Minuten vor dem Termin angegeben. und haben eine Methode, die festlegt, wie der Nutzer benachrichtigt wird.

Die Calendar Provider API ist flexibel und leistungsstark. Gleichzeitig ist es wichtig, eine gute Nutzererfahrung zu bieten und die Integrität des Kalenders und seiner Daten zu schützen. Beachten Sie daher bei der Verwendung der API Folgendes:

  • Kalendertermine einfügen, aktualisieren und ansehen Wenn Sie Ereignisse direkt im Kalenderanbieter einfügen, ändern und lesen möchten, benötigen Sie die entsprechenden Berechtigungen. Wenn Sie jedoch keine vollwertige Kalenderanwendung oder keinen Synchronisierungsadapter erstellen, ist die Anforderung dieser Berechtigungen nicht erforderlich. Sie können stattdessen Intents verwenden, die von der Kalender-App von Android unterstützt werden, um Lese- und Schreibvorgänge an diese App weiterzuleiten. Wenn Sie die Intents verwenden, sendet Ihre Anwendung Nutzer an die Kalenderanwendung, um den gewünschten Vorgang auszuführen. in einem vorausgefüllten Formular. Anschließend werden sie an Ihre Anwendung zurückgegeben. Wenn Sie Ihre App so entwerfen, dass häufige Vorgänge über den Kalender ausgeführt werden, bieten Sie Nutzern eine einheitliche, robuste Benutzeroberfläche. Dies ist die empfohlenen Ansatz. Weitere Informationen finden Sie unter Kalender-Intents.
  • Adapter synchronisieren. Ein Synchronisierungsadapter synchronisiert die Kalenderdaten auf dem Gerät eines Nutzers mit einem anderen Server oder einer anderen Datenquelle. In den Tabellen CalendarContract.Calendars und CalendarContract.Events gibt es Spalten, die für die Synchronisierungsadapter reserviert sind. Anbieter und Anwendungen dürfen sie nicht ändern. Sie sind nur dann sichtbar, wenn auf sie als Synchronadapter zugegriffen wird. Weitere Informationen zu Synchronisatoren finden Sie unter Synchronisatoren.

Nutzerberechtigungen

Damit eine Anwendung Kalenderdaten lesen kann, muss sie die Berechtigung READ_CALENDAR in ihrer Manifestdatei enthalten. Sie muss die Berechtigung WRITE_CALENDAR zum Löschen, Einfügen oder Aktualisieren von Kalenderdaten enthalten:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"...>
    <uses-sdk android:minSdkVersion="14" />
    <uses-permission android:name="android.permission.READ_CALENDAR" />
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />
    ...
</manifest>

Kalendertabelle

Die Tabelle CalendarContract.Calendars enthält Details zu einzelnen Kalendern. Die folgenden Kalenderspalten können sowohl von einer Anwendung als auch von einem Synchronisierungsadapter geschrieben werden. Eine vollständige Liste der unterstützten Felder finden Sie in der Referenz zu CalendarContract.Calendars.

Konstante Beschreibung
NAME Der Name des Kalenders.
CALENDAR_DISPLAY_NAME Der Name dieses Kalenders, der dem Nutzer angezeigt wird.
VISIBLE Ein boolescher Wert, der angibt, ob der Kalender angezeigt werden soll. A 0 bedeutet, dass diesem Kalender zugeordnete Termine nicht in angezeigt. Ein Wert von 1 gibt an, dass Termine, die mit diesem Kalender verknüpft sind, angezeigt werden sollen. Dieser Wert wirkt sich auf die Generierung von Zeilen in der Tabelle CalendarContract.Instances aus.
SYNC_EVENTS Ein boolescher Wert, der angibt, ob der Kalender synchronisiert werden soll und die auf dem Gerät gespeichert sind. Der Wert 0 besagt, dass dieser Kalender nicht synchronisiert oder Ereignisse auf dem Gerät zu speichern. Der Wert 1 gibt an, dass Termine für diesen Kalender synchronisiert werden sollen. und speichern Sie die Ereignisse auf dem Gerät.

Kontotyp für alle Vorgänge angeben

Wenn Sie eine Abfrage für eine Calendars.ACCOUNT_NAME stellen, muss Calendars.ACCOUNT_TYPE auch in der Auswahl enthalten sein. Das liegt daran, dass ein bestimmtes Konto nur als eindeutig betrachtet, da sowohl ACCOUNT_NAME als auch ACCOUNT_TYPE. ACCOUNT_TYPE ist der String, der dem Konto-Authenticator entspricht, der beim Registrieren des Kontos mit der AccountManager verwendet wurde. Es gibt auch einen speziellen Kontotyp namens ACCOUNT_TYPE_LOCAL für Kalender, die nicht mit einem Gerätekonto verknüpft sind. ACCOUNT_TYPE_LOCAL Konten erhalten nicht synchronisiert.

Kalender abfragen

Das folgende Beispiel zeigt, wie Sie die Kalender eines bestimmten Nutzer. Der Einfachheit halber wird in diesem Beispiel der Abfragevorgang in der Benutzeroberflächen-Thread („Hauptthread“). In der Praxis sollte dies in einem asynchronen Thread und nicht im Hauptthread erfolgen. Weitere Informationen finden Sie unter Loader: Wenn Sie nicht nur Daten lesen, aber ändern, siehe AsyncQueryHandler.

Kotlin

// Projection array. Creating indices for this array instead of doing
// dynamic lookups improves performance.
private val EVENT_PROJECTION: Array<String> = arrayOf(
        CalendarContract.Calendars._ID,                     // 0
        CalendarContract.Calendars.ACCOUNT_NAME,            // 1
        CalendarContract.Calendars.CALENDAR_DISPLAY_NAME,   // 2
        CalendarContract.Calendars.OWNER_ACCOUNT            // 3
)

// The indices for the projection array above.
private const val PROJECTION_ID_INDEX: Int = 0
private const val PROJECTION_ACCOUNT_NAME_INDEX: Int = 1
private const val PROJECTION_DISPLAY_NAME_INDEX: Int = 2
private const val PROJECTION_OWNER_ACCOUNT_INDEX: Int = 3

Java

// Projection array. Creating indices for this array instead of doing
// dynamic lookups improves performance.
public static final String[] EVENT_PROJECTION = new String[] {
    Calendars._ID,                           // 0
    Calendars.ACCOUNT_NAME,                  // 1
    Calendars.CALENDAR_DISPLAY_NAME,         // 2
    Calendars.OWNER_ACCOUNT                  // 3
};

// The indices for the projection array above.
private static final int PROJECTION_ID_INDEX = 0;
private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;
private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;

Im nächsten Teil des Beispiels erstellen Sie die Abfrage. Mit der Auswahl werden die Kriterien für die Abfrage festgelegt. In diesem Beispiel wird in der Abfrage nach Kalendern gesucht, die die ACCOUNT_NAME „hera@beispiel.de“, die ACCOUNT_TYPE „beispiel.de“ und die OWNER_ACCOUNT „hera@beispiel.de“ enthalten. Wenn Sie alle Kalender sehen möchten, die ein Nutzer aufgerufen hat, nicht nur die, deren Inhaber er ist, lassen Sie die OWNER_ACCOUNT weg. Die Abfrage gibt ein Cursor-Objekt zurück, mit dem Sie den von der Datenbankabfrage zurückgegebenen Ergebnissatz durchsuchen können. Weitere Informationen zur Verwendung von Abfragen bei Contentanbietern Siehe Contentanbieter.

Kotlin

// Run query
val uri: Uri = CalendarContract.Calendars.CONTENT_URI
val selection: String = "((${CalendarContract.Calendars.ACCOUNT_NAME} = ?) AND (" +
        "${CalendarContract.Calendars.ACCOUNT_TYPE} = ?) AND (" +
        "${CalendarContract.Calendars.OWNER_ACCOUNT} = ?))"
val selectionArgs: Array<String> = arrayOf("hera@example.com", "com.example", "hera@example.com")
val cur: Cursor = contentResolver.query(uri, EVENT_PROJECTION, selection, selectionArgs, null)

Java

// Run query
Cursor cur = null;
ContentResolver cr = getContentResolver();
Uri uri = Calendars.CONTENT_URI;
String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
                        + Calendars.ACCOUNT_TYPE + " = ?) AND ("
                        + Calendars.OWNER_ACCOUNT + " = ?))";
String[] selectionArgs = new String[] {"hera@example.com", "com.example",
        "hera@example.com"};
// Submit the query and get a Cursor object back.
cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

Im nächsten Abschnitt wird der Cursor verwendet, um den Ergebnissatz durchzugehen. Dabei werden die Konstanten verwendet, die zu Beginn des Beispiels festgelegt wurden, um die Werte für jedes Feld zurückzugeben.

Kotlin

// Use the cursor to step through the returned records
while (cur.moveToNext()) {
    // Get the field values
    val calID: Long = cur.getLong(PROJECTION_ID_INDEX)
    val displayName: String = cur.getString(PROJECTION_DISPLAY_NAME_INDEX)
    val accountName: String = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX)
    val ownerName: String = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX)
    // Do something with the values...
}

Java

// Use the cursor to step through the returned records
while (cur.moveToNext()) {
    long calID = 0;
    String displayName = null;
    String accountName = null;
    String ownerName = null;

    // Get the field values
    calID = cur.getLong(PROJECTION_ID_INDEX);
    displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
    accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
    ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);

    // Do something with the values...

   ...
}

Kalender ändern

Um einen Kalender zu aktualisieren, können Sie die _ID des Kalenders entweder als angehängte ID an der URI (withAppendedId()) oder als erstes Auswahlelement. Die Auswahl sollte mit "_id=?" beginnen und die erste selectionArg sollte die _ID des Kalenders sein. Sie können auch Aktualisierungen vornehmen, indem Sie die ID im URI codieren. In diesem Beispiel wird ein Anzeigename des Kalenders mithilfe der (withAppendedId()) Ansatz:

Kotlin

const val DEBUG_TAG: String = "MyActivity"
...
val calID: Long = 2
val values = ContentValues().apply {
    // The new display name for the calendar
    put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar")
}
val updateUri: Uri = ContentUris.withAppendedId(CalendarContract.Calendars.CONTENT_URI, calID)
val rows: Int = contentResolver.update(updateUri, values, null, null)
Log.i(DEBUG_TAG, "Rows updated: $rows")

Java

private static final String DEBUG_TAG = "MyActivity";
...
long calID = 2;
ContentValues values = new ContentValues();
// The new display name for the calendar
values.put(Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar");
Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID);
int rows = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);

Kalender einfügen

Kalender werden hauptsächlich über einen Synchronisierungsadapter verwaltet. sollten nur neue Kalender als Synchronisierungsadapter eingefügt werden. Größtenteils Anwendungen können nur oberflächliche Änderungen an Kalendern vornehmen, beispielsweise den Anzeigenamen. Wenn muss eine Anwendung einen lokalen Kalender erstellen, Das Einfügen des Kalenders als Synchronisierungsadapter mit einem ACCOUNT_TYPE von ACCOUNT_TYPE_LOCAL. ACCOUNT_TYPE_LOCAL ist ein spezieller Kontotyp für Kalender, die nicht die mit einem Gerätekonto verknüpft sind. Kalender dieses Typs werden nicht mit einem Server synchronisiert. Weitere Informationen zu Synchronisatoren finden Sie unter Synchronisatoren.

Ereignistabelle

Die Tabelle CalendarContract.Events enthält Details zu einzelnen Ereignissen. Wenn eine Anwendung Ereignisse hinzufügen, aktualisieren oder löschen möchte, muss sie die Berechtigung WRITE_CALENDAR in ihrer Manifestdatei angeben.

Die folgenden Spalten für Ereignisse können sowohl von einer Anwendung als auch von einem Synchronisierungsadapter beschrieben werden. Eine vollständige Liste der unterstützten Felder findest du in der CalendarContract.Events-Referenz.

Konstante Beschreibung
CALENDAR_ID Die _ID des Kalenders, zu dem der Termin gehört.
ORGANIZER E-Mail-Adresse des Organisators (Inhabers) der Veranstaltung.
TITLE Der Titel der Veranstaltung.
EVENT_LOCATION Wo das Ereignis stattfindet.
DESCRIPTION Die Beschreibung des Ereignisses.
DTSTART Die Startzeit des Ereignisses in Millisekunden (UTC) seit der Epoche.
DTEND Die Uhrzeit, zu der das Ereignis endet, in Millisekunden nach der Epoche (UTC).
EVENT_TIMEZONE Die Zeitzone für den Termin.
EVENT_END_TIMEZONE Die Zeitzone für das Ende des Termins.
DURATION Die Dauer des Ereignisses im RFC5545-Format. Beispielsweise gibt der Wert "PT1H" an, dass das Ereignis sollte eine Stunde dauern und der Wert "P2W" steht für Dauer von 2 Wochen.
ALL_DAY Der Wert „1“ gibt an, dass dieses Ereignis den gesamten Tag einnimmt, wie durch der lokalen Zeitzone. Der Wert 0 bedeutet, dass es sich um ein normales Ereignis handelt, das möglicherweise beginnen kann. und enden zu jeder Tageszeit.
RRULE Die Wiederholungsregel für das Ereignisformat. Beispiel: "FREQ=WEEKLY;COUNT=10;WKST=SU". Weitere Beispiele
RDATE Die Wiederholungsdaten des Ereignisses. Normalerweise wird RDATE in Kombination mit RRULE verwendet, um eine Gesamtheit sich wiederholender Vorkommen zu definieren. Weitere Informationen finden Sie in der RFC 5545-Spezifikation.
AVAILABILITY Wenn dieser Termin als beschäftigt oder als kostenlose Zeit gezählt wird, geplant ist.
GUESTS_CAN_MODIFY Ob Gäste den Termin bearbeiten können.
GUESTS_CAN_INVITE_OTHERS Ob Gäste andere Gäste einladen können.
GUESTS_CAN_SEE_GUESTS Gibt an, ob Gäste die Teilnehmerliste sehen können.

Hinzufügen von Terminen

Wenn Ihre Anwendung ein neues Ereignis einfügt, empfehlen wir die Verwendung eines INSERT-Intents, wie unter Ereignisse mit einem Intent einfügen beschrieben. Sie können Ereignisse aber auch direkt einfügen. In diesem Abschnitt wird beschrieben, wie Sie dies.

Beachten Sie beim Einfügen eines neuen Ereignisses die folgenden Regeln:

Hier ist ein Beispiel für das Einfügen eines Ereignisses. Aus Gründen der Vereinfachung wird dies im UI-Thread ausgeführt. In der Praxis sollten Einfügungen und Aktualisierungen in einem asynchronen Thread erfolgen, um die Aktion in einen Hintergrundthread zu verschieben. Weitere Informationen finden Sie unter AsyncQueryHandler.

Kotlin

val calID: Long = 3
val startMillis: Long = Calendar.getInstance().run {
    set(2012, 9, 14, 7, 30)
    timeInMillis
}
val endMillis: Long = Calendar.getInstance().run {
    set(2012, 9, 14, 8, 45)
    timeInMillis
}
...

val values = ContentValues().apply {
    put(CalendarContract.Events.DTSTART, startMillis)
    put(CalendarContract.Events.DTEND, endMillis)
    put(CalendarContract.Events.TITLE, "Jazzercise")
    put(CalendarContract.Events.DESCRIPTION, "Group workout")
    put(CalendarContract.Events.CALENDAR_ID, calID)
    put(CalendarContract.Events.EVENT_TIMEZONE, "America/Los_Angeles")
}
val uri: Uri = contentResolver.insert(CalendarContract.Events.CONTENT_URI, values)

// get the event ID that is the last element in the Uri
val eventID: Long = uri.lastPathSegment.toLong()
//
// ... do something with event ID
//
//

Java

long calID = 3;
long startMillis = 0;
long endMillis = 0;
Calendar beginTime = Calendar.getInstance();
beginTime.set(2012, 9, 14, 7, 30);
startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2012, 9, 14, 8, 45);
endMillis = endTime.getTimeInMillis();
...

ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Events.DTSTART, startMillis);
values.put(Events.DTEND, endMillis);
values.put(Events.TITLE, "Jazzercise");
values.put(Events.DESCRIPTION, "Group workout");
values.put(Events.CALENDAR_ID, calID);
values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles");
Uri uri = cr.insert(Events.CONTENT_URI, values);

// get the event ID that is the last element in the Uri
long eventID = Long.parseLong(uri.getLastPathSegment());
//
// ... do something with event ID
//
//

Hinweis:In diesem Beispiel wird das Ereignis erfasst. ID, nachdem das Ereignis erstellt wurde. Dies ist die einfachste Methode, um eine Ereignis-ID abzurufen. Sie benötigen die Ereignis-ID häufig, um andere Kalenderaktionen auszuführen, z. B. um einem Termin Teilnehmer oder Erinnerungen hinzuzufügen.

Updates

Wenn Nutzer in Ihrer Anwendung ein Ereignis bearbeiten können sollen, empfehlen wir, Sie einen EDIT-Intent verwenden, beschrieben unter Intent zum Bearbeiten eines Ereignisses verwenden. Sie können Termine aber auch direkt bearbeiten. So führen Sie eine Aktualisierung durch: eines Ereignisses möchten, können Sie die _ID des Ereignis, entweder als angehängte ID an den URI (withAppendedId()) oder als erstes Auswahlelement. Die Auswahl sollte mit "_id=?" beginnen und die erste selectionArg sollte die _ID des Ereignisses sein. Sie können Aktualisierungen auch mit einer Auswahl ohne ID vornehmen. Hier ist ein Beispiel für die Aktualisierung eines . Mithilfe der Funktion withAppendedId() Ansatz:

Kotlin

val DEBUG_TAG = "MyActivity"
...
val eventID: Long = 188
...
val values = ContentValues().apply {
    // The new title for the event
    put(CalendarContract.Events.TITLE, "Kickboxing")
}
val updateUri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val rows: Int = contentResolver.update(updateUri, values, null, null)
Log.i(DEBUG_TAG, "Rows updated: $rows")

Java

private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 188;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
Uri updateUri = null;
// The new title for the event
values.put(Events.TITLE, "Kickboxing");
updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = cr.update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);

Termine löschen

Sie können ein Ereignis löschen, indem Sie _ID als angehängte ID für den URI verwenden oder Standardauswahl. Wenn Sie eine angehängte ID verwenden, können Sie keine Auswahl treffen. Es gibt zwei Versionen von Delete: als Anwendung und als Synchronisierungsadapter. Beim Löschen einer Anwendung wird in der Spalte deleted der Wert 1 festgelegt. Dieses Flag teilt dem Synchronisierungsadapter mit, dass die Zeile gelöscht wurde und dass diese Löschung an den Server weitergegeben werden soll. Durch das Löschen des Sync-Adapters wird das Ereignis aus dem sowie mit allen zugehörigen Daten. Hier ist ein Anwendungsbeispiel Löschen eines Termins über _ID:

Kotlin

val DEBUG_TAG = "MyActivity"
...
val eventID: Long = 201
...
val deleteUri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val rows: Int = contentResolver.delete(deleteUri, null, null)
Log.i(DEBUG_TAG, "Rows deleted: $rows")

Java

private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 201;
...
ContentResolver cr = getContentResolver();
Uri deleteUri = null;
deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = cr.delete(deleteUri, null, null);
Log.i(DEBUG_TAG, "Rows deleted: " + rows);

Tabelle „Teilnehmer“

Jede Zeile der Tabelle CalendarContract.Attendees steht für einen einzelnen Teilnehmer oder Gast einer Veranstaltung. Anrufen query() gibt eine Teilnehmerliste für die mit dem angegebenen EVENT_ID. Dieses EVENT_ID muss mit dem _ID eines bestimmten Ereignisses übereinstimmen.

In der folgenden Tabelle sind die beschreibbar sind. Wenn Sie einen neuen Teilnehmer einfügen, müssen Sie alle Felder außer ATTENDEE_NAME ausfüllen.

Konstante Beschreibung
EVENT_ID Die ID des Ereignisses.
ATTENDEE_NAME Der Name des Gasts.
ATTENDEE_EMAIL Die E-Mail-Adresse des Teilnehmers.
ATTENDEE_RELATIONSHIP

Die Beziehung des Teilnehmers zum Termin. Eine der folgenden Optionen:

ATTENDEE_TYPE

Der Teilnehmertyp. Eine der folgenden Möglichkeiten:

ATTENDEE_STATUS

Der Teilnahmestatus des Teilnehmers. Eine der folgenden Optionen:

Teilnehmer hinzufügen

Hier ist ein Beispiel, in dem einer Veranstaltung ein einzelner Teilnehmer hinzugefügt wird. Beachten Sie, dass EVENT_ID erforderlich ist:

Kotlin

val eventID: Long = 202
...
val values = ContentValues().apply {
    put(CalendarContract.Attendees.ATTENDEE_NAME, "Trevor")
    put(CalendarContract.Attendees.ATTENDEE_EMAIL, "trevor@example.com")
    put(
        CalendarContract.Attendees.ATTENDEE_RELATIONSHIP,
        CalendarContract.Attendees.RELATIONSHIP_ATTENDEE
    )
    put(CalendarContract.Attendees.ATTENDEE_TYPE, CalendarContract.Attendees.TYPE_OPTIONAL)
    put(
        CalendarContract.Attendees.ATTENDEE_STATUS,
        CalendarContract.Attendees.ATTENDEE_STATUS_INVITED
    )
    put(CalendarContract.Attendees.EVENT_ID, eventID)
}
val uri: Uri = contentResolver.insert(CalendarContract.Attendees.CONTENT_URI, values)

Java

long eventID = 202;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Attendees.ATTENDEE_NAME, "Trevor");
values.put(Attendees.ATTENDEE_EMAIL, "trevor@example.com");
values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL);
values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED);
values.put(Attendees.EVENT_ID, eventID);
Uri uri = cr.insert(Attendees.CONTENT_URI, values);

Erinnerungstabelle

Jede Zeile der Tabelle CalendarContract.Reminders steht für eine einzelne Erinnerung für ein Ereignis. Wenn Sie query() aufrufen, wird eine Liste der Erinnerungen für das Ereignis mit der angegebenen EVENT_ID zurückgegeben.

In der folgenden Tabelle sind die beschreibbaren Felder für Erinnerungen aufgeführt. Sie müssen alle angegeben werden, wenn Sie eine neue Erinnerung einfügen. Synchronadapter geben die von ihnen unterstützten Arten von Erinnerungen in der Tabelle CalendarContract.Calendars an. Weitere Informationen finden Sie unter ALLOWED_REMINDERS .

Konstante Beschreibung
EVENT_ID Die ID des Ereignisses.
MINUTES Die Minuten vor dem Ereignis, in dem die Erinnerung ausgelöst werden soll.
METHOD

Die Weckmethode, die auf dem Server festgelegt ist. Eine der folgenden Möglichkeiten:

Erinnerungen erstellen

In diesem Beispiel wird einem Termin eine Erinnerung hinzugefügt. Die Erinnerung wird 15 Minuten vor dem Termin ausgelöst.

Kotlin

val eventID: Long = 221
...
val values = ContentValues().apply {
    put(CalendarContract.Reminders.MINUTES, 15)
    put(CalendarContract.Reminders.EVENT_ID, eventID)
    put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT)
}
val uri: Uri = contentResolver.insert(CalendarContract.Reminders.CONTENT_URI, values)

Java

long eventID = 221;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Reminders.MINUTES, 15);
values.put(Reminders.EVENT_ID, eventID);
values.put(Reminders.METHOD, Reminders.METHOD_ALERT);
Uri uri = cr.insert(Reminders.CONTENT_URI, values);

Tabelle „Instanzen“

Die Tabelle CalendarContract.Instances enthält die Start- und Endzeit für die Vorkommnisse eines Ereignisses. Jede Zeile in dieser Tabelle steht für ein einzelnes Ereignis. Die Tabelle „instances“ ist nicht beschreibbar und bietet nur eine Möglichkeit, Ereignisvorkommnisse abzufragen.

In der folgenden Tabelle sind einige Felder aufgeführt, die Sie für eine Instanz abfragen können. Die Zeitzone wird durch KEY_TIMEZONE_TYPE und KEY_TIMEZONE_INSTANCES definiert.

Konstante Beschreibung
BEGIN Die Startzeit der Instanz in UTC-Millisekunden.
END Die Endzeit der Instanz in UTC-Millisekunden.
END_DAY Der julianische Endtag der Instanz, bezogen auf die Kalenderzeit .
END_MINUTE Die Endminute der Instanz, gemessen ab Mitternacht im Zeitzone des Kalenders
EVENT_ID Der _ID des Ereignisses für diese Instanz.
START_DAY Der Julianische Starttag der Instanz bezogen auf die Zeitzone des Kalenders.
START_MINUTE Die Startminute der Instanz, gemessen ab Mitternacht, bezogen auf die Zeitzone des Kalenders

Tabelle „instances“ abfragen

Wenn Sie die Tabelle „Instances“ abfragen möchten, müssen Sie im URI einen Zeitraum für die Abfrage angeben. In diesem Beispiel: CalendarContract.Instances erhält Zugriff auf das Feld TITLE über seine Implementierung der CalendarContract.EventsColumns-Schnittstelle. Mit anderen Worten, TITLE wird durch einen Datenbankansicht zu verwenden, nicht durch Abfragen der rohen CalendarContract.Instances-Tabelle.

Kotlin

const val DEBUG_TAG: String = "MyActivity"
val INSTANCE_PROJECTION: Array<String> = arrayOf(
        CalendarContract.Instances.EVENT_ID, // 0
        CalendarContract.Instances.BEGIN, // 1
        CalendarContract.Instances.TITLE // 2
)

// The indices for the projection array above.
const val PROJECTION_ID_INDEX: Int = 0
const val PROJECTION_BEGIN_INDEX: Int = 1
const val PROJECTION_TITLE_INDEX: Int = 2

// Specify the date range you want to search for recurring
// event instances
val startMillis: Long = Calendar.getInstance().run {
    set(2011, 9, 23, 8, 0)
    timeInMillis
}
val endMillis: Long = Calendar.getInstance().run {
    set(2011, 10, 24, 8, 0)
    timeInMillis
}

// The ID of the recurring event whose instances you are searching
// for in the Instances table
val selection: String = "${CalendarContract.Instances.EVENT_ID} = ?"
val selectionArgs: Array<String> = arrayOf("207")

// Construct the query with the desired date range.
val builder: Uri.Builder = CalendarContract.Instances.CONTENT_URI.buildUpon()
ContentUris.appendId(builder, startMillis)
ContentUris.appendId(builder, endMillis)

// Submit the query
val cur: Cursor = contentResolver.query(
        builder.build(),
        INSTANCE_PROJECTION,
        selection,
        selectionArgs, null
)
while (cur.moveToNext()) {
    // Get the field values
    val eventID: Long = cur.getLong(PROJECTION_ID_INDEX)
    val beginVal: Long = cur.getLong(PROJECTION_BEGIN_INDEX)
    val title: String = cur.getString(PROJECTION_TITLE_INDEX)

    // Do something with the values.
    Log.i(DEBUG_TAG, "Event: $title")
    val calendar = Calendar.getInstance().apply {
        timeInMillis = beginVal
    }
    val formatter = SimpleDateFormat("MM/dd/yyyy")
    Log.i(DEBUG_TAG, "Date: ${formatter.format(calendar.time)}")
}

Java

private static final String DEBUG_TAG = "MyActivity";
public static final String[] INSTANCE_PROJECTION = new String[] {
    Instances.EVENT_ID,      // 0
    Instances.BEGIN,         // 1
    Instances.TITLE          // 2
  };

// The indices for the projection array above.
private static final int PROJECTION_ID_INDEX = 0;
private static final int PROJECTION_BEGIN_INDEX = 1;
private static final int PROJECTION_TITLE_INDEX = 2;
...

// Specify the date range you want to search for recurring
// event instances
Calendar beginTime = Calendar.getInstance();
beginTime.set(2011, 9, 23, 8, 0);
long startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2011, 10, 24, 8, 0);
long endMillis = endTime.getTimeInMillis();

Cursor cur = null;
ContentResolver cr = getContentResolver();

// The ID of the recurring event whose instances you are searching
// for in the Instances table
String selection = Instances.EVENT_ID + " = ?";
String[] selectionArgs = new String[] {"207"};

// Construct the query with the desired date range.
Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, startMillis);
ContentUris.appendId(builder, endMillis);

// Submit the query
cur =  cr.query(builder.build(),
    INSTANCE_PROJECTION,
    selection,
    selectionArgs,
    null);

while (cur.moveToNext()) {
    String title = null;
    long eventID = 0;
    long beginVal = 0;

    // Get the field values
    eventID = cur.getLong(PROJECTION_ID_INDEX);
    beginVal = cur.getLong(PROJECTION_BEGIN_INDEX);
    title = cur.getString(PROJECTION_TITLE_INDEX);

    // Do something with the values.
    Log.i(DEBUG_TAG, "Event:  " + title);
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(beginVal);
    DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
    Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime()));
    }
 }

Kalender-Intents

Ihre Anwendung benötigt keine Berechtigungen zum Lesen und Schreiben von Kalenderdaten. Er kann stattdessen Intents verwenden, die von der Android-Kalenderanwendung unterstützt werden, um Lese- und Schreibvorgänge an diese Anwendung zu übergeben. In der folgenden Tabelle sind die vom Kalenderanbieter unterstützten Intents aufgeführt:

Aktion URI Beschreibung Extras

VIEW

content://com.android.calendar/time/<ms_since_epoch>

Sie können auch mit CalendarContract.CONTENT_URI Ein Beispiel für die Verwendung dieses Intents finden Sie unter Intents zum Ansehen von Kalenderdaten verwenden.
Öffnet den Kalender zur von <ms_since_epoch> angegebenen Uhrzeit. Keine.

VIEW

content://com.android.calendar/events/<event_id>

Sie können den URI auch mit Events.CONTENT_URI referenzieren. Ein Beispiel für die Verwendung dieses Intents finden Sie unter Intents zum Ansehen von Kalenderdaten verwenden.
Rufen Sie das Ereignis auf, das durch <event_id> angegeben ist. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

content://com.android.calendar/events/<event_id>

Sie können auch mit Events.CONTENT_URI Ein Beispiel für die Verwendung dieses Intents finden Sie unter Ereignisse mit einem Intent bearbeiten.
Bearbeiten Sie das in <event_id> angegebene Ereignis. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

INSERT

content://com.android.calendar/events

Sie können den URI auch mit Events.CONTENT_URI referenzieren. Ein Beispiel für die Verwendung dieses Intents finden Sie unter Ereignisse mit einem Intent einfügen.
Erstellen Sie einen Termin. Alle in der folgenden Tabelle aufgeführten Extras

In der folgenden Tabelle sind die vom Kalenderanbieter unterstützten Intent-Extras aufgeführt:

Intent Extra Beschreibung
Events.TITLE Name des Ereignisses.
CalendarContract.EXTRA_EVENT_BEGIN_TIME Beginn des Ereignisses in Millisekunden ab der Epoche.
CalendarContract.EXTRA_EVENT_END_TIME Ereignisende in Millisekunden seit der Epoche.
CalendarContract.EXTRA_EVENT_ALL_DAY Ein boolescher Wert, der angibt, dass ein Ereignis den ganzen Tag dauert. Der Wert kann true oder false sein.
Events.EVENT_LOCATION Ort des Ereignisses.
Events.DESCRIPTION Ereignisbeschreibung
Intent.EXTRA_EMAIL E-Mail-Adressen der einzuladenden Personen als durch Kommas getrennte Liste.
Events.RRULE Die Wiederholungsregel für den Termin.
Events.ACCESS_LEVEL Ob es sich um eine private oder öffentliche Veranstaltung handelt.
Events.AVAILABILITY Ob dieser Termin als beschäftigt oder als kostenlose Zeit gezählt wird, der später geplant werden kann.

In den folgenden Abschnitten wird beschrieben, wie Sie diese Intents verwenden.

Intent zum Einfügen eines Ereignisses verwenden

Intent INSERT verwenden ermöglicht Ihre Anwendung, die Aufgabe zum Einfügen von Terminen an den Kalender selbst zu übergeben. Bei diesem Ansatz muss die Berechtigung WRITE_CALENDAR nicht einmal in der Manifestdatei Ihrer Anwendung enthalten sein.

Wenn Nutzer eine Anwendung ausführen, die diesen Ansatz verwendet, werden sie von der Anwendung zum Kalender weitergeleitet, um den Termin fertig hinzuzufügen. Der Intent INSERT verwendet zusätzliche Felder, ein Formular mit den Termindetails im Kalender vorab ausfüllen. Nutzer können den Termin dann absagen, das Formular nach Bedarf bearbeiten oder den Termin in ihrem Kalender speichern.

Hier ist ein Code-Snippet, mit dem ein Ereignis am 19. Januar 2012 geplant wird, von 7:30 bis 8:30 Uhr. Beachten Sie bei diesem Code-Snippet Folgendes:

Kotlin

val startMillis: Long = Calendar.getInstance().run {
    set(2012, 0, 19, 7, 30)
    timeInMillis
}
val endMillis: Long = Calendar.getInstance().run {
    set(2012, 0, 19, 8, 30)
    timeInMillis
}
val intent = Intent(Intent.ACTION_INSERT)
        .setData(CalendarContract.Events.CONTENT_URI)
        .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startMillis)
        .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endMillis)
        .putExtra(CalendarContract.Events.TITLE, "Yoga")
        .putExtra(CalendarContract.Events.DESCRIPTION, "Group class")
        .putExtra(CalendarContract.Events.EVENT_LOCATION, "The gym")
        .putExtra(CalendarContract.Events.AVAILABILITY, CalendarContract.Events.AVAILABILITY_BUSY)
        .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com")
startActivity(intent)

Java

Calendar beginTime = Calendar.getInstance();
beginTime.set(2012, 0, 19, 7, 30);
Calendar endTime = Calendar.getInstance();
endTime.set(2012, 0, 19, 8, 30);
Intent intent = new Intent(Intent.ACTION_INSERT)
        .setData(Events.CONTENT_URI)
        .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis())
        .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis())
        .putExtra(Events.TITLE, "Yoga")
        .putExtra(Events.DESCRIPTION, "Group class")
        .putExtra(Events.EVENT_LOCATION, "The gym")
        .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY)
        .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com");
startActivity(intent);

Intent zum Bearbeiten eines Ereignisses verwenden

Sie können ein Ereignis direkt aktualisieren, wie unter Ereignisse aktualisieren beschrieben. Mit dem Intent EDIT kann eine App, die keine Berechtigung hat, die Terminbearbeitung an die Kalender-App weitergeben. Wenn Nutzer die Bearbeitung des Termins im Kalender abgeschlossen haben, werden sie zur ursprünglichen Anwendung zurückgeleitet.

Hier ist ein Beispiel für einen Intent, der einen neuen Titel für einen bestimmten Termin und ermöglicht den Nutzern, diesen im Kalender zu bearbeiten.

Kotlin

val eventID: Long = 208
val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val intent = Intent(Intent.ACTION_EDIT)
        .setData(uri)
        .putExtra(CalendarContract.Events.TITLE, "My New Title")
startActivity(intent)

Java

long eventID = 208;
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_EDIT)
    .setData(uri)
    .putExtra(Events.TITLE, "My New Title");
startActivity(intent);

Intents verwenden, um Kalenderdaten aufzurufen

Der Kalenderanbieter bietet zwei Möglichkeiten, die VIEW-Intention zu verwenden:

  • So öffnen Sie den Kalender für ein bestimmtes Datum:
  • So rufen Sie einen Termin auf:

Hier ein Beispiel, wie Sie den Kalender auf ein bestimmtes Datum öffnen:

Kotlin

val startMillis: Long
...
val builder: Uri.Builder = CalendarContract.CONTENT_URI.buildUpon()
        .appendPath("time")
ContentUris.appendId(builder, startMillis)
val intent = Intent(Intent.ACTION_VIEW)
        .setData(builder.build())
startActivity(intent)

Java

// A date-time specified in milliseconds since the epoch.
long startMillis;
...
Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
builder.appendPath("time");
ContentUris.appendId(builder, startMillis);
Intent intent = new Intent(Intent.ACTION_VIEW)
    .setData(builder.build());
startActivity(intent);

Das folgende Beispiel zeigt, wie Sie einen Termin öffnen, um ihn sich anzusehen:

Kotlin

val eventID: Long = 208
...
val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val intent = Intent(Intent.ACTION_VIEW).setData(uri)
startActivity(intent)

Java

long eventID = 208;
...
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_VIEW)
   .setData(uri);
startActivity(intent);

Adapter für die Synchronisierung

Es gibt nur geringfügige Unterschiede bei der Art und Weise, wie eine Anwendung und ein Synchronisierungsadapter auf den Kalenderanbieter zugreifen:

  • Ein Synchronisierungsadapter muss angeben, dass es sich um einen Synchronisierungsadapter handelt, indem CALLER_IS_SYNCADAPTER auf true festgelegt wird.
  • Ein Synchronisierungsadapter muss einen ACCOUNT_NAME und einen ACCOUNT_TYPE als Abfrageparameter im URI angeben.
  • Ein Synchronisierungsadapter hat Schreibzugriff auf mehr Spalten als eine Anwendung oder ein Widget. Eine Anwendung kann beispielsweise nur einige Eigenschaften eines Kalenders ändern, z. B. seinen Namen, seinen Anzeigenamen, die Sichtbarkeitseinstellung und ob der Kalender synchronisiert wird. Ein Synchronisierungsadapter kann dagegen nicht nur auf diese Spalten, sondern auch auf viele andere zugreifen, z. B. auf Kalenderfarbe, Zeitzone, Zugriffsebene und Standort. Ein Synchronisierungsadapter ist jedoch auf die angegebenen ACCOUNT_NAME und ACCOUNT_TYPE beschränkt.

Mit der folgenden Hilfsmethode können Sie einen URI zur Verwendung mit einem Synchronisierungsadapter zurückgeben:

Kotlin

fun asSyncAdapter(uri: Uri, account: String, accountType: String): Uri {
    return uri.buildUpon()
            .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
            .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, account)
            .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, accountType).build()
}

Java

static Uri asSyncAdapter(Uri uri, String account, String accountType) {
    return uri.buildUpon()
        .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true")
        .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
        .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
 }