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

Takvim Sağlayıcısı, kullanıcının takvim etkinlikleri için bir veri havuzudur. Calendar Provider API, takvimler, etkinlikler, katılımcılar, hatırlatıcılar ve benzeri öğeler üzerinde sorgulama gerçekleştirmenize, işlemler eklemenize, güncellemenize ve silmenize olanak tanır.

Takvim Sağlayıcı API'sı, uygulamalar ve senkronizasyon bağdaştırıcıları tarafından kullanılabilir. Kurallar, çağrı yapan programın türüne bağlı olarak değişiklik gösterir. Bu belgede öncelikli olarak Calendar Provider API'nin uygulama olarak kullanılması ele alınmaktadır. Senkronizasyon bağdaştırıcılarının farklılıkları hakkında bilgi edinmek için Senkronizasyon Bağdaştırıcıları bölümüne bakın.

Normalde takvim verilerini okumak veya yazmak için bir uygulamanın manifest dosyası, Kullanıcı İzinleri bölümünde açıklanan uygun izinleri içermelidir. Sık kullanılan işlemlerin gerçekleştirilmesini kolaylaştırmak için Takvim Sağlayıcı, Takvim Amaçları'nda açıklandığı gibi bir dizi amaç sunar. Bu amaçlar; etkinlik ekleme, görüntüleme ve düzenleme işlemleri 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. Dolayısıyla uygulamanızın izin istemesi veya etkinlikleri görüntülemek veya oluşturmak için kullanıcı arayüzü sağlaması gerekmez.

Temel Bilgiler

İçerik sağlayıcılar verileri depolar ve uygulamaların erişimine sunar. Android platformu (Takvim Sağlayıcı dahil) tarafından sunulan içerik sağlayıcılar, verileri genellikle ilişkisel veritabanı modeline dayalı tablolar halinde sunar. Bu modelde her satır bir kayıt, her sütun ise belirli bir tür ve anlama sahip veridir. Uygulamalar ve senkronizasyon bağdaştırıcıları, Calendar Provider API aracılığıyla bir kullanıcının takvim verilerini barındıran veritabanı tablolarına okuma/yazma erişimi elde edebilir.

Her içerik sağlayıcı, veri kümesini benzersiz bir şekilde tanımlayan herkese açık bir URI (Uri nesnesi olarak sarmalanmış) sunar. Birden çok 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'lar "content://" dizesiyle başlar. Bu şekilde, veriler bir içerik sağlayıcı tarafından kontrol ediliyor olarak tanımlanır. Takvim Sağlayıcı, sınıflarının her biri (tablolar) için URI'lar için sabit değerler tanımlar. Bu URI'ler <class>.CONTENT_URI biçimindedir. Örneğin, Events.CONTENT_URI.

Şekil 1'de, Takvim Sağlayıcısı veri modelinin grafik gösterimi gösterilmektedir. Bu tabloda, ana tablolar ve bunları birbirine bağlayan alanlar gösterilir.

Takvim Sağlayıcı Veri Modeli

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

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

CalendarContract, takvimin ve etkinlikle ilgili bilgilerin veri modelini tanımlar. Bu veriler, aşağıda listelenen bir dizi tabloda saklanır.

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

CalendarContract.Calendars

Bu tablo, takvime özgü bilgileri içerir. Bu tablodaki her satırda, tek bir takvimle ilgili ad, renk, senkronizasyon bilgileri gibi ayrıntılar yer alır.
CalendarContract.Events Bu tabloda etkinliğe özgü bilgiler yer alır. Bu tablodaki her satırda tek bir etkinlikle ilgili bilgiler bulunur (ör. etkinlik başlığı, konum, başlangıç zamanı, bitiş zamanı vb.). Etkinlik bir kez gerçekleşebilir veya birden çok kez yinelenebilir. Katılımcılar, hatırlatıcılar ve genişletilmiş özellikler ayrı tablolarda depolanır. Her birinin, Etkinlikler tablosundaki _ID öğesine başvuruda bulunan bir EVENT_ID öğesi vardır.
CalendarContract.Instances Bu tabloda, bir etkinliğin geçtiği her yerin başlangıç ve bitiş zamanı gösterilir. Bu tablodaki her satır, tek bir etkinlik oluşumunu temsil eder. Tek seferlik etkinlikler için örnekler ile etkinlikler 1:1 eşlenir. Düzenli etkinlikler için otomatik olarak birden fazla satır oluşturulur. Bu satırlar, söz konusu etkinliğin birden fazla kez gerçekleşmesine karşılık gelir.
CalendarContract.Attendees Bu tabloda etkinlik katılımcısı (davetli) bilgileri bulunur. Her satır, bir etkinliğin tek bir konuğunu temsil eder. Davetli türünü ve davetlinin etkinlik için katılım yanıtını belirtir.
CalendarContract.Reminders Bu tablo, uyarı/bildirim verilerini içerir. Her satır, bir etkinlikle ilgili tek bir uyarıyı temsil eder. Bir etkinlikte birden fazla hatırlatıcı olabilir. Etkinlik başına maksimum hatırlatıcı sayısı, belirtilen takvimin sahibi olan senkronizasyon bağdaştırıcısı tarafından ayarlanan MAX_REMINDERS politikasında belirtilir. Hatırlatıcılar, etkinlikten dakikalar önce belirtilir ve kullanıcının nasıl uyarılacağını belirleyen bir yöntem bulunur.

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

  • Takvim etkinliklerini ekleme, güncelleme ve görüntüleme. Etkinlikleri doğrudan Takvim Sağlayıcısı'ndan eklemek, değiştirmek ve okumak için uygun izinlere ihtiyacınız vardır. Ancak tam kapsamlı bir takvim uygulaması veya senkronizasyon bağdaştırıcısı oluşturmuyorsanız bu izinleri istemek gerekli değildir. Bunun yerine, okuma ve yazma işlemlerini söz konusu uygulamaya aktarmak için Android'in Takvim uygulaması tarafından desteklenen amaçları kullanabilirsiniz. Amaçları kullandığınızda uygulamanız, istenen işlemi önceden doldurulmuş bir formda gerçekleştirmeleri için kullanıcıları Takvim uygulamasına gönderir. Bu işlemler tamamlandıktan sonra uygulamanıza geri döndürülürler. Uygulamanızı, Takvim aracılığıyla genel işlemleri gerçekleştirecek şekilde tasarlayarak kullanıcılara tutarlı ve sağlam bir kullanıcı arayüzü sunarsınız. Bu, önerilen yaklaşımdır. Daha fazla bilgi için Takvim Amaçları konusuna bakın.
  • Senkronizasyon bağdaştırıcıları. Senkronizasyon bağdaştırıcıları, bir 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 bunları değiştirmemelidir. Aslında, 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ı bölümüne bakın.

Kullanıcı izinleri

Takvim verilerini okumak için uygulamanın manifest dosyasına READ_CALENDAR iznini eklemesi gerekir. Takvim verilerini silmek, eklemek veya güncellemek için 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, takvimlerin ayrıntılarını içerir. Aşağıdaki Takvimler sütunlarına hem bir uygulama hem de bir 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österilmek üzere seçilip seçilmediğini belirten boole. 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 belirtir. Bu değer, CalendarContract.Instances tablosundaki satırların oluşturulmasını etkiler.
SYNC_EVENTS Takvimin senkronize edilmesi gerekip gerekmediğini ve etkinliklerinin cihazda depolanıp depolanmayacağını belirten bir boole değeridir. 0 değeri, "bu takvimi senkronize etme" veya "etkinlikleri cihazda depolama" ifadesini belirtir. 1 değeri, bu takvimin senkronizasyon etkinliklerini ve takvim etkinliklerini cihazda depoladığını belirtir.

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

Calendars.ACCOUNT_NAME üzerinde sorgu oluşturursanız seçime Calendars.ACCOUNT_TYPE ifadesini de eklemeniz gerekir. Bunun nedeni, belirli bir hesabın hem ACCOUNT_NAME hem de ACCOUNT_TYPE göz önünde bulundurularak benzersiz kabul edilmesidir. ACCOUNT_TYPE, hesap AccountManager ile kaydettirildiğinde kullanılan hesap kimlik doğrulayıcıya karşılık gelen dizedir. Ayrıca, bir cihaz hesabıyla ilişkili olmayan takvimler için ACCOUNT_TYPE_LOCAL adı verilen özel bir hesap türü de vardır. ACCOUNT_TYPE_LOCAL hesap senkronize edilmez.

Takvimi sorgulama

Belirli bir kullanıcının sahip olduğu takvimlerin nasıl alınacağını gösteren bir örneği aşağıda bulabilirsiniz. Kolaylık olması açısından bu örnekte sorgu işlemi kullanıcı arayüzü iş parçacığında ("ana iş parçacığı") gösterilmektedir. Pratikte bu, ana iş parçacığı yerine eşzamansız bir iş parçacığında yapılmalıdır. Daha fazla bilgi için Yükleyiciler bölümüne bakın. Yalnızca verileri okumuyor, aynı zamanda değiştiriyorsanız AsyncQueryHandler 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 sonraki bölümünde sorgunuzu oluşturursunuz. Bu seçim, sorgu için kriterleri belirtir. Bu örnekteki sorgu, ACCOUNT_NAME"hera@example.com", ACCOUNT_TYPE"com.example" ve OWNER_ACCOUNT"hera@example.com" öğelerini içeren takvimleri arar. Yalnızca kullanıcıya ait takvimleri değil, bir kullanıcının görüntülediği tüm takvimleri görmek istiyorsanız OWNER_ACCOUNT özelliğini çıkarın. Sorgu, veritabanı sorgusu tarafından döndürülen sonuç kümesini aktarmak için kullanabileceğiniz bir Cursor nesnesi döndürür. İçerik sağlayıcılarda sorguların kullanımıyla ilgili 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);

Sıradaki bölümde, sonuç kümesinde ilerlemek için imleç kullanılır. Her alanın değerlerini döndürmek için, örneğin başında ayarlanan sabit değerleri 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...

   ...
}

Takvimi değiştirme

Bir takvimi güncellemek için takvimin _ID özelliğini URI'ya (withAppendedId()) eklenen bir kimlik olarak veya ilk seçim öğesi olarak sağlayabilirsiniz. Seçim "_id=?" ile başlamalı ve ilk selectionArg takvim için _ID olmalıdır. Güncellemeleri, URI'daki kimliği kodlayarak da yapabilirsiniz. Bu örnekte, bir takvimin görünen adı (withAppendedId()) yaklaşımı kullanılarak 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 temel olarak bir senkronizasyon bağdaştırıcısı tarafından yönetilecek şekilde tasarlandığından senkronizasyon bağdaştırıcısı olarak yalnızca yeni takvimleri eklemeniz gerekir. Çoğunlukla, uygulamalar takvimlerde yalnızca görünen adı değiştirmek gibi yüzeysel değişiklikler yapabilir. Bir uygulamanın yerel takvim oluşturması gerekiyorsa bunu, ACCOUNT_TYPE_LOCAL içinde ACCOUNT_TYPE kullanıp senkronizasyon bağdaştırıcısı olarak takvim ekleme işlemini yaparak gerçekleştirebilir. ACCOUNT_TYPE_LOCAL, herhangi bir cihaz hesabıyla ilişkilendirilmemiş takvimler için kullanılan özel bir hesap türüdür. Bu türdeki takvimler sunucuyla senkronize edilmez. Senkronizasyon bağdaştırıcıları hakkında ayrıntılı bilgi için Senkronizasyon Bağdaştırıcıları bölümüne bakın.

Etkinlikler tablosu

CalendarContract.Events tablosu, bağımsız etkinliklerle ilgili ayrıntıları içerir. Etkinlik eklemek, güncellemek veya silmek için bir uygulamanın manifest dosyasına WRITE_CALENDAR iznini eklemesi gerekir.

Aşağıdaki Etkinlikler sütunlarına hem bir uygulama hem de bir senkronizasyon adaptörü 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 takvimdeki _ID.
ORGANIZER Etkinliği düzenleyenin (sahibi) e-posta adresi.
TITLE Etkinliğin başlığı.
EVENT_LOCATION Etkinliğin gerçekleştiği yer.
DESCRIPTION Etkinliğin açıklaması.
DTSTART Dönemden itibaren etkinliğin başladığı zaman (UTC milisaniye).
DTEND Dönemden bu yana etkinliğin, UTC milisaniye cinsinden sona erdiği zaman.
EVENT_TIMEZONE Etkinliğe ilişkin saat dilimi.
EVENT_END_TIMEZONE Etkinliğin bitiş zamanının 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, yerel saat diliminde tanımlandığı şekilde bu etkinliğin tüm günü kapladığını gösterir. 0 değeri, gün içinde herhangi bir zamanda başlayıp bitebilecek normal bir etkinlik olduğunu belirtir.
RRULE Etkinlik biçimi için yinelenme kuralı. Örneğin, "FREQ=WEEKLY;COUNT=10;WKST=SU". Burada daha fazla örnek bulabilirsiniz.
RDATE Etkinliğin yinelenme tarihleri. Yinelenen tekrarlardan oluşan birleştirilmiş bir kümeyi tanımlamak için genellikle RRULE ile birlikte RDATE kullanırsınız. Daha fazla bilgi için RFC5545 spesifikasyonuna bakın.
AVAILABILITY Bu etkinlik, meşgul olarak sayılıyor veya planlanabilecek boş zaman olarak değerlendirilebilir.
GUESTS_CAN_MODIFY Davetlilerin etkinliği değiştirip değiştiremeyeceğini belirler.
GUESTS_CAN_INVITE_OTHERS Konukların başka konukları davet edip edemeyeceğini.
GUESTS_CAN_SEE_GUESTS Davetlilerin katılımcı listesini görüp göremeyeceğini belirtir.

Etkinlik ekleme

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

Yeni etkinlik eklemeyle ilgili kurallar şunlardır:

Etkinlik eklemeyle ilgili bir örnek aşağıda verilmiştir. Bu işlem, kolaylık olması amacıyla UI iş parçacığında gerçekleştirilir. Pratikte, ekleme ve güncelleme işlemlerinin eşzamansız bir iş parçacığında yapılması gerekir. Böylece, işlem bir arka plan iş parçacığına taşınır. Daha fazla bilgi için AsyncQueryHandler sayfasını inceleyin.

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ığına bakın. Bu, etkinlik kimliği almanın en kolay yoludur. Diğer takvim işlemlerini (örneğin, bir etkinliğe katılımcılar veya hatırlatıcılar eklemek) gerçekleştirmek için genellikle etkinlik kimliğine ihtiyacınız olur.

Güncelleme etkinlikleri

Uygulamanız kullanıcının bir etkinliği düzenlemesine izin vermek istediğinde, Etkinlik düzenlemek için amaç kullanma bölümünde açıklandığı gibi bir EDIT amacı kullanmanızı öneririz. Ancak gerekirse etkinlikleri doğrudan düzenleyebilirsiniz. Bir Etkinliğin güncellemesini gerçekleştirmek için etkinliğin _ID özelliğini URI'ya (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. Kimliksiz bir seçim kullanarak da güncelleme yapabilirsiniz. Aşağıda, etkinlik güncelleme bir örneği verilmiştir. withAppendedId() yaklaşımını kullanarak etkinliğin başlığını değiştirir:

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'da eklenen kimlik olarak _ID veya standart seçimi kullanarak silebilirsiniz. Eklenen bir kimlik kullanırsanı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. Uygulama silme işlemi, silinen sütunu 1 olarak ayarlar. Senkronizasyon bağdaştırıcısına satırın silindiğini ve bu silme işleminin sunucuda uygulanması gerektiğini bildiren bu işaret. Senkronizasyon bağdaştırıcısı silme işlemi, etkinliği tüm ilişkili verileriyle birlikte veritabanından kaldırır. Burada, _ID aracı üzerinden etkinlik silen bir uygulama örneği gösterilmektedir:

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 katılımcısını veya davetlisini temsil eder. query() çağrısı yapıldığında belirtilen EVENT_ID ile etkinlik için katılımcıların listesi döndürülür. Bu EVENT_ID, belirli bir etkinliğin _ID ile eşleşmelidir.

Aşağıdaki tabloda yazılabilir alanlar listelenmiştir. Yeni katılımcı eklerken ATTENDEE_NAME hariç tüm katılımcıları dahil etmeniz 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ının etkinlikle olan ilişkisi. Şunlardan biri:

ATTENDEE_TYPE

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

ATTENDEE_STATUS

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

Katılımcı ekle

Bir etkinliğe tek bir katılımcının eklendiği bir örneği aşağıda görebilirsiniz. EVENT_ID alanının 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 tablosunun her satırı, bir etkinlik için tek bir hatırlatıcıyı temsil eder. query() çağrısı, belirtilen EVENT_ID öğesine sahip etkinlik için bir hatırlatıcı listesi 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ünün dahil edilmesi gerekir. Senkronizasyon bağdaştırıcılarının, CalendarContract.Calendars tablosunda destekledikleri hatırlatıcı türlerini 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, etkinlikten kaç dakika önce etkinleşeceği.
METHOD

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

Hatırlatıcı ekle

Bu örnek, bir etkinliğe hatırlatıcı ekler. Hatırlatıcı, etkinlikten 15 dakika önce etkinleşir.

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şme zamanını ve bitiş zamanını içerir. Bu tablodaki her satır, tek bir etkinlik oluşumunu temsil eder. Örnekler tablosu yazılabilir değildir ve yalnızca etkinlik oluşumlarını sorgulamak için bir yöntem sağlar.

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

Sabit Açıklama
BEGIN Örneğin başlangıç zamanı (UTC milisaniye cinsinden).
END Örneğin bitiş zamanı (UTC milisaniye cinsinden).
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 ölçülen örneğin bitiş dakikası.
EVENT_ID Bu örnek için etkinliğin _ID.
START_DAY Takvimin saat dilimine göre örneğin Jülyen başlangıç günü.
START_MINUTE Takvim'in saat dilimine göre gece yarısından ölçülen örneğin başlangıç dakikası.

Örnekler tablosunu sorgulama

Örnekler tablosunu sorgulamak amacıyla URI'de sorgu için bir aralık zamanı belirtmeniz gerekir. Bu örnekte CalendarContract.Instances, CalendarContract.EventsColumns arayüzünü uygulayarak TITLE alanına erişim elde eder. Diğer bir deyişle, TITLE ham CalendarContract.Instances tablosunun sorgulanmasıyla değil, 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 amaçları

Uygulamanızın takvim verilerini okumak ve yazmak için izinlere ihtiyacı yoktur. Bunun yerine, okuma ve yazma işlemlerini söz konusu uygulamaya aktarmak için Android'in Takvim uygulaması tarafından desteklenen niyetleri 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'ya CalendarContract.CONTENT_URI ile de başvurabilirsiniz. Bu amacın kullanılmasına ilişkin bir örnek için Takvim verilerini görüntülemek için amaçları kullanma başlıklı makaleye bakın.
Takvimi <ms_since_epoch> tarafından belirtilen saate açın. Yok.

VIEW

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

URI'ya Events.CONTENT_URI ile de başvurabilirsiniz. Bu amacın kullanılmasına ilişkin bir örnek için Takvim verilerini görüntülemek için amaçları kullanma başlıklı makaleye bakın.
<event_id> tarafından 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'ya Events.CONTENT_URI ile de başvurabilirsiniz. Bu amacın kullanımına ilişkin bir örnek için Bir etkinliği düzenlemek için amaç kullanma bölümüne bakın.
<event_id> tarafından belirtilen etkinliği düzenleyin. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

INSERT

content://com.android.calendar/events

URI'ya Events.CONTENT_URI ile de başvurabilirsiniz. Bu amacın kullanımına ilişkin bir örnek için Etkinlik eklemek için amaç kullanma bölümüne bakın.
Bir etkinlik oluşturun. Aşağıdaki tabloda listelenen ekstralardan herhangi biri.

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

İntent Ekstra Açıklama
Events.TITLE Etkinliğin adı.
CalendarContract.EXTRA_EVENT_BEGIN_TIME Dönemden itibaren milisaniye cinsinden etkinlik başlangıç zamanı.
CalendarContract.EXTRA_EVENT_END_TIME Dönemden itibaren milisaniye cinsinden etkinlik bitiş zamanı.
CalendarContract.EXTRA_EVENT_ALL_DAY Bir etkinliğin tüm gün olduğunu belirten boole değeridir. Değer true veya false olabilir.
Events.EVENT_LOCATION Etkinliğin konumu.
Events.DESCRIPTION Etkinlik açıklaması.
Intent.EXTRA_EMAIL Davet edilecek kişilerin virgülle ayrılmış liste olarak e-posta adresleri.
Events.RRULE Etkinliğin yineleme kuralı.
Events.ACCESS_LEVEL Etkinliğin özel mi yoksa herkese açık mı olduğu.
Events.AVAILABILITY Bu etkinlik meşgul zaman olarak sayılır veya etkinlik için planlanabilecek boş zaman olarak değerlendirilir.

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ını sağlar. Bu yaklaşımla uygulamanızın manifest dosyasına WRITE_CALENDAR izninin eklenmesi bile gerekmez.

Kullanıcılar bu yaklaşımı kullanan bir uygulama çalıştırdığında, uygulama etkinlik ekleme işlemini tamamlamak için bu uygulamaları Takvim'e gönderir. INSERT Amacı, bir formu Takvim'deki etkinliğin ayrıntılarıyla önceden doldurmak için ekstra alanlar kullanır. Ardından kullanıcılar etkinliği iptal edebilir, formu gereken şekilde düzenleyebilir veya etkinliği takvimlerine kaydedebilir.

19 Ocak 2012 tarihinde 07:30 ile 08:30 arasında süren bir etkinlik planlayan kod snippet'ini aşağıda görebilirsiniz. Bu kod snippet'iyle ilgili olarak aşağıdakileri göz önünde bulundurun:

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

Etkinliği düzenlemek için intent kullanma

Bir etkinliği doğrudan, Etkinlikleri güncelleme bölümünde açıklandığı şekilde güncelleyebilirsiniz. Ancak EDIT Intent'in kullanılması, etkinlik düzenlemesini Takvim uygulamasına aktarma izni olmayan bir uygulamaya izin verir. Kullanıcılar Takvim'de etkinliklerini düzenlemeyi tamamladığında orijinal uygulamaya geri dönerler.

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 niyet örneğini burada 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 amaçları kullanma

Takvim Sağlayıcısı, VIEW amacını kullanmak için iki farklı yol sunar:

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

Takvim'in belirli bir tarihe nasıl açılacağını 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);

Aşağıda, görüntülemek üzere bir etkinliğin nasıl açılacağını gösteren bir örnek verilmiştir:

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 adaptörleri

Bir uygulamanın ve senkronizasyon bağdaştırıcısının Takvim Sağlayıcısı'na erişme şeklinde yalnızca küçük farklar vardır:

  • Bir senkronizasyon bağdaştırıcısının, CALLER_IS_SYNCADAPTER politikasını true değerine ayarlayarak bunun bir senkronizasyon bağdaştırıcısı olduğunu belirtmesi gerekir.
  • Senkronizasyon bağdaştırıcılarının URI'de sorgu parametreleri olarak ACCOUNT_NAME ve ACCOUNT_TYPE sağlaması gerekir.
  • Senkronizasyon bağdaştırıcılarının, uygulama veya widget'a göre daha fazla sütuna yazma erişimi vardır. Örneğin, bir uygulama bir takvimin yalnızca adı, görünen adı, görünürlük ayarı ve takvimin senkronize olup olmadığı 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 gibi birçok sütuna da erişebilir. Ancak senkronizasyon bağdaştırıcıları belirtilen ACCOUNT_NAME ve ACCOUNT_TYPE ile sınırlıdır.

Senkronizasyon bağdaştırıcısıyla birlikte kullanılacak bir URI döndürmek için kullanabileceğiniz yardımcı bir 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();
 }