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.
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 |
---|---|
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
undCalendarContract.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:
- Sie müssen
CALENDAR_ID
undDTSTART
angeben. - Sie müssen ein
EVENT_TIMEZONE
einfügen. So rufen Sie eine Liste ab: der vom System installierten Zeitzonen-IDs verwenden SiegetAvailableIDs()
. Diese Regel gilt nicht, wenn Sie ein Ereignis über denINSERT
-Intent einfügen, wie unter Ereignisse über einen Intent einfügen beschrieben. In diesem Fall wird eine Standardzeitzone angegeben. - Für einmalige Termine muss
DTEND
angegeben werden. - Bei wiederkehrenden Ereignissen müssen Sie zusätzlich zu
RRULE
oderRDATE
einenDURATION
angeben. Diese Regel gilt nicht, wenn Sie ein Ereignis über denINSERT
-Intent einfügen, der unter Ereignisse über einen Intent einfügen beschrieben wird. In diesem Fall können SieRRULE
in Verbindung mitDTSTART
undDTEND
verwenden. Die Kalenderanwendung wandelt den Wert dann automatisch in eine Dauer um.
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 |
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. |
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 |
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 |
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:
Events.CONTENT_URI
wird als URI angegeben.- Dabei werden die zusätzlichen Felder
CalendarContract.EXTRA_EVENT_BEGIN_TIME
undCalendarContract.EXTRA_EVENT_END_TIME
verwendet, um das Formular vorab mit der Uhrzeit des Ereignisses auszufüllen. Die Werte für diese Zeiten müssen in UTC-Millisekunden angegeben werden. aus der Epoche. - Im zusätzlichen Feld
Intent.EXTRA_EMAIL
wird eine durch Kommas getrennte Liste der eingeladenen Personen angegeben, die anhand der E-Mail-Adressen festgelegt wird.
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
auftrue
festgelegt wird. - Ein Synchronisierungsadapter muss einen
ACCOUNT_NAME
und einenACCOUNT_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
undACCOUNT_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(); }