lightbulb_outline Please take our October 2018 developer survey. Start survey

Penyedia Kalender

Penyedia Kalender adalah repositori untuk kejadian kalender seorang pengguna. Calendar Provider API memungkinkan Anda melakukan kueri, menyisipkan, memperbarui, dan menghapus pada kalender, kejadian, peserta, pengingat, dan seterusnya.

Calender Provider API bisa digunakan oleh aplikasi dan adaptor sinkronisasi. Aturannya bervariasi menurut tipe program yang membuat panggilan. Dokumen ini terutama berfokus pada penggunaan Calender Provider API sebagai sebuah aplikasi. Untuk pembahasan ragam adaptor sinkronisasi, lihat Adaptor Sinkronisasi.

Biasanya, untuk membaca atau menulis data kalender, manifes aplikasi harus berisi izin yang sesuai, yang dijelaskan dalam Izin Pengguna. Untuk mempermudah dilakukannya operasi umum, Penyedia Kalender menyediakan satu set maksud, seperti dijelaskan dalam Maksud Kalender. Semua maksud ini membawa pengguna ke aplikasi Kalender untuk menyisipkan, menampilkan, dan mengedit kejadian. Pengguna berinteraksi dengan aplikasi Kalender kemudian kembali ke aplikasi semula. Jadi, aplikasi Anda tidak perlu meminta izin, juga tidak perlu menyediakan antarmuka pengguna untuk menampilkan atau membuat kejadian.

Dasar-Dasar

Penyedia materi menyimpan data dan menjadikannya bisa diakses oleh aplikasi. Penyedia materi yang ditawarkan oleh platform Android (termasuk Penyedia Kalender) biasanya mengekspos data sebagai satu set tabel berdasarkan model database relasional, dengan tiap baris berupa catatan dan tiap kolom berupa data yang memiliki tipe dan arti tertentu. Melalui Calendar Provider API, aplikasi dan adaptor sinkronisasi bisa mendapatkan akses baca/tulis ke tabel-tabel database yang menyimpan data kalender seorang pengguna.

Setiap penyedia materi membuka sebuah URI publik (yang dibungkus sebagai objek Uri ) yang mengidentifikasikan set datanya secara unik. Penyedia materi yang mengontrol beberapa set data (beberapa tabel) mengekspos URI terpisah untuk tiap set. Semua URI untuk penyedia diawali dengan string "content://". String ini mengidentifikasi data sebagai dikontrol oleh penyedia materi. Penyedia Kalender mendefinisikan konstanta untuk URI masing-masing kelas (tabel). URI ini memiliki format <class>.CONTENT_URI. Misalnya, Events.CONTENT_URI.

Gambar 1 menampilkan representasi grafis model data Penyedia Kalender. Gambar ini menampilkan tabel dan bidang utama yang saling bertautan.

Model Data Penyedia Kalender

Gambar 1. Model data Penyedia Kalender

Seorang pengguna bisa memiliki beberapa kalender, dan kalender yang berbeda bisa dikaitkan dengan tipe akun yang berbeda (Google Kalender, Exchange, dan seterusnya).

CalendarContract mendefinisikan model data dari informasi yang terkait dengan kalender dan kejadian. Data ini disimpan di sejumlah tabel, yang dicantumkan di bawah ini.

Tabel (Kelas) Keterangan

CalendarContract.Calendars

Tabel ini menyimpan informasi khusus kalender. Tiap baris dalam tabel ini berisi data untuk satu kalender, seperti nama, warna, informasi sinkronisasi, dan seterusnya.
CalendarContract.Events Tabel ini menyimpan informasi khusus kejadian. Tiap baris dalam tabel ini berisi informasi untuk satu kejadian—misalnya, judul kejadian, lokasi, waktu mulai, waktu berakhir, dan seterusnya. Kejadian bisa terjadi satu kali atau bisa berulang beberapa kali. Peserta, pengingat, dan properti perluasan disimpan dalam tabel terpisah. Mereka masing-masing memiliki EVENT_ID yang mereferensikan _ID dalam tabel Kejadian.
CalendarContract.Instances Tabel ini menyimpan waktu mulai dan waktu berakhir setiap bentuk kejadian. Tiap baris dalam tabel ini mewakili satu bentuk kekerapan. Untuk kejadian satu kali ada pemetaan 1:1 antara instance dan kejadian. Untuk kejadian berulang, beberapa baris akan dibuat secara otomatis yang sesuai dengan beberapa kejadian itu.
CalendarContract.Attendees Tabel ini menyimpan informasi peserta (tamu) kejadian. Tiap baris mewakili satu tamu kejadian. Ini menetapkan tipe tamu dan respons kehadiran tamu untuk kejadian.
CalendarContract.Reminders Tabel ini menyimpan data peringatan/notifikasi. Tiap baris mewakili satu peringatan untuk sebuah kejadian. Sebuah kejadian bisa memiliki beberapa pengingat. Jumlah maksimum pengingat per kejadian ditetapkan dalam MAX_REMINDERS, yang disetel oleh adaptor sinkronisasi yang memiliki kalender yang diberikan. Pengingat ditetapkan dalam menit sebelum kejadian dan memiliki metode yang menentukan cara pengguna akan diperingatkan.

Calendar Provider API didesain agar luwes dan tangguh. Sementara itu , Anda perlu memberikan pengalaman pengguna akhir yang baik dan melindungi integritas kalender dan datanya. Untuk mencapainya, berikut ini adalah beberapa hal yang harus diingat saat menggunakan API ini:

  • Menyisipkan, memperbarui, dan menampilkan kejadian kalender. Untuk menyisipkan, mengubah, dan membaca kejadian secara langsung dari Penyedia Kalender, Anda memerlukan izin yang sesuai. Akan tetapi, jika Anda tidak sedang membangun aplikasi atau adaptor sinkronisasi kalender berfitur lengkap, maka tidak perlu meminta izin. Sebagai gantinya, Anda bisa menggunakan maksud yang didukung oleh aplikasi Kalender Android untuk menyerahkan operasi baca dan tulis ke aplikasi itu. Bila menggunakan maksud, aplikasi Anda akan mengirim pengguna ke aplikasi Kalender untuk melakukan operasi yang diinginkan dalam sebuah formulir yang sudah diisi. Setelah operasi selesai, formulir dikembalikan ke aplikasi Anda. Dengan mendesain aplikasi untuk melakukan operasi umum melalui Kalender, Anda akan memberi pengguna sebuah antarmuka pengguna yang konsisten dan tangguh. Inilah pendekatan yang disarankan. Untuk informasi selengkapnya, lihat Maksud Kalender.

  • Adaptor sinkronisasi. Adaptor sinkronisasi menyinkronkan data kalender pada perangkat pengguna dengan server atau sumber data lain. Dalam tabel CalendarContract.Calendars dan CalendarContract.Events, ada kolom yang dicadangkan untuk digunakan adaptor sinkronisasi. Penyedia dan aplikasi tidak boleh memodifikasinya. Sebenarnya, tabel-tabel itu tidak terlihat kecuali jika diakses sebagai adaptor sinkronisasi. Untuk informasi selengkapnya tentang adaptor sinkronisasi, lihat Adaptor Sinkronisasi.

Izin Pengguna

Untuk membaca data kalender, aplikasi harus menyertakan izin READ_CALENDAR dalam file manifesnya. File harus menyertakan izin WRITE_CALENDAR untuk menghapus, menyisipkan, atau memperbarui data kalender:

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

Tabel Kalender

Tabel CalendarContract.Calendars berisi data untuk tiap kalender. Kolom-kolom Kalender berikut ini bisa ditulisi oleh aplikasi maupun adaptor sinkronisasi. Untuk daftar lengkap tentang bidang yang didukung, lihat referensi CalendarContract.Calendars.

Konstanta Keterangan
NAME Nama kalender.
CALENDAR_DISPLAY_NAME Nama kalender ini yang ditampilkan kepada pengguna.
VISIBLE Sebuah boolean yang menunjukkan apakah kalender dipilih untuk ditampilkan. Nilai 0 menunjukkan bahwa kejadian yang terkait dengan kalender ini tidak boleh ditampilkan. Nilai 1 menunjukkan bahwa kejadian yang terkait dengan kalender ini harus ditampilkan. Nilai ini memengaruhi pembuatan baris dalam tabel CalendarContract.Instances.
SYNC_EVENTS Sebuah boolean yang menunjukkan apakah kalender harus disinkronkan dan apakah kejadiannya harus disimpan pada perangkat. Nilai 0 berarti jangan menyinkronkan kalender ini atau simpan kejadiannya pada perangkat. Nilai 1 berarti menyinkronkan kejadian untuk kalender ini dan simpan kejadiannya pada perangkat.

Membuat kueri kalender

Berikut ini adalah contoh yang menampilkan cara mendapatkan kalender yang dimiliki oleh pengguna tertentu. Untuk memudahkan, dalam contoh ini, operasi kueri ditampilkan dalam thread antarmuka pengguna ("thread utama"). Dalam praktiknya, hal ini harus dilakukan dalam thread asinkron, sebagai ganti pada thread utama. Untuk pembahasan selengkapnya, lihat Loader. Jika Anda tidak sekadar membaca data melainkan memodifikasinya, lihat AsyncQueryHandler.

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

Di bagian berikutnya pada contoh ini, Anda akan melakukan kueri. Pemilihan akan menetapkan kriteria untuk kueri. Dalam contoh ini, kueri mencari kalender yang memiliki ACCOUNT_NAME "sampleuser@google.com", ACCOUNT_TYPE "com.google", dan OWNER_ACCOUNT "sampleuser@google.com". Jika Anda ingin melihat semua kalender yang telah ditampilkan pengguna, bukan hanya kalender yang dimiliki pengguna, hilangkan OWNER_ACCOUNT. Kueri tersebut akan mengembalikan objek Cursor yang bisa Anda gunakan untuk menyusuri set hasil yang dikembalikan oleh kueri database. Untuk pembahasan selengkapnya tentang penggunaan kueri dalam penyedia materi, lihat Penyedia Materi.

// 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[] {"sampleuser@gmail.com", "com.google",
        "sampleuser@gmail.com"};
// Submit the query and get a Cursor object back.
cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

Bagian berikutnya ini menggunakan kursor untuk merunut set hasil. Bagian ini menggunakan konstanta yang disiapkan pada awal contoh ini untuk mengembalikan nilai-nilai bagi tiap bidang.

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

   ...
}

Memodifikasi kalender

Untuk melakukan pembaruan kalender, Anda bisa menyediakan _ID kalender itu baik sebagai ID yang ditambahkan ke URI (withAppendedId()) atau sebagai item pilihan pertama. Seleksi harus dimulai dengan"_id=?", dan selectionArg yang pertama haruslah _ID kalender. Anda juga bisa melakukan pembaruan dengan enkode ID dalam URI. Contoh ini mengubah nama tampilan kalender dengan pendekatan (withAppendedId()) :

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

Menyisipkan kalender

Kalender didesain untuk dikelola terutama oleh sebuah adaptor sinkronisasi, sehingga Anda hanya boleh menyisipkan kalender baru sebagai adaptor sinkronisasi. Biasanya, aplikasi hanya bisa membuat perubahan semu pada kalender, misalnya mengubah nama tampilan. Jika perlu membuat sebuah kalender lokal, aplikasi bisa melakukannya dengan melakukan penyisipan kalender sebagai adaptor sinkronisasi, menggunakan ACCOUNT_TYPE dari ACCOUNT_TYPE_LOCAL. ACCOUNT_TYPE_LOCAL adalah sebuah tipe akun khusus untuk kalender yang tidak terkait dengan akun perangkat. Kalender tipe ini tidak disinkronkan dengan server. Untuk diskusi tentang adaptor sinkronisasi, lihat Adaptor Sinkronisasi.

Tabel Events

Tabel CalendarContract.Events berisi detail untuk tiap kejadian. Untuk menambah, memperbarui, atau menghapus kejadian, aplikasi harus menyertakan izin WRITE_CALENDAR dalam file manifesnya.

Kolom-kolom Events berikut ini bisa ditulis oleh aplikasi maupun adaptor sinkronisasi. Untuk mengetahui daftar lengkap bidang-bidang yang didukung, lihat referensi CalendarContract.Events.

Konstanta Keterangan
CALENDAR_ID _ID Kalender yang memiliki kejadian.
ORGANIZER Email penyelenggara (pemilik) kejadian.
TITLE Judul kejadian.
EVENT_LOCATION Tempat kejadian berlangsung.
DESCRIPTION Keterangan kejadian.
DTSTART Waktu mulai kejadian dalam milidetik UTC sejak waktu patokan.
DTEND Waktu selesai kejadian dalam milidetik UTC sejak waktu patokan.
EVENT_TIMEZONE Zona waktu kejadian.
EVENT_END_TIMEZONE Zona waktu untuk waktu berakhir kejadian.
DURATION Durasi kejadian dalam format RFC5545. Misalnya, nilai "PT1H" menyatakan bahwa kejadian akan berlangsung satu jam, dan nilai "P2W" menunjukkan durasi 2 minggu.
ALL_DAY Nilai 1 menunjukkan kejadian ini memakan waktu sehari penuh, seperti yang didefinisikan oleh zona waktu lokal. Nilai 0 menunjukkan kejadian adalah kejadian biasa yang mungkin dimulai dan selesai pada sembarang waktu selama suatu hari.
RRULE Aturan perulangan untuk format kejadian. Misalnya, "FREQ=WEEKLY;COUNT=10;WKST=SU". Anda bisa menemukan contoh selengkapnya di sini.
RDATE Tanggal perulangan kejadian. Anda biasanya menggunakan RDATE bersama RRULE untuk mendefinisikan serangkaian agregat kejadian berulang. Untuk pembahasan selengkapnya, lihat Spesifikasi RFC5545.
AVAILABILITY Jika kejadian ini dihitung sebagai waktu sibuk atau waktu luang yang bisa dijadwalkan lagi.
GUESTS_CAN_MODIFY Apakah tamu bisa memodifikasi kejadian atau tidak.
GUESTS_CAN_INVITE_OTHERS Apakah tamu bisa mengundang tamu lain atau tidak.
GUESTS_CAN_SEE_GUESTS Apakah tamu bisa membaca daftar peserta atau tidak.

Menambahkan Kejadian

Bila aplikasi Anda menyisipkan kejadian baru, sebaiknya Anda menggunakan Maksud INSERT, seperti dijelaskan dalam Menggunakan maksud untuk menyisipkan kejadian. Akan tetapi, jika perlu, Anda bisa menyisipkan kejadian secara langsung. Bagian ini menjelaskan caranya.

Berikut ini adalah aturan untuk menyisipkan kejadian baru:

Berikut ini adalah contoh penyisipan kejadian. Penyisipan ini dilakukan dalam thread UI demi kemudahan. Dalam praktiknya, penyisipan dan pembaruan harus dilakukan di thread asinkron untuk memindahkan aksi ke dalam thread latar belakang. Untuk informasi selengkapnya, lihat AsyncQueryHandler.

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

Catatan: Lihat cara contoh ini menangkap ID kejadian setelah kejadian dibuat. Inilah cara termudah untuk mendapatkan ID kejadian. Anda akan sering memerlukan ID kejadian untuk melakukan operasi kalender lainnya—misalnya, untuk menambahkan peserta atau pengingat ke kejadian.

Memperbarui Kejadian

Bila aplikasi Anda ingin memperbolehkan pengguna mengedit kejadian, sebaiknya gunakan Maksud EDIT, seperti dijelaskan dalam Menggunakan maksud untuk mengedit kejadian. Akan tetapi, jika perlu, Anda bisa mengedit kejadian secara langsung. Untuk melakukan pembaruan suatu Kejadian, Anda bisa menyediakan _ID kejadian itu sebagai ID yang ditambahkan ke Uri (withAppendedId()) atau sebagai item pilihan pertama. Pemilihan harus dimulai dengan "_id=?", dan selectionArg pertama harus _ID kejadian. Anda juga bisa melakukan pembaruan dengan menggunakan pemilihan tanpa ID. Berikut ini adalah contoh pembaruan kejadian. Contoh ini mengubah judul kejadian dengan pendekatan withAppendedId() :

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 = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);  

Menghapus Kejadian

Anda bisa menghapus kejadian dengan _ID sebagai ID yang ditambahkan pada URI, atau dengan pemilihan standar. Jika Anda menggunakan ID yang ditambahkan, Anda tidak bisa melakukan pemilihan. Ada dua versi penghapusan: sebagai aplikasi dan sebagai adaptor sinkronisasi. Penghapusan aplikasi menyetel kolom yang dihapus ke 1. Flag ini yang memberi tahu adaptor sinkronisasi bahwa baris telah dihapus dan bahwa penghapusan ini harus diberitahukan ke server. Penghapusan adaptor sinkronisasi akan membuang kejadian dari database bersama semua data terkaitnya. Berikut ini adalah contoh aplikasi yang menghapus kejadian melalui _ID-nya:

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

Tabel Peserta

Tiap baris tabel CalendarContract.Attendees mewakili satu peserta atau tamu dari sebuah kejadian. Memanggil query() akan mengembalikan daftar peserta untuk kejadian dengan EVENT_ID yang diberikan. EVENT_ID ini harus cocok dengan _ID dari kejadian tertentu.

Tabel berikut mencantumkan bidang-bidang yang bisa ditulis. Saat menyisipkan peserta baru, Anda harus menyertakan semuanya kecuali ATTENDEE_NAME.

Konstanta Keterangan
EVENT_ID ID kejadian.
ATTENDEE_NAME Nama peserta.
ATTENDEE_EMAIL Alamat email peserta.
ATTENDEE_RELATIONSHIP

Hubungan peserta dengan kejadian. Salah satu dari:

ATTENDEE_TYPE

Tipe peserta. Salah satu dari:

ATTENDEE_STATUS

Status kehadiran peserta. Salah satu dari:

Menambahkan Peserta

Berikut ini adalah contoh yang menambahkan satu peserta ke kejadian. Perhatikan bahwa EVENT_ID diperlukan:

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

Tabel Pengingat

Tiap baris tabel CalendarContract.Reminders mewakili satu pengingat untuk sebuah kejadian. Memanggil query() akan mengembalikan daftar pengingat untuk kejadian dengan EVENT_ID yang diberikan.

Tabel berikut mencantumkan bidang-bidang yang bisa ditulis untuk pengingat. Semua bidang harus disertakan saat menyisipkan pengingat baru. Perhatikan bahwa adaptor sinkronisasi menetapkan tipe pengingat yang didukungnya dalam tabel CalendarContract.Calendars. Lihat ALLOWED_REMINDERS untuk detailnya.

Konstanta Keterangan
EVENT_ID ID kejadian.
MINUTES Menit yang ditunggu untuk memicu kejadian pengingat.
METHOD

Metode alarm, seperti yang diatur pada server. Salah satu dari:

Menambahkan Pengingat

Contoh ini menambahkan pengingat ke kejadian. Pengingat dipicu 15 menit sebelum kejadian.

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

Tabel Instances

Tabel CalendarContract.Instances menyimpan waktu mulai dan waktu berakhir kejadian. Tiap baris dalam tabel ini mewakili satu bentuk kekerapan. Tabel instance tidak bisa ditulis dan hanya menyediakan sebuah cara untuk membuat kueri kekerapan.

Tabel berikut mencantumkan beberapa bidang yang bisa Anda kueri untuk suatu instance. Perhatikan bahwa zona waktu didefinisikan oleh KEY_TIMEZONE_TYPE dan KEY_TIMEZONE_INSTANCES.

Konstanta Keterangan
BEGIN Waktu mulai instance, dalam milidetik UTC.
END Waktu berakhir instance, dalam milidetik UTC.
END_DAY Hari berakhir Julian dari instance, relatif terhadap zona waktu Kalender.
END_MINUTE Menit berakhir dari instance yang diukur dari tengah malam di zona waktu Kalender.
EVENT_ID _ID Kejadian untuk instance ini.
START_DAY Hari mulai Julian dari instance, relatif terhadap zona waktu Kalender.
START_MINUTE Menit mulai dari instance yang diukur dari tengah malam, relatif terhadap zona waktu Kalender.

Membuat kueri tabel Instance

Untuk melakukan kueri tabel Instances, Anda perlu menetapkan rentang waktu kueri dalam URI. Dalam contoh ini, CalendarContract.Instances mendapat akses ke bidang TITLE melalui implementasi dari antarmuka CalendarContract.EventsColumns. Dengan kata lain, TITLE dikembalikan melalui database tampilan, tidak melalui kueri tabel CalendarContract.Instances mentah.

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

Maksud Kalender

Aplikasi Anda tidak memerlukan izin untuk membaca dan menulis data kalender. Sebagai gantinya, aplikasi bisa menggunakan maksud yang didukung oleh aplikasi Kalender Android untuk menyerahkan operasi baca dan tulis ke aplikasi itu. Tabel berikut mencantumkan maksud yang didukung oleh Penyedia Kalender:

Aksi URI Keterangan Tambahan

VIEW

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

Anda juga bisa mengacu ke URI dengan CalendarContract.CONTENT_URI. Untuk contoh yang menggunakan maksud ini, lihat Menggunakan maksud untuk menampilkan data kalender.
Membuka kalender pada waktu yang ditetapkan oleh <ms_since_epoch>. Tidak ada.

VIEW

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

Anda juga bisa mengacu ke URI dengan Events.CONTENT_URI. Untuk contoh yang menggunakan maksud ini, lihat Menggunakan maksud untuk menampilkan data kalender.
Menampilkan kejadian yang ditetapkan oleh <event_id>. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

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

Anda juga bisa mengacu ke URI dengan Events.CONTENT_URI. Untuk contoh yang menggunakan maksud ini, lihat Menggunakan maksud untuk mengedit kejadian.
Mengedit kejadian yang ditetapkan oleh <event_id>. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

INSERT

content://com.android.calendar/events

Anda juga bisa mengacu ke URI dengan Events.CONTENT_URI. Untuk contoh yang menggunakan maksud ini, lihat Menggunakan maksud untuk menyisipkan kejadian.
Membuat sebuah kejadian. Beberapa tambahan tercantum dalam tabel di bawah.

Tabel berikut mencantumkan tambahan maksud yang didukung oleh Penyedia Kalender:

Ekstra Maksud Keterangan
Events.TITLE Nama kejadian.
CalendarContract.EXTRA_EVENT_BEGIN_TIME Waktu mulai kejadian dalam milidetik sejak waktu patokan.
CalendarContract.EXTRA_EVENT_END_TIME Waktu berakhir kejadian dalam milidetik sejak waktu patokan.
CalendarContract.EXTRA_EVENT_ALL_DAY Sebuah boolean yang menunjukkan bahwa kejadian berlangsung sehari penuh. Nilai bisa true atau false.
Events.EVENT_LOCATION Lokasi kejadian.
Events.DESCRIPTION Keterangan kejadian.
Intent.EXTRA_EMAIL Alamat email mereka yang akan diundang, berupa daftar yang dipisahkan koma.
Events.RRULE Aturan perulangan kejadian.
Events.ACCESS_LEVEL Apakah kejadian bersifat privat atau publik.
Events.AVAILABILITY Jika kejadian ini dihitung sebagai waktu sibuk atau waktu luang yang bisa dijadwalkan lagi.

Bagian berikut menjelaskan cara menggunakan semua maksud ini.

Menggunakan maksud untuk menyisipkan kejadian

Penggunaan Maksud INSERT akan memungkinkan aplikasi Anda menyerahkan tugas penyisipan kejadian ke Kalender itu sendiri. Dengan pendekatan ini, aplikasi Anda bahkan tidak perlu menyertakan izin WRITE_CALENDAR dalam file manifesnya.

Bila pengguna menjalankan aplikasi yang menggunakan pendekatan ini, aplikasi akan mengirim izin ke Kalender untuk menyelesaikan penambahan kejadian. Maksud INSERT menggunakan bidang-bidang ekstra untuk mengisi formulir lebih dahulu dengan detail kejadian dalam Kalender. Pengguna kemudian bisa membatalkan kejadian, mengedit formulir bila perlu, atau menyimpan kejadian ke kalender mereka.

Berikut ini adalah cuplikan kode yang menjadwalkan kejadian pada tanggal 19 Januari 2012, yang berjalan dari 7:30 pagi hingga 8:30 pagi. Perhatikan hal-hal berikut tentang cuplikan kode ini:

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

Menggunakan maksud untuk mengedit kejadian

Anda bisa memperbarui kejadian secara langsung, seperti dijelaskan dalam Memperbarui kejadian. Namun penggunaan Maksud EDIT memungkinkan aplikasi yang tidak memiliki izin untuk menyerahkan pengeditan kejadian ke aplikasi Kalender. Bila pengguna selesai mengedit kejadian dalam Kalender, pengguna akan dikembalikan ke aplikasi semula.

Berikut ini adalah contoh maksud yang mengatur judul baru bagi kejadian yang ditetapkan dan memungkinkan pengguna mengedit kejadian dalam Kalender.

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

Menggunakan maksud untuk menampilkan data kalender

Penyedia Kalender menyediakan dua cara menggunakan Maksud VIEW:

  • Untuk membuka Kalender pada tanggal tertentu.
  • Untuk menampilkan sebuah kejadian.

Berikut ini adalah contoh yang menampilkan cara membuka Kalender pada tanggal tertentu:

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

Berikut ini adalah contoh yang menampilkan cara membuka kejadian untuk menampilkan:

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

Adaptor Sinkronisasi

Hanya ada perbedaan kecil dalam cara aplikasi dan adaptor sinkronisasi mengakses Penyedia Kalender:

  • Adaptor sinkronisasi perlu menetapkan bahwa dirinya sebuah adaptor sinkronisasi dengan menyetel CALLER_IS_SYNCADAPTER ke true.
  • Adaptor sinkronisasi perlu menyediakan ACCOUNT_NAME dan ACCOUNT_TYPE sebagai parameter kueri dalam URI.
  • Adaptor sinkronisasi memiliki akses tulis ke lebih banyak kolom daripada aplikasi atau widget. Misalnya, aplikasi hanya bisa mengubah sedikit karakteristik kalender, misalnya nama, nama tampilan, setelan visibilitas, dan apakah kalender disinkronkan atau tidak. Sebagai perbandingan, adaptor sinkronisasi bisa mengakses bukan hanya kolom-kolom itu, namun banyak kolom lainnya, misalnya warna kalender, zona waktu, tingkat akses, lokasi, dan seterusnya. Akan tetapi, adaptor sinkronisasi dibatasi pada ACCOUNT_NAME dan ACCOUNT_TYPE yang ditetapkannya.

Berikut ini adalah metode pembantu yang bisa Anda gunakan untuk mengembalikan URI bagi penggunaan dengan adaptor sinkronisasi:

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

Untuk contoh implementasi adaptor sinkronisasi (yang tidak terkait secara khusus dengan Kalender), lihat SampleSyncAdapter.