Der Kalenderanbieter ist ein Repository für die Kalendertermine eines Nutzers. Mit der Kalenderanbieter API können Sie Vorgänge für Kalender, Termine, Teilnehmer, Erinnerungen usw. abfragen, einfügen, aktualisieren und löschen.
Die Calender Provider API kann von Anwendungen und Synchronisierungsadaptern verwendet werden. Die Regeln variieren je nach Art des Programms, das die Aufrufe durchführt. In diesem Dokument geht es hauptsächlich um die Verwendung der Calender Provider API als Anwendung. Weitere Informationen zu den Unterschieden zwischen Synchronisierungsadaptern finden Sie unter Synchronisierungsadapter.
Normalerweise muss das Manifest einer App zum Lesen oder Schreiben von Kalenderdaten die erforderlichen Berechtigungen enthalten, wie unter Nutzerberechtigungen beschrieben. Um gängige Vorgänge einfacher auszuführen, bietet der Kalenderanbieter eine Reihe von Intents, wie unter Kalender-Intents beschrieben. Über diese Intents werden Nutzer zur Kalenderanwendung weitergeleitet, um Termine einzufügen, anzusehen und zu bearbeiten. Der Nutzer interagiert mit der Kalenderanwendung und kehrt dann zur ursprünglichen Anwendung zurück. Daher muss Ihre Anwendung keine Berechtigungen anfordern oder eine Benutzeroberfläche zum Anzeigen oder Erstellen von Ereignissen bereitstellen.
Grundlegende Informationen
Contentanbieter speichern Daten und machen sie für Anwendungen zugänglich. Die von der Android-Plattform angebotenen Inhaltsanbieter (einschließlich des Kalenderanbieters) stellen Daten in der Regel in Form einer Reihe von Tabellen auf der Grundlage eines relationalen Datenbankmodells bereit. Dabei ist jede Zeile ein Datensatz und jede Spalte enthält Daten eines bestimmten Typs und einer bestimmten Bedeutung. Über die Calender Provider API erhalten Anwendungen und Synchronisierungsadapter Lese-/Schreibzugriff auf die Datenbanktabellen mit den Kalenderdaten eines Nutzers.
Jeder Contentanbieter stellt einen öffentlichen URI (verpackt als Uri
-Objekt) bereit, der seinen Datensatz eindeutig identifiziert. Ein Contentanbieter, der mehrere Datasets (mehrere Tabellen) steuert, stellt für jeden einen separaten URI zur Verfügung. Alle URIs für Anbieter beginnen mit dem String „content://“. Dadurch wird angegeben, dass die Daten von einem Contentanbieter kontrolliert 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. Es werden die Haupttabellen und die Felder angezeigt, die sie miteinander verknüpfen.
Ein Nutzer kann mehrere Kalender haben und verschiedene Kalender können mit verschiedenen Arten von Konten verknüpft sein (Google Kalender, Exchange usw.).
CalendarContract
definiert das Datenmodell von kalender- und terminbezogenen Informationen. Diese Daten werden in verschiedenen Tabellen gespeichert, die unten aufgeführt sind.
Tabelle (Klasse) | Beschreibung |
---|---|
Diese Tabelle enthält kalenderspezifische Informationen. Jede Zeile in dieser Tabelle enthält die Details für einen einzelnen Kalender, z. B. Name, Farbe, Synchronisierungsinformationen usw. | |
CalendarContract.Events |
Diese Tabelle enthält die ereignisspezifischen Informationen. Jede Zeile in dieser Tabelle enthält die Informationen für ein einzelnes Ereignis, z. B. Titel, Ort, Beginn und Ende der Veranstaltung. Das Ereignis kann einmalig oder mehrmals auftreten. Gäste, Erinnerungen und erweiterte Properties werden in separaten Tabellen gespeichert.
Jedes Element hat ein EVENT_ID , das auf das _ID in der Ereignistabelle verweist. |
CalendarContract.Instances |
Diese Tabelle enthält die Start- und Endzeit für jedes Auftreten eines Ereignisses. Jede Zeile in dieser Tabelle steht für ein einzelnes Ereignisvorkommen. Bei einmaligen Ereignissen werden die Instanzen 1:1 den Ereignissen zugeordnet. Bei wiederkehrenden Ereignissen werden automatisch mehrere Zeilen generiert, die mehreren Vorkommen dieses Ereignisses entsprechen. |
CalendarContract.Attendees |
Diese Tabelle enthält die Informationen zum Ereignisteilnehmer (Gast). Jede Zeile steht für einen einzelnen Gast eines Ereignisses. Sie gibt den Typ des Gasts und seine Teilnahmeantwort auf den Termin an. |
CalendarContract.Reminders |
Diese Tabelle enthält die Benachrichtigungsdaten. Jede Zeile steht für eine einzelne Benachrichtigung für ein Ereignis. Ein Termin
kann mehrere Erinnerungen haben. Die maximale Anzahl von Erinnerungen pro Termin wird in MAX_REMINDERS angegeben. Sie wird vom Synchronisierungsadapter festgelegt, der Inhaber des jeweiligen Kalenders ist. Erinnerungen werden in Minuten vor dem Termin angegeben und haben eine Methode, die bestimmt, wie der Nutzer benachrichtigt wird. |
Die Kalenderanbieter API ist flexibel und leistungsstark. Gleichzeitig ist es wichtig, eine gute Endnutzererfahrung zu bieten und die Integrität des Kalenders und seiner Daten zu schützen. Beachten Sie deshalb bei der Verwendung der API Folgendes:
- Kalendertermine einfügen, aktualisieren und ansehen Wenn Sie Termine direkt vom Kalenderanbieter einfügen, ändern und lesen möchten, benötigen Sie die entsprechenden Berechtigungen. Wenn Sie jedoch keine vollwertige Kalenderanwendung oder keinen vollwertigen Synchronisierungsadapter erstellen, müssen diese Berechtigungen nicht angefordert werden. Sie können stattdessen von der Kalenderanwendung von Android unterstützte Intents verwenden, um Lese- und Schreibvorgänge an diese Anwendung zu übergeben. Wenn Sie die Intents verwenden, sendet Ihre Anwendung Nutzer an die Kalenderanwendung, um den gewünschten Vorgang in einem vorausgefüllten Formular auszuführen. Anschließend werden sie an Ihre Anwendung zurückgegeben. Wenn Sie Ihre Anwendung so gestalten, dass gängige Vorgänge über den Kalender ausgeführt werden, bieten Sie den Nutzern eine einheitliche, robuste Benutzeroberfläche. Dies ist der empfohlene 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
undCalendarContract.Events
gibt es Spalten, die für die zu verwendenden Synchronisierungsadapter reserviert sind. Der Anbieter und die Anwendungen dürfen keine Änderungen daran vornehmen. Tatsächlich sind sie nur sichtbar, wenn sie über einen Synchronisierungsadapter aufgerufen werden. Weitere Informationen zu Synchronisierungsadaptern finden Sie unter Synchronisierungsadapter.
Nutzerberechtigungen
Zum Lesen von Kalenderdaten muss eine App die Berechtigung READ_CALENDAR
in der Manifestdatei enthalten. Es 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 einem Synchronisierungsadapter beschrieben 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, den der Nutzer sieht. |
VISIBLE |
Ein boolescher Wert, der angibt, ob der Kalender zur Anzeige ausgewählt ist. Der Wert 0 bedeutet, dass mit diesem Kalender verknüpfte Termine nicht angezeigt werden sollen. Der Wert „1“ bedeutet, dass mit diesem Kalender verknüpfte Termine 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 und die Termine auf dem Gerät gespeichert werden sollen. Der Wert 0 bedeutet, dass dieser Kalender nicht synchronisiert und keine Termine auf dem Gerät gespeichert werden sollen. Der Wert „1“ bedeutet, dass Termine für diesen Kalender synchronisiert und die Termine auf dem Gerät gespeichert werden. |
Kontotyp für alle Vorgänge einschließen
Wenn Sie eine Abfrage für einen Calendars.ACCOUNT_NAME
ausführen, müssen Sie auch Calendars.ACCOUNT_TYPE
in die Auswahl aufnehmen. Das liegt daran, dass ein bestimmtes Konto nur dann als eindeutig gilt, wenn sowohl seine ACCOUNT_NAME
als auch seine ACCOUNT_TYPE
festgelegt sind. ACCOUNT_TYPE
ist der String für die Kontoauthentifizierungs-App, die bei der Registrierung des Kontos mit AccountManager
verwendet wurde. Für Kalender, die nicht mit einem Gerätekonto verknüpft sind, gibt es auch einen speziellen Kontotyp mit dem Namen ACCOUNT_TYPE_LOCAL
.
ACCOUNT_TYPE_LOCAL
-Konten werden nicht synchronisiert.
Kalender abfragen
Das folgende Beispiel zeigt, wie Sie die Kalender abrufen, die einem bestimmten Nutzer gehören. Der Einfachheit halber wird in diesem Beispiel der Abfragevorgang im Benutzeroberflächen-Thread („Hauptthread“) dargestellt. In der Praxis sollte dies in einem asynchronen Thread statt im Hauptthread erfolgen. Weitere Informationen finden Sie unter Loader. Wenn Sie Daten nicht nur lesen, sondern ändern möchten, finden Sie unter AsyncQueryHandler
weitere Informationen.
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 Ihre Abfrage. Die Auswahl gibt die Kriterien für die Abfrage an. In diesem Beispiel wird nach Kalendern gesucht, die die ACCOUNT_NAME
"hera@example.com", die ACCOUNT_TYPE
"com.example" und die OWNER_ACCOUNT
"hera@example.com" enthalten. Wenn Sie alle Kalender sehen möchten, die ein Nutzer angesehen hat, und nicht nur Kalender, die ihm gehören, lassen Sie OWNER_ACCOUNT
weg.
Die Abfrage gibt ein Cursor
-Objekt zurück, mit dem Sie die von der Datenbankabfrage zurückgegebene Ergebnismenge durchsuchen können. Weitere Informationen zur Verwendung von Abfragen bei Contentanbietern finden Sie unter 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 mit dem Cursor durch die Ergebnisse geführt. Die zu Beginn des Beispiels eingerichteten Konstanten werden verwendet, 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 den URI (withAppendedId()
) oder als erstes Auswahlelement angeben. Die Auswahl sollte mit "_id=?"
beginnen und der erste selectionArg
sollte der _ID
des Kalenders sein.
Sie können Aktualisierungen auch vornehmen, indem Sie die ID im URI codieren. In diesem Beispiel wird der Anzeigename eines Kalenders nach dem Ansatz (withAppendedId()
) geändert:
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 sind so konzipiert, dass sie hauptsächlich über einen Synchronisierungsadapter verwaltet werden, daher sollten Sie neue Kalender nur als Synchronisierungsadapter einfügen. In den meisten Fällen können Anwendungen nur oberflächliche Änderungen an Kalendern vornehmen, z. B. den Anzeigenamen ändern. Wenn eine Anwendung einen lokalen Kalender erstellen muss, kann sie das Einfügen des Kalenders als Synchronisierungsadapter mit einem ACCOUNT_TYPE
von ACCOUNT_TYPE_LOCAL
ausführen.
ACCOUNT_TYPE_LOCAL
ist ein spezieller Kontotyp für Kalender, die nicht mit einem Gerätekonto verknüpft sind. Kalender dieses Typs werden nicht mit einem Server synchronisiert. Eine Beschreibung von Synchronisierungsadaptern finden Sie unter Synchronisierungsadapter.
Ereignistabelle
Die Tabelle CalendarContract.Events
enthält Details zu einzelnen Ereignissen. Zum Hinzufügen, Aktualisieren oder Löschen von Ereignissen muss eine Anwendung die Berechtigung WRITE_CALENDAR
in der Manifestdatei enthalten.
Die folgenden Ereignisspalten können sowohl von einer Anwendung als auch von einem Synchronisierungsadapter beschreibt werden. Eine vollständige Liste der unterstützten Felder finden Sie in der Referenz zu CalendarContract.Events
.
Konstante | Beschreibung |
---|---|
CALENDAR_ID |
_ID des Kalenders, zu dem der Termin gehört |
ORGANIZER |
E-Mail-Adresse des Organisators (Inhabers) des Termins. |
TITLE |
Der Titel des Termins. |
EVENT_LOCATION |
Ort, an dem das Ereignis stattfindet. |
DESCRIPTION |
Die Beschreibung des Ereignisses. |
DTSTART |
Die Zeit, zu der das Ereignis seit der Epoche in UTC-Millisekunden beginnt. |
DTEND |
Die Uhrzeit, zu der das Ereignis seit der Epoche in UTC-Millisekunden endet. |
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.
Ein Wert von "PT1H" gibt beispielsweise an, dass das Ereignis eine Stunde dauern soll, und der Wert "P2W" gibt eine Dauer von 2 Wochen an. |
ALL_DAY |
Der Wert „1“ bedeutet, dass dieses Ereignis den gesamten Tag gemäß der lokalen Zeitzone einnimmt. Der Wert 0 bedeutet, dass es sich um ein reguläres Ereignis handelt, das zu jeder Zeit eines Tages beginnen und enden kann. |
RRULE |
Die Wiederholungsregel für das Ereignisformat. Beispiel: "FREQ=WEEKLY;COUNT=10;WKST=SU" . Weitere Beispiele finden Sie hier. |
RDATE |
Die Wiederholungsdaten des Termins.
Normalerweise verwenden Sie RDATE in Verbindung mit RRULE , um eine Reihe von sich wiederholenden Vorkommen zu definieren. Weitere Informationen finden Sie in der RFC5545-Spezifikation. |
AVAILABILITY |
Gibt an, ob es sich bei diesem Ereignis um eine kostenlose Zeit oder um eine kostenlose Zeit handelt, die verschoben werden kann. |
GUESTS_CAN_MODIFY |
Gibt an, ob Gäste den Termin bearbeiten können. |
GUESTS_CAN_INVITE_OTHERS |
Gibt an, ob Gäste weitere 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 Intent zum Einfügen eines Ereignisses verwenden beschrieben. Bei Bedarf können Sie Ereignisse jedoch auch direkt einfügen. In diesem Abschnitt wird beschrieben, wie Sie dies tun.
Folgende Regeln gelten für das Einfügen eines neuen Ereignisses:
- Sie müssen
CALENDAR_ID
undDTSTART
angeben. - Sie müssen eine
EVENT_TIMEZONE
angeben. Verwenden SiegetAvailableIDs()
, um eine Liste der installierten Zeitzonen-IDs des Systems abzurufen. Diese Regel gilt nicht, wenn Sie ein Ereignis über den IntentINSERT
einfügen, wie unter Intent zum Einfügen eines Ereignisses verwenden beschrieben. Dabei wird eine Standardzeitzone angegeben. - Für einmalige Termine musst du
DTEND
angeben. - Bei wiederkehrenden Terminen müssen Sie zusätzlich zu
RRULE
oderRDATE
eineDURATION
angeben. Diese Regel gilt nicht, wenn Sie ein Ereignis über den IntentINSERT
einfügen, wie unter Intent zum Einfügen eines Ereignisses verwenden beschrieben. In diesem Szenario können SieRRULE
in Verbindung mitDTSTART
undDTEND
verwenden und die Kalenderanwendung wandelt ihn automatisch in eine Dauer um.
Hier ist ein Beispiel für das Einfügen eines Ereignisses. Dies wird der Einfachheit halber im UI-Thread durchgefü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 die Ereignis-ID nach dem Erstellen des Ereignisses erfasst. Dies ist die einfachste Methode, um eine Ereignis-ID zu erhalten. Sie benötigen die Termin-ID häufig, um andere Kalendervorgänge auszuführen, z. B. um Teilnehmer oder Erinnerungen zu einem Termin hinzuzufügen.
Updates
Wenn Nutzer in Ihrer App die Möglichkeit haben, Ereignisse zu bearbeiten, empfehlen wir die Verwendung eines EDIT
-Intents, wie unter Intent zum Bearbeiten eines Ereignisses verwenden beschrieben.
Bei Bedarf können Sie Termine aber auch direkt bearbeiten. Wenn Sie ein Ereignis aktualisieren möchten, können Sie die _ID
des Ereignisses entweder als angehängte ID an den URI (withAppendedId()
) oder als erstes Auswahlelement angeben.
Die Auswahl sollte mit "_id=?"
beginnen und der erste selectionArg
sollte der _ID
des Ereignisses sein. Sie können Aktualisierungen auch mit einer Auswahl ohne ID vornehmen. Hier ist ein Beispiel für die Aktualisierung eines Ereignisses. Der Titel des Termins wird mit der Methode withAppendedId()
geändert:
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 entweder anhand seiner _ID
als angehängte ID im URI oder über die Standardauswahl löschen. Wenn Sie eine angehängte ID verwenden, ist nicht gleichzeitig eine Auswahl möglich.
Es gibt zwei Versionen von Delete: als Anwendung und als Synchronisierungsadapter. Beim Löschen einer Anwendung wird die Spalte deleted auf 1 gesetzt. Dieses Flag, das dem Synchronisierungsadapter mitteilt, dass die Zeile gelöscht wurde und dass die Löschung an den Server weitergeleitet werden soll. Durch das Löschen eines Synchronisierungsadapters werden das Ereignis und alle zugehörigen Daten aus der Datenbank entfernt. Hier ist ein Beispiel für eine Anwendung, die ein Ereignis über ihre _ID
löscht:
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
stellt einen einzelnen Gast oder Gast eines Termins dar. Durch Aufrufen von query()
wird eine Liste der Teilnehmer des Termins mit dem angegebenen EVENT_ID
zurückgegeben.
Dieser EVENT_ID
muss mit dem _ID
eines bestimmten Ereignisses übereinstimmen.
In der folgenden Tabelle sind die beschreibbaren Felder aufgeführt. Wenn Sie einen neuen Gast einfügen, müssen Sie alle außer ATTENDEE_NAME
einschließen.
Konstante | Beschreibung |
---|---|
EVENT_ID |
Die ID des Ereignisses. |
ATTENDEE_NAME |
Der Name des Teilnehmers. |
ATTENDEE_EMAIL |
Die E-Mail-Adresse des Teilnehmers. |
ATTENDEE_RELATIONSHIP |
Die Beziehung des Teilnehmers zum Ereignis. Eine der folgenden Optionen: |
ATTENDEE_TYPE |
Der Teilnehmertyp. Eine der folgenden Optionen: |
ATTENDEE_STATUS |
Der Teilnahmestatus des Teilnehmers. Eine der folgenden Optionen: |
Teilnehmer hinzufügen
In diesem Beispiel wird einem Termin ein einzelner Gast hinzugefügt. 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);
Tabelle mit Erinnerungen
Jede Zeile der Tabelle CalendarContract.Reminders
steht für eine einzelne Erinnerung für ein Ereignis. Beim Aufrufen von query()
wird eine Liste von Erinnerungen für das Ereignis mit dem angegebenen EVENT_ID
zurückgegeben.
In der folgenden Tabelle sind die beschreibbaren Felder für Erinnerungen aufgeführt. Alle müssen beim Einfügen
einer neuen Erinnerung angegeben werden. Beachten Sie, dass Synchronisierungsadapter die unterstützten Erinnerungstypen in der Tabelle CalendarContract.Calendars
angeben. Weitere Informationen finden Sie unter ALLOWED_REMINDERS
.
Konstante | Beschreibung |
---|---|
EVENT_ID |
Die ID des Ereignisses. |
MINUTES |
Die Minuten vor dem Ereignis, in denen die Erinnerung ausgelöst werden soll. |
METHOD |
Die auf dem Server festgelegte Alarmmethode. Eine der folgenden Optionen: |
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);
Instanztabelle
Die Tabelle CalendarContract.Instances
enthält die Start- und Endzeit für das Auftreten eines Ereignisses. Jede Zeile in dieser Tabelle steht für ein einzelnes Ereignisvorkommen. Die Instanztabelle ist nicht beschreibbar und bietet nur eine Möglichkeit, Ereignisvorkommen 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 im Verhältnis zur Zeitzone des Kalenders. |
END_MINUTE |
Die Endminute der Instanz, gemessen ab Mitternacht in der Zeitzone des Kalenders. |
EVENT_ID |
Der _ID des Ereignisses für diese Instanz. |
START_DAY |
Der julianische Starttag der Instanz im Verhältnis zur Zeitzone des Kalenders. |
START_MINUTE |
Die Startminute der Instanz, gemessen ab Mitternacht, bezogen auf die Zeitzone des Kalenders. |
Instanztabelle abfragen
Wenn Sie die Instanztabelle abfragen möchten, müssen Sie im URI eine Bereichszeit für die Abfrage angeben. In diesem Beispiel erhält CalendarContract.Instances
über die Implementierung der CalendarContract.EventsColumns
-Schnittstelle Zugriff auf das Feld TITLE
.
Mit anderen Worten: TITLE
wird über eine Datenbankansicht zurückgegeben und nicht durch Abfragen der Rohtabelle CalendarContract.Instances
.
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 Kalenderanwendung von Android 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 |
CalendarContract.CONTENT_URI auf den URI verweisen.
Ein Beispiel für die Verwendung dieses Intents finden Sie unter Intents zum Ansehen von Kalenderdaten verwenden.
|
Den Kalender für die in <ms_since_epoch> angegebene Zeit öffnen. |
Keine. |
Events.CONTENT_URI auf den URI verweisen.
Ein Beispiel für die Verwendung dieses Intents finden Sie unter Intents zum Ansehen von Kalenderdaten verwenden.
|
Sehen Sie sich das in <event_id> angegebene Ereignis an. |
CalendarContract.EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_END_TIME |
|
EDIT |
Events.CONTENT_URI auf den URI verweisen.
Ein Beispiel für die Verwendung dieses Intents finden Sie unter Intent zum Bearbeiten eines Ereignisses verwenden.
|
Bearbeite das in <event_id> angegebene Ereignis. |
CalendarContract.EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_END_TIME |
EDIT INSERT |
Events.CONTENT_URI auf den URI verweisen.
Ein Beispiel für die Verwendung dieses Intents finden Sie unter Mit einem Intent ein Ereignis einfügen.
|
Erstellen Sie einen Termin. | Alle in der Tabelle unten 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 |
Ereignisbeginn in Millisekunden seit der Epoche. |
CalendarContract.EXTRA_EVENT_END_TIME |
Ereignisende in Millisekunden seit Epoche. |
CalendarContract.EXTRA_EVENT_ALL_DAY |
Ein boolescher Wert, der angibt, dass ein Ereignis ganztägig ist. 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 |
Gibt an, ob der Termin privat oder öffentlich ist. |
Events.AVAILABILITY |
Ob es sich um einen kostenlosen Termin oder eine kostenlose Zeit handelt, die verschoben werden kann. |
In den folgenden Abschnitten wird die Verwendung dieser Intents beschrieben.
Intent zum Einfügen eines Ereignisses verwenden
Mit dem Intent INSERT
kann Ihre Anwendung die Aufgabe zum Einfügen eines Termins an den Kalender selbst übergeben.
Bei diesem Ansatz muss für deine App nicht einmal die Berechtigung WRITE_CALENDAR
in der Manifestdatei enthalten sein.
Wenn Nutzer eine Anwendung mit diesem Ansatz ausführen, sendet sie sie an den Kalender, um das Hinzufügen des Termins abzuschließen. Der Intent INSERT
verwendet zusätzliche Felder, um ein Formular vorab mit den Details des Termins im Kalender auszufüllen. Nutzer können den Termin dann absagen, das Formular nach Bedarf bearbeiten oder den Termin in ihren Kalendern speichern.
Hier sehen Sie ein Code-Snippet, mit dem ein Ereignis für den 19. Januar 2012 geplant wird, das von 7:30 Uhr bis 8:30 Uhr stattfindet. Beachten Sie Folgendes zu diesem Code-Snippet:
- Er gibt
Events.CONTENT_URI
als URI an. - Die zusätzlichen Felder
CalendarContract.EXTRA_EVENT_BEGIN_TIME
undCalendarContract.EXTRA_EVENT_END_TIME
werden verwendet, um das Formular mit dem Zeitpunkt des Ereignisses vorab auszufüllen. Die Werte für diese Zeiten müssen in UTC-Millisekunden seit der Epoche angegeben werden. - Über das zusätzliche Feld
Intent.EXTRA_EMAIL
wird eine durch Kommas getrennte Liste von eingeladenen Personen bereitgestellt, die anhand ihrer E-Mail-Adresse angegeben werden.
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 Ereignisse direkt aktualisieren. Eine Anleitung dazu finden Sie unter Ereignisse aktualisieren. Wenn Sie jedoch den Intent EDIT
verwenden, kann eine Anwendung, die nicht berechtigt ist, die Terminbearbeitung an die Kalenderanwendung zu übergeben.
Wenn Nutzer mit der Bearbeitung ihres Termins in Google Kalender fertig sind, werden sie zur ursprünglichen Anwendung zurückgeleitet.
Hier ist ein Beispiel für einen Intent, mit dem für einen bestimmten Termin ein neuer Titel festgelegt wird und Nutzer den Termin im Kalender bearbeiten können.
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 zum Ansehen von Kalenderdaten verwenden
Kalenderanbieter bietet zwei verschiedene Möglichkeiten, den Intent VIEW
zu verwenden:
- So öffnen Sie den Kalender für ein bestimmtes Datum:
- Um einen Termin anzusehen.
Das folgende Beispiel zeigt, wie Sie den Kalender für 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 zur Ansicht öffnen:
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 synchronisieren
Es gibt nur geringfügige Unterschiede darin, wie eine Anwendung und ein Synchronisierungsadapter auf den Kalenderanbieter zugreifen:
- Ein Synchronisierungsadapter muss angeben, dass er ein Synchronisierungsadapter ist, indem Sie
CALLER_IS_SYNCADAPTER
auftrue
setzen. - Ein Synchronisierungsadapter muss ein
ACCOUNT_NAME
und einACCOUNT_TYPE
als Abfrageparameter im URI angeben. - Ein Synchronisierungsadapter hat Schreibzugriff auf mehr Spalten als eine Anwendung oder ein Widget.
Beispielsweise kann eine Anwendung nur wenige Eigenschaften eines Kalenders ändern, z. B. den Namen, den Anzeigenamen, die Sichtbarkeitseinstellung und ob der Kalender synchronisiert wird. Im Vergleich dazu kann ein Synchronisierungsadapter nicht nur auf diese Spalten zugreifen, sondern auch auf viele andere, z. B. auf Kalenderfarbe, Zeitzone, Zugriffsebene, Standort usw.
Ein Synchronisierungsadapter ist jedoch auf die angegebenen
ACCOUNT_NAME
undACCOUNT_TYPE
beschränkt.
Hier ist eine Hilfsmethode, mit der Sie einen URI zur Verwendung mit einem Synchronisierungsadapter zurückgeben können:
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(); }