Takvim sağlayıcısına genel bakış

Takvim sağlayıcı, kullanıcının takvim etkinliklerinin bulunduğu bir depodur. Takvim Sağlayıcı API'si; takvimler, etkinlikler, katılımcılar, hatırlatıcılar vb. üzerinde sorgu, ekleme, güncelleme ve silme işlemleri yapmanıza olanak tanır.

Takvim Sağlayıcı API'si, uygulamalar ve senkronizasyon bağdaştırıcılar tarafından kullanılabilir. Kurallar, çağrı yapan programın türüne göre değişiklik gösterir. Bu doküman, öncelikle Takvim Sağlayıcı API'sinin uygulama olarak kullanılmasına odaklanır. Senkronizasyon adaptörlerinin farklılıkları hakkında bilgi edinmek için Senkronizasyon Adaptörleri başlıklı makaleyi inceleyin.

Normalde, takvim verilerini okumak veya yazmak için uygulamanın manifest dosyasında Kullanıcı İzinleri bölümünde açıklanan uygun izinler bulunmalıdır. Takvim sağlayıcı, sık kullanılan işlemleri kolaylaştırmak için Takvim Intent'leri bölümünde açıklanan bir dizi intent sunar. Bu amaçlar; etkinlik eklemek, görüntülemek ve düzenlemek için kullanıcıları Takvim uygulamasına yönlendirir. Kullanıcı, Takvim uygulamasıyla etkileşimde bulunur ve ardından orijinal uygulamaya geri döner. Bu nedenle, uygulamanızın izin istemesi veya etkinlikleri görüntülemek ya da oluşturmak için bir kullanıcı arayüzü sağlaması gerekmez.

Temel Bilgiler

İçerik sağlayıcılar verileri depolar ve uygulamalara erişilebilir hale getirir. Android platformu tarafından sunulan içerik sağlayıcılar (Takvim Sağlayıcı dahil), verileri genellikle her satırın bir kayıt ve her sütunun belirli bir tür ve anlama sahip veriler olduğu ilişkisel veritabanı modeline dayalı bir tablo grubu olarak gösterir. Uygulamalar ve senkronizasyon bağdaştırıcılar, Takvim Sağlayıcı API'si aracılığıyla kullanıcının takvim verilerini içeren veritabanı tablolarına okuma/yazma erişimi elde edebilir.

Her içerik sağlayıcı, veri kümesini benzersiz şekilde tanımlayan herkese açık bir URI (Uri nesnesi olarak sarmalanır) sağlar. Birden fazla veri kümesini (birden fazla tablo) kontrol eden bir içerik sağlayıcı, her biri için ayrı bir URI gösterir. Sağlayıcılara ait tüm URI'ler "content://" dizesiyle başlar. Bu, verilerin bir içerik sağlayıcı tarafından kontrol edildiğini tanımlar. Takvim Sağlayıcı, sınıflarının (tablolar) her biri için URI'ler için sabitler tanımlar. Bu URI'ler <class>.CONTENT_URI biçimindedir. Örneğin, Events.CONTENT_URI.

Şekil 1'de Takvim Sağlayıcı veri modelinin grafiksel gösterimi gösterilmektedir. Ana tabloları ve bunları birbirine bağlayan alanları gösterir.

Takvim Sağlayıcı Veri Modeli

Şekil 1. Takvim Sağlayıcı veri modeli.

Bir kullanıcının birden fazla takvimi olabilir ve farklı takvimler farklı hesap türleriyle (Google Takvim, Exchange vb.) ilişkilendirilebilir.

CalendarContract, takvim ve etkinlikle ilgili bilgilerin veri modelini tanımlar. Bu veriler aşağıda listelenen çeşitli tablolarda depolanır.

Tablo (Sınıf) Açıklama

CalendarContract.Calendars

Bu tabloda takvime özgü bilgiler bulunur. Bu tablodaki her satırda tek bir takvime ilişkin ad, renk, senkronizasyon bilgileri gibi ayrıntılar bulunur.
CalendarContract.Events Bu tabloda etkinliğe özel bilgiler yer alır. Bu tablodaki her satırda tek bir etkinliğe ait bilgiler (ör. etkinlik başlığı, konum, başlangıç zamanı, bitiş zamanı vb.) bulunur. Etkinlik tek seferlik veya birden fazla kez tekrarlanabilir. Katılımcılar, hatırlatıcılar ve genişletilmiş özellikler ayrı tablolarda saklanır. Her birinin, Etkinlikler tablosundaki _ID'a referans veren bir EVENT_ID vardır.
CalendarContract.Instances Bu tabloda, bir etkinliğin her gerçekleşmesinin başlangıç ve bitiş zamanı bulunur. Bu tablodaki her satır tek bir etkinlik oluşumunu temsil eder. Tek seferlik etkinliklerde örneklerin etkinliklerle 1:1 eşlemesi vardır. Yinelenen etkinlikler için, söz konusu etkinliğin birden fazla gerçekleşmesine karşılık gelen birden fazla satır otomatik olarak oluşturulur.
CalendarContract.Attendees Bu tabloda etkinlik katılımcısı (konuk) bilgileri yer alır. Her satır, bir etkinliğin tek bir konuğunu temsil eder. Davetlinin türünü ve etkinlik için verdiği katılım yanıtını belirtir.
CalendarContract.Reminders Bu tabloda uyarı/bildirim verileri bulunur. Her satır, bir etkinlik için tek bir uyarıyı temsil eder. Bir etkinliğin birden fazla hatırlatıcısı olabilir. Etkinlik başına maksimum hatırlatıcı sayısı, MAX_REMINDERS içinde belirtilir. Bu değer, ilgili takvimin sahibi olan senkronizasyon bağdaştırıcısı tarafından belirlenir. Hatırlatıcılar, etkinlikten kaç dakika önce gösterileceğini belirtir ve kullanıcının nasıl uyarılacağını belirleyen bir yönteme sahiptir.

Calendar Provider API, esnek ve güçlü olacak şekilde tasarlanmıştır. Aynı zamanda, iyi bir son kullanıcı deneyimi sunmak ve takvim ile verilerinin bütünlüğünü korumak da önemlidir. Bu amaçla, API'yi kullanırken aklınızda bulundurmanız gereken bazı noktalar aşağıda belirtilmiştir:

  • Takvim etkinlikleri ekleme, güncelleme ve görüntüleme. Takvim sağlayıcısından doğrudan etkinlik eklemek, değiştirmek ve okumak için uygun izinlere sahip olmanız gerekir. Ancak tam teşekküllü bir takvim uygulaması veya senkronizasyon bağdaştırıcısı oluşturmuyorsanız bu izinleri istemeniz gerekmez. Bunun yerine, okuma ve yazma işlemlerini Android'in Takvim uygulamasına aktarmak için Android'in Takvim uygulaması tarafından desteklenen intent'leri kullanabilirsiniz. Amaçları kullandığınızda, uygulamanız istenen işlemi önceden doldurulmuş bir formda yapmaları için kullanıcıları Takvim uygulamasına gönderir. İşlem tamamlandıktan sonra kullanıcılar uygulamanıza geri döner. Uygulamanızı, Takvim aracılığıyla sık yapılan işlemleri gerçekleştirecek şekilde tasarladığınızda kullanıcılara tutarlı ve güçlü bir kullanıcı arayüzü sunarsınız. Bu, önerilen yaklaşımdır. Daha fazla bilgi için Takvim intent'leri başlıklı makaleyi inceleyin.
  • Senkronizasyon adaptörleri Senkronizasyon bağdaştırıcısı, kullanıcının cihazındaki takvim verilerini başka bir sunucu veya veri kaynağıyla senkronize eder. CalendarContract.Calendars ve CalendarContract.Events tablolarında, senkronizasyon bağdaştırıcılarının kullanması için ayrılmış sütunlar bulunur. Sağlayıcı ve uygulamalar bu değerleri değiştirmemelidir. Hatta senkronizasyon bağdaştırıcısı olarak erişilmediği sürece görünmezler. Senkronizasyon bağdaştırıcılar hakkında daha fazla bilgi için Senkronizasyon Bağdaştırıcılar başlıklı makaleyi inceleyin.

Kullanıcı izinleri

Bir uygulamanın, takvim verilerini okuyabilmesi için manifest dosyasına READ_CALENDAR iznini eklemesi gerekir. Takvim verilerini silme, ekleme veya güncelleme WRITE_CALENDAR iznini içermelidir:

<?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>

Takvimler tablosu

CalendarContract.Calendars tablosu, her bir takvimle ilgili ayrıntıları içerir. Aşağıdaki Takvimler sütunları hem bir uygulama hem de senkronizasyon bağdaştırıcısı tarafından yazılabilir. Desteklenen alanların tam listesi için CalendarContract.Calendars referansına bakın.

Sabit Açıklama
NAME Takvimin adı.
CALENDAR_DISPLAY_NAME Bu takvimin kullanıcıya gösterilen adı.
VISIBLE Takvimin görüntülenmek için seçili olup olmadığını gösteren boole değeri. 0 değeri, bu takvimle ilişkili etkinliklerin gösterilmemesi gerektiğini belirtir. 1 değeri, bu takvimle ilişkili etkinliklerin gösterilmesi gerektiğini gösterir. Bu değer, CalendarContract.Instances tablosundaki satırların oluşturulmasını etkiler.
SYNC_EVENTS Takvimde senkronizasyon yapılıp yapılmaması ve etkinliklerin cihazda depolanıp depolanmaması gerektiğini belirten bir boole değeri. 0 değeri, bu takvimin senkronize edilmemesini veya etkinliklerinin cihazda depolanmamasını belirtir. 1 değeri, bu takvimin etkinliklerini senkronize et ve etkinliklerini cihazda sakla anlamına gelir.

Tüm işlemler için bir hesap türü ekleyin

Bir Calendars.ACCOUNT_NAME hakkında sorgu yapıyorsanız Calendars.ACCOUNT_TYPE'u da seçime dahil etmeniz gerekir. Bunun nedeni, belirli bir hesabın yalnızca ACCOUNT_NAME ve ACCOUNT_TYPE değerlerine göre benzersiz olarak kabul edilmesidir. ACCOUNT_TYPE, hesap AccountManager'a kaydedilirken kullanılan hesap kimlik doğrulayıcısına karşılık gelen dizedir. Ayrıca, cihaz hesabıyla ilişkili olmayan takvimler için ACCOUNT_TYPE_LOCAL adlı özel bir hesap türü de vardır. ACCOUNT_TYPE_LOCAL hesapları senkronize edilmez.

Takvim sorgulaması yapma

Aşağıda, belirli bir kullanıcıya ait takvimlerin nasıl alınacağını gösteren bir örnek verilmiştir. Kolaylık sağlaması açısından, bu örnekte sorgu işlemi kullanıcı arayüzü iş parçacığında ("ana iş parçacığı") gösterilmektedir. Uygulamada bu işlem, ana iş parçacığı yerine asenkron bir iş parçacığında yapılmalıdır. Daha fazla bilgi için Yükleyiciler bölümüne bakın. Verileri yalnızca okumakla kalmıyor, aynı zamanda değiştiriyorsanız AsyncQueryHandler bölümüne bakın.

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;

Örneğin bir sonraki bölümünde sorgunuzu oluşturursunuz. Seçim, sorgu için ölçütleri belirtir. Bu örnekte sorgu, ACCOUNT_NAME"hera@example.com", ACCOUNT_TYPE "com.example" ve OWNER_ACCOUNT "hera@example.com" içeren takvimleri aramaktadır. Bir kullanıcının yalnızca sahip olduğu takvimleri değil, görüntülediği tüm takvimleri görmek istiyorsanız OWNER_ACCOUNT öğesini çıkarın. Sorgu, veritabanı sorgusu tarafından döndürülen sonuç kümesini incelemek için kullanabileceğiniz bir Cursor nesnesi döndürür. İçerik sağlayıcılarda sorgu kullanma hakkında daha fazla bilgi için İçerik Sağlayıcılar bölümüne bakın.

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

Sonraki bölümde, sonuç kümesinde ilerlemek için imleç kullanılır. Her alanın değerini döndürmek için örneğin başında ayarlanan sabitleri kullanır.

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...

   ...
}

Takvimde değişiklik yapma

Bir takvimi güncellemek için takvimin _ID değerini Uri'ye eklenmiş bir kimlik olarak (withAppendedId()) veya ilk seçim öğesi olarak sağlayabilirsiniz. Seçim "_id=?" ile başlamalı ve ilk selectionArg, takvimin _ID olmalıdır. Kimliği URI'de kodlayarak da güncelleme yapabilirsiniz. Bu örnekte, (withAppendedId()) yaklaşımı kullanılarak bir takvimin görünen adı değiştirilmektedir:

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

Takvim ekleme

Takvimler öncelikle bir senkronizasyon bağdaştırıcısı tarafından yönetilecek şekilde tasarlanmıştır. Bu nedenle, yalnızca senkronizasyon bağdaştırıcısı olarak yeni takvimler eklemeniz gerekir. Uygulamalar, takvimlerde genellikle yalnızca görünen ad gibi yüzeysel değişiklikler yapabilir. Bir uygulamanın yerel takvim oluşturması gerekiyorsa bunu ACCOUNT_TYPE_LOCAL ACCOUNT_TYPE kullanarak takvim eklemeyi senkronizasyon bağdaştırıcısı olarak gerçekleştirerek yapabilir. ACCOUNT_TYPE_LOCAL cihaz hesabıyla ilişkili olmayan takvimler için özel bir hesap türüdür. Bu türdeki takvimler bir sunucuya senkronize edilmez. Senkronizasyon adaptörleriyle ilgili bilgi için Senkronizasyon Adaptörleri başlıklı makaleyi inceleyin.

Etkinlikler tablosu

CalendarContract.Events tablosu, her bir etkinliğin ayrıntılarını içerir. Bir uygulamanın etkinlik eklemek, güncellemek veya silmek için manifest dosyasında WRITE_CALENDAR iznini içermesi gerekir.

Aşağıdaki Etkinlik sütunları hem bir uygulama hem de senkronizasyon bağdaştırıcısı tarafından yazılabilir. Desteklenen alanların tam listesi için CalendarContract.Events referansına bakın.

Sabit Açıklama
CALENDAR_ID Etkinliğin ait olduğu takvimin _ID.
ORGANIZER Etkinliği düzenleyen kullanıcının (sahibi) e-posta adresi.
TITLE Etkinliğin başlığı.
EVENT_LOCATION Etkinliğin nerede gerçekleştiği.
DESCRIPTION Etkinliğin açıklaması.
DTSTART Etkinliğin başladığı zaman (UTC milisaniye cinsinden).
DTEND Etkinliğin, sıfır zamandan itibaren geçen UTC milisaniye cinsinden bitiş zamanı.
EVENT_TIMEZONE Etkinliğin saat dilimi.
EVENT_END_TIMEZONE Etkinliğin bitiş saatinin saat dilimi.
DURATION Etkinliğin RFC5545 biçimindeki süresi. Örneğin, "PT1H" değeri etkinliğin bir saat sürmesi gerektiğini, "P2W" değeri ise 2 haftalık bir süreyi belirtir.
ALL_DAY 1 değeri, bu etkinliğin yerel saat dilimi tarafından tanımlandığı şekilde tüm günü kapladığını gösterir. 0 değeri, bunun gün içinde herhangi bir zamanda başlayıp sona erebilen normal bir etkinlik olduğunu gösterir.
RRULE Etkinlik biçimi için yinelenme kuralı. Örneğin, "FREQ=WEEKLY;COUNT=10;WKST=SU". Daha fazla örneği burada bulabilirsiniz.
RDATE Etkinliğin yinelenme tarihleri. Genellikle, tekrarlanan oluşumların toplu bir grubunu tanımlamak için RDATE ile birlikte RRULE kullanırsınız. Daha fazla bilgi için RFC5545 spesifikasyonuna bakın.
AVAILABILITY Bu etkinlik yoğun zaman olarak kabul ediliyorsa veya planlanabilen boş zamansa.
GUESTS_CAN_MODIFY Davetlilerin etkinliği değiştirip değiştiremeyeceği.
GUESTS_CAN_INVITE_OTHERS Davetlilerin başka davetlileri davet edip edemeyeceği.
GUESTS_CAN_SEE_GUESTS Davetlilerin katılımcı listesini görüp göremeyeceği.

Etkinlik ekleme

Uygulamanız yeni bir etkinlik eklediğinde Etkinlik eklemek için intent kullanma bölümünde açıklandığı şekilde bir INSERT Niyeti kullanmanızı öneririz. Ancak gerekirse etkinlikleri doğrudan ekleyebilirsiniz. Bu bölümde bunun nasıl yapılacağı açıklanmaktadır.

Yeni etkinlik ekleme kuralları şunlardır:

Aşağıda, etkinlik eklemeyle ilgili bir örnek verilmiştir. Bu işlem, daha basit olması için UI iş parçacığında gerçekleştirilir. Uygulamada, işlemi arka plan iş parçacığına taşımak için eklemeler ve güncellemeler, asenkron bir iş parçacığında yapılmalıdır. Daha fazla bilgi için AsyncQueryHandler sayfasına bakın.

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
//
//

Not: Bu örneğin, etkinlik oluşturulduktan sonra etkinlik kimliğini nasıl yakaladığını inceleyin. Bu, etkinlik kimliği almanın en kolay yoludur. Diğer takvim işlemlerini (ör. bir etkinliğe katılımcı veya hatırlatıcı ekleme) gerçekleştirmek için genellikle etkinlik kimliğine ihtiyacınız vardır.

Güncelleme etkinlikleri

Uygulamanız kullanıcının bir etkinliği düzenlemesine izin vermek istediğinde Etkinliği düzenlemek için intent kullanma bölümünde açıklandığı gibi bir EDIT intent kullanmanızı öneririz. Ancak gerekirse etkinlikleri doğrudan düzenleyebilirsiniz. Bir etkinliği güncellemek için etkinliğin _ID değerini Uri'ye (withAppendedId()) eklenmiş bir kimlik olarak veya ilk seçim öğesi olarak sağlayabilirsiniz. Seçim "_id=?" ile başlamalı ve ilk selectionArg, etkinliğin _ID olmalıdır. Kimliği olmayan bir seçim kullanarak da güncelleme yapabilirsiniz. Aşağıda, bir etkinliğin güncellenmesine ilişkin bir örnek verilmiştir. Aşağıdaki yaklaşımı kullanarak etkinliğin başlığını değiştirir: withAppendedId()

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

Etkinlikleri sil

Bir etkinliği, URI'ye eklenmiş kimliği _ID olarak veya standart seçimi kullanarak silebilirsiniz. Ekli kimlik kullanıyorsanız seçim de yapamazsınız. Silme işleminin iki sürümü vardır: uygulama olarak ve senkronizasyon bağdaştırıcısı olarak. Bir uygulamanın silinmesi, deleted sütununu 1 olarak ayarlar. Bu işaret, senkronizasyon bağdaştırıcısına satırın silindiğini ve bu silme işleminin sunucuya dağıtılması gerektiğini bildirir. Senkronizasyon bağdaştırıcısı silme işlemi, etkinliği ilişkili tüm verileriyle birlikte veritabanından kaldırır. Aşağıda, _ID aracılığıyla bir etkinliği silen uygulama örneği verilmiştir:

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

Katılımcılar tablosu

CalendarContract.Attendees tablosunun her satırı, bir etkinliğin tek bir katılımcısını veya misafirini temsil eder. query() çağrısı, belirli bir EVENT_ID ile etkinliğin katılımcılarının listesini döndürür. Bu EVENT_ID, belirli bir etkinliğin _ID ile eşleşmelidir.

Aşağıdaki tabloda yazılabilir alanlar listelenmiştir. Yeni bir katılımcı eklerken ATTENDEE_NAME hariç tümünü eklemeniz gerekir.

Sabit Açıklama
EVENT_ID Etkinliğin kimliği.
ATTENDEE_NAME Katılımcının adı.
ATTENDEE_EMAIL Katılımcının e-posta adresi.
ATTENDEE_RELATIONSHIP

Katılımcıya ait etkinlikle ilişkisi. Şunlardan biri:

ATTENDEE_TYPE

Katılımcının türü. Şunlardan biri:

ATTENDEE_STATUS

Katılımcıya ait katılım durumu. Şunlardan biri:

Katılımcı ekle

Bir etkinliğe tek bir katılımcı eklemeyle ilgili bir örneği aşağıda bulabilirsiniz. EVENT_ID değerinin zorunlu olduğunu unutmayın:

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

Hatırlatıcılar tablosu

CalendarContract.Reminders tablosundaki her satır, bir etkinlik için tek bir hatırlatıcıyı temsil eder. query() çağrısı, belirli bir EVENT_ID ile etkinlikle ilgili hatırlatıcıların listesini döndürür.

Aşağıdaki tabloda, hatırlatıcılar için yazılabilir alanlar listelenmiştir. Yeni bir hatırlatıcı eklerken bunların tümü eklenmelidir. Senkronizasyon bağdaştırıcıların, destekledikleri hatırlatıcı türlerini CalendarContract.Calendars tablosunda belirttiğini unutmayın. Ayrıntılar için ALLOWED_REMINDERS sayfasını inceleyin.

Sabit Açıklama
EVENT_ID Etkinliğin kimliği.
MINUTES Hatırlatıcının etkinleşmesi gereken etkinlikten dakika önce.
METHOD

Sunucuda ayarlandığı şekilde alarm yöntemi. Şunlardan biri:

Hatırlatıcı ekle

Bu örnekte, bir etkinliğe hatırlatıcı eklenmektedir. Hatırlatıcı, etkinlikten 15 dakika önce etkinleştirilir.

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

Örnekler tablosu

CalendarContract.Instances tablosu, bir etkinliğin gerçekleşmelerinin başlangıç ve bitiş zamanını içerir. Bu tablodaki her satır, tek bir etkinlik tekrarını temsil eder. Örnekler tablosu yazılabilir değildir ve yalnızca etkinlik oluşumlarını sorgulamanızı sağlar.

Aşağıdaki tabloda, bir örnek için sorgulayabileceğiniz bazı alanlar listelenmiştir. Saat diliminin KEY_TIMEZONE_TYPE ve KEY_TIMEZONE_INSTANCES ile tanımlandığını unutmayın.

Sabit Açıklama
BEGIN UTC milisaniye cinsinden örneğin başlangıç zamanı.
END UTC milisaniye cinsinden örneğin bitiş zamanı.
END_DAY Takvim'in saat dilimine göre örneğin Jülyen bitiş günü.
END_MINUTE Takvim'in saat diliminde gece yarısından itibaren ölçülen örneğin bitiş dakikası.
EVENT_ID Bu örnek için etkinliğin _ID değeri.
START_DAY Takvim'in saat dilimine göre örneğin Jülyen başlangıç günü.
START_MINUTE Takvim'in saat dilimine göre gece yarısından itibaren ölçülen örneğin başlangıç dakikası.

Örnekler tablosunu sorgulama

Örnekler tablosunu sorgulamak için URI'de sorgu için bir zaman aralığı belirtmeniz gerekir. Bu örnekte CalendarContract.Instances, CalendarContract.EventsColumns arayüzünü uygulayarak TITLE alanına erişir. Diğer bir deyişle, TITLE ham CalendarContract.Instances tablosu sorgulanarak değil, bir veritabanı görünümü aracılığıyla döndürülür.

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

Takvim intent'leri

Uygulamanızın takvim verilerini okumak ve yazmak için izinlere ihtiyacı yoktur. Bunun yerine, okuma ve yazma işlemlerini Android'in Takvim uygulamasına aktarmak için Android'in Takvim uygulaması tarafından desteklenen intent'leri kullanabilir. Aşağıdaki tabloda Takvim Sağlayıcısı tarafından desteklenen amaçlar listelenmektedir:

İşlem URI Açıklama Ekstralar

VIEW

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

URI'ye CalendarContract.CONTENT_URI ile de referans verebilirsiniz. Bu intent'in kullanımıyla ilgili bir örnek için Takvim verilerini görüntülemek için intent'leri kullanma başlıklı makaleyi inceleyin.
Takvimi <ms_since_epoch> tarafından belirtilen saate açın. Yok.

VIEW

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

URI'ye Events.CONTENT_URI ile de referans verebilirsiniz. Bu amacın kullanımına dair bir örnek için Takvim verilerini görüntülemek için intent'leri kullanma başlıklı makaleye bakın.
<event_id> ile belirtilen etkinliği görüntüleyin. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

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

URI'ye Events.CONTENT_URI ile de referans verebilirsiniz. Bu amacın kullanımına ilişkin bir örnek için Bir etkinliği düzenlemek için intent kullanma bölümüne bakın.
<event_id> ile belirtilen etkinliği düzenleyin. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

INSERT

content://com.android.calendar/events

URI'ye Events.CONTENT_URI ile de referans verebilirsiniz. Bu niyetin kullanımına dair bir örnek için Etkinlik eklemek için niyet kullanma başlıklı makaleyi inceleyin.
Bir etkinlik oluşturun. Aşağıdaki tabloda listelenen ekstralardan herhangi biri.

Aşağıdaki tabloda, Takvim Sağlayıcı tarafından desteklenen intent ekstraları listelenmiştir:

Intent Ekstra Açıklama
Events.TITLE Etkinliğin adı.
CalendarContract.EXTRA_EVENT_BEGIN_TIME Dönemden bu yana geçen, milisaniye cinsinden etkinlik başlangıç zamanı.
CalendarContract.EXTRA_EVENT_END_TIME Dönemden bu yana geçen, milisaniye cinsinden etkinlik bitiş zamanı.
CalendarContract.EXTRA_EVENT_ALL_DAY Bir etkinliğin tüm gün olduğunu belirten boole değeri. Değer true veya false olabilir.
Events.EVENT_LOCATION Etkinliğin konumu.
Events.DESCRIPTION Etkinlik açıklaması.
Intent.EXTRA_EMAIL Davet edilecek kullanıcıların e-posta adreslerini virgülle ayrılmış liste olarak girin.
Events.RRULE Etkinliğin yinelenme kuralı.
Events.ACCESS_LEVEL Etkinliğin gizli mi yoksa herkese açık mı olduğu.
Events.AVAILABILITY Bu etkinlik meşgulse veya planlanabilecek boş zaman olarak mı sayılıyor?

Aşağıdaki bölümlerde bu amaçların nasıl kullanılacağı açıklanmaktadır.

Etkinlik eklemek için intent kullanma

INSERT Intent'i kullanmak, uygulamanızın etkinlik ekleme görevini Takvim'e aktarmasına olanak tanır. Bu yaklaşımda, uygulamanızın manifest dosyasında WRITE_CALENDAR izninin bulunması bile gerekmez.

Kullanıcılar bu yaklaşımı kullanan bir uygulamayı çalıştırdığında uygulama, etkinliği eklemeyi tamamlamaları için onları Takvim'e gönderir. INSERT intent'i, bir formu Takvim'deki etkinliğin ayrıntılarıyla önceden doldurmak için ek alanlar kullanır. Kullanıcılar etkinliği iptal edebilir, formu gerektiği şekilde düzenleyebilir veya takvimlerine kaydedebilir.

19 Ocak 2012 tarihinde 07:30-08:30 saatleri arasında etkinlik planlayan bir kod snippet'ini aşağıda bulabilirsiniz. Bu kod snippet'i hakkında aşağıdaki noktalara dikkat edin:

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

Bir etkinliği düzenlemek için intent kullanma

Etkinlikleri güncelleme bölümünde açıklandığı şekilde bir etkinliği doğrudan güncelleyebilirsiniz. Ancak EDIT amacı, etkinlik düzenlemeyi Takvim uygulamasına devretme izni olmayan bir uygulamanın bunu yapmasına olanak tanır. Kullanıcılar Takvim'de etkinliklerini düzenlemeyi tamamladığında orijinal uygulamaya geri yönlendirilir.

Belirli bir etkinlik için yeni bir başlık ayarlayan ve kullanıcıların etkinliği Takvim'de düzenlemesine olanak tanıyan bir intent örneğini aşağıda bulabilirsiniz.

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

Takvim verilerini görüntülemek için intent'leri kullanma

Takvim Sağlayıcı, VIEW intent'ini kullanmanın iki farklı yolunu sunar:

  • Takvim'i belirli bir tarihte açmak için.
  • Bir etkinliği görüntülemek için:

Takvim'i belirli bir tarihe göre nasıl açacağınızı gösteren bir örneği aşağıda bulabilirsiniz:

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

Bir etkinliğin görüntüleme için nasıl açılacağını gösteren örnek:

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

Senkronizasyon bağdaştırıcıları

Bir uygulamanın ve senkronizasyon bağdaştırıcının Takvim Sağlayıcı'ya erişme şekli arasında yalnızca küçük farklılıklar vardır:

  • Senkronizasyon adaptörünün, CALLER_IS_SYNCADAPTER değerini true olarak ayarlayarak senkronizasyon adaptörü olduğunu belirtmesi gerekir.
  • Senkronizasyon bağdaştırıcının, URI'de sorgu parametresi olarak bir ACCOUNT_NAME ve bir ACCOUNT_TYPE sağlaması gerekir.
  • Senkronizasyon bağdaştırıcısı, bir uygulama veya widget'a göre daha fazla sütuna yazma erişimine sahiptir. Örneğin, bir uygulama yalnızca takvimin adı, görünen adı, görünürlük ayarı ve takvimin senkronize edilip edilmediği gibi birkaç özelliğini değiştirebilir. Buna karşılık, senkronizasyon bağdaştırıcısı yalnızca bu sütunlara değil, takvim rengi, saat dilimi, erişim düzeyi, konum vb. gibi birçok sütuna da erişebilir. Ancak senkronizasyon bağdaştırıcısı, belirttiği ACCOUNT_NAME ve ACCOUNT_TYPE ile sınırlıdır.

Senkronizasyon adaptörüyle kullanılmak üzere bir URI döndürmek için kullanabileceğiniz yardımcı yöntem aşağıda verilmiştir:

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