Home | History | Annotate | Download | only in providers
      1 page.title=Penyedia Kalender
      2 @jd:body
      3 
      4 <div id="qv-wrapper">
      5 <div id="qv">
      6     <h2>Dalam dokumen ini</h2>
      7     <ol>
      8   <li><a href="#overview">Dasar-Dasar</a></li>
      9   <li><a href="#manifest">Izin Pengguna</a></li>
     10   <li><a href="#calendar">Tabel kalender</a>
     11 <ol>
     12       <li><a href="#query">Membuat query kalender</a></li>
     13       <li><a href="#modify-calendar">Memodifikasi kalender</a></li>
     14       <li><a href="#insert-calendar">Menyisipkan kalender</a></li>
     15     </ol>
     16   </li>
     17   <li><a href="#events">Tabel Events</a>
     18 <ol>
     19       <li><a href="#add-event">Menambahkan Kejadian</a></li>
     20       <li><a href="#update-event">Memperbarui Kejadian</a></li>
     21       <li><a href="#delete-event">Menghapus Kejadian</a></li>
     22     </ol>
     23   </li>
     24   <li><a href="#attendees">Tabel peserta</a>
     25 <ol>
     26       <li><a href="#add-attendees">Menambahkan Peserta</a></li>
     27     </ol>
     28   </li>
     29   <li><a href="#reminders">Tabel pengingat</a>
     30 <ol>
     31       <li><a href="#add-reminders">Menambahkan Pengingat</a></li>
     32     </ol>
     33   </li>
     34   <li><a href="#instances">Tabel Instances</a>
     35   <ol>
     36       <li><a href="#query-instances">Membuat query tabel Instance</a></li>
     37   </ol></li>
     38   <li><a href="#intents">Intent Kalender</a>
     39   <ol>
     40       <li><a href="#intent-insert">Menggunakan intent untuk menyisipkan kejadian</a></li>
     41       <li><a href="#intent-edit">Menggunakan intent untuk mengedit kejadian</a></li>
     42       <li><a href="#intent-view">Menggunakan intent untuk menampilkan data kalender</a></li>
     43     </ol>
     44   </li>
     45   
     46   <li><a href="#sync-adapter">Adaptor Sinkronisasi</a></li>
     47 </ol>
     48 
     49     <h2>Kelas-kelas utama</h2>
     50     <ol>
     51       <li>{@link android.provider.CalendarContract.Calendars}</li>
     52       <li>{@link android.provider.CalendarContract.Events}</li>
     53       <li>{@link android.provider.CalendarContract.Attendees}</li>
     54       <li>{@link android.provider.CalendarContract.Reminders}</li>
     55     </ol>
     56 </div>
     57 </div>
     58 
     59 <p>Penyedia Kalender adalah repository untuk kejadian kalender seorang pengguna. API
     60 Penyedia Kalender memungkinkan Anda melakukan query, menyisipkan, memperbarui, dan menghapus
     61 pada kalender, kejadian, peserta, pengingat, dan seterusnya.</p>
     62 
     63 
     64 <p>API Penyedia Kalender bisa digunakan oleh aplikasi dan adaptor sinkronisasi. Aturannya
     65 bervariasi menurut tipe program yang membuat panggilan. Dokumen ini
     66 terutama berfokus pada penggunaan API Penyedia Kalender sebagai sebuah aplikasi. Untuk 
     67 pembahasan ragam adaptor sinkronisasi, lihat 
     68 <a href="#sync-adapter">Adaptor Sinkronisasi</a>.</p>
     69 
     70 
     71 <p>Biasanya, untuk membaca atau menulis data kalender, manifes aplikasi harus
     72 berisi izin yang sesuai, yang dijelaskan dalam <a href="#manifest">Izin
     73 Pengguna</a>. Untuk mempermudah dilakukannya operasi umum,
     74 Penyedia Kalender menyediakan satu set intent, seperti dijelaskan dalam <a href="#intents">Intent
     75 Kalender</a>. Semua intent ini membawa pengguna ke aplikasi Kalender untuk menyisipkan, menampilkan,
     76 dan mengedit kejadian. Pengguna berinteraksi dengan aplikasi Kalender kemudian
     77 kembali ke aplikasi semula. Jadi, aplikasi Anda tidak perlu meminta izin,
     78 juga tidak perlu menyediakan antarmuka pengguna untuk menampilkan atau membuat kejadian.</p>
     79 
     80 <h2 id="overview">Dasar-Dasar</h2>
     81 
     82 <p><a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia konten</a> menyimpan data dan menjadikannya bisa diakses oleh
     83 aplikasi. Penyedia konten yang ditawarkan oleh platform Android (termasuk Penyedia Kalender) biasanya mengekspos data sebagai satu set tabel berdasarkan
     84 model database relasional, dengan tiap baris berupa record dan tiap kolom berupa data
     85 yang memiliki tipe dan arti tertentu. Melalui API Penyedia Kalender, aplikasi
     86 dan adaptor sinkronisasi bisa mendapatkan akses baca/tulis ke tabel-tabel database yang menyimpan
     87 data kalender seorang pengguna.</p>
     88 
     89 <p>Setiap penyedia konten membuka sebuah URI publik (yang dibungkus sebagai objek
     90 {@link android.net.Uri}
     91 ) yang mengidentifikasikan set datanya secara unik.  Penyedia konten yang mengontrol
     92  beberapa set data (beberapa tabel) mengekspos URI terpisah untuk tiap set.  Semua 
     93 URI untuk penyedia diawali dengan string "content://".  String ini
     94 mengidentifikasi data sebagai dikontrol oleh penyedia konten. Penyedia Kalender
     95 mendefinisikan konstanta untuk URI masing-masing kelas (tabel). URI ini
     96 memiliki format <code><em>&lt;class&gt;</em>.CONTENT_URI</code>. Misalnya,
     97 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}.</p>
     98 
     99 <p>Gambar 1 menampilkan representasi grafis model data Penyedia Kalender. Gambar ini menampilkan
    100 tabel dan bidang utama yang saling berkaitan.</p>
    101 
    102 <img src="{@docRoot}images/providers/datamodel.png" alt="Calendar Provider Data Model" />
    103 <p class="img-caption"><strong>Gambar 1.</strong> Model data Penyedia Kalender.</p>
    104 
    105 <p>Seorang pengguna bisa memiliki beberapa kalender, dan kalender yang berbeda bisa dikaitkan dengan tipe akun yang berbeda (Google Calendar, Exchange, dan seterusnya).</p>
    106 
    107 <p>{@link android.provider.CalendarContract} mendefinisikan model data dari informasi yang terkait dengan kalender dan kejadian. Data ini disimpan di sejumlah tabel, yang dicantumkan di bawah ini.</p>
    108 
    109 <table>
    110   <tr>
    111     <th>Tabel (Kelas)</th>
    112     <th>Keterangan</th>
    113   </tr>
    114   <tr>
    115     <td><p>{@link android.provider.CalendarContract.Calendars}</p></td>
    116     
    117     <td>Tabel ini menyimpan 
    118 informasi khusus kalender. Tiap baris dalam tabel ini berisi data untuk
    119 satu kalender, seperti nama, warna, informasi sinkronisasi, dan seterusnya.</td>
    120   </tr>
    121   <tr>
    122     <td>{@link android.provider.CalendarContract.Events}</td>
    123     
    124     <td>Tabel ini menyimpan
    125 informasi khusus kejadian. Tiap baris dalam tabel ini berisi informasi untuk satu
    126 kejadian&mdash;misalnya, judul kejadian, lokasi, waktu mulai, waktu
    127 selesai, dan seterusnya. Kejadian bisa terjadi satu kali atau bisa berulang beberapa kali. Peserta,
    128 pengingat, dan properti perluasan disimpan dalam tabel terpisah. 
    129 Masing-masing memiliki sebuah {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 
    130 yang mengacu {@link android.provider.BaseColumns#_ID} dalam tabel Events.</td>
    131 
    132   </tr>
    133   <tr>
    134     <td>{@link android.provider.CalendarContract.Instances}</td>
    135     
    136     <td>Tabel ini menyimpan
    137 waktu mulai dan waktu selesai setiap bentuk kejadian. Tiap baris dalam tabel ini
    138 mewakili satu bentuk kejadian. Untuk kejadian satu kali ada pemetaan 1:1
    139 antara instance dan kejadian. Untuk kejadian berulang, beberapa baris akan dibuat
    140 secara otomatis yang sesuai dengan beberapa kejadian itu.</td>
    141   </tr>
    142   <tr>
    143     <td>{@link android.provider.CalendarContract.Attendees}</td>
    144     
    145     <td>Tabel ini menyimpan
    146 informasi peserta (tamu) kejadian. Tiap baris mewakili satu tamu
    147 kejadian. Ini menetapkan tipe tamu dan respons kehadiran tamu
    148 untuk kejadian.</td>
    149   </tr>
    150   <tr>
    151     <td>{@link android.provider.CalendarContract.Reminders}</td>
    152     
    153     <td>Tabel ini menyimpan
    154 data peringatan/pemberitahuan. Tiap baris mewakili satu peringatan untuk sebuah kejadian. Sebuah
    155 kejadian bisa memiliki beberapa pengingat. Jumlah maksimum pengingat per kejadian
    156 ditetapkan dalam 
    157 {@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS}, 
    158 yang diatur oleh adaptor sinkronisasi yang
    159 memiliki kalender yang diberikan. Pengingat ditetapkan dalam menit sebelum kejadian
    160 dan memiliki metode yang menentukan cara pengguna akan diperingatkan.</td>
    161   </tr>
    162   
    163 </table>
    164 
    165 <p>API Penyedia Kalender didesain agar luwes dan tangguh. Sementara itu
    166 , Anda perlu memberikan pengalaman pengguna akhir yang baik dan
    167 melindungi integritas kalender dan datanya. Untuk mencapainya, berikut ini adalah
    168 beberapa hal yang harus diingat saat menggunakan API ini:</p>
    169 
    170 <ul>
    171 
    172 <li><strong>Menyisipkan, memperbarui, dan menampilkan kejadian kalender.</strong> Untuk menyisipkan, mengubah, dan membaca kejadian secara langsung dari Penyedia Kalender, Anda memerlukan <a href="#manifest">izin</a> yang sesuai. Akan tetapi, jika Anda tidak sedang membuat aplikasi atau adaptor sinkronisasi kalender berfitur lengkap, maka tidak perlu meminta izin. Sebagai gantinya, Anda bisa menggunakan intent yang didukung oleh aplikasi Kalender Android untuk menyerahkan operasi baca dan tulis ke aplikasi itu. Bila menggunakan intent, aplikasi Anda akan mengirim pengguna ke aplikasi Kalender untuk melakukan operasi yang diinginkan
    173 dalam sebuah formulir yang sudah diisi. Setelah operasi selesai, formulir dikembalikan ke aplikasi Anda.
    174 Dengan mendesain aplikasi untuk melakukan operasi umum melalui Kalender,
    175 Anda akan memberi pengguna sebuah antarmuka pengguna yang konsisten dan tangguh. Inilah
    176 pendekatan yang disarankan. Untuk informasi selengkapnya, lihat <a href="#intents">Intent
    177 Kalender</a>.</p>
    178 
    179 
    180 <li><strong>Adaptor sinkronisasi.</strong> Adaptor sinkronisasi menyinkronkan data kalender
    181 pada perangkat pengguna dengan server atau sumber data lain. Dalam tabel 
    182 {@link android.provider.CalendarContract.Calendars} dan
    183 {@link android.provider.CalendarContract.Events}, 
    184 ada kolom yang dicadangkan untuk digunakan adaptor sinkronisasi.
    185 Penyedia dan aplikasi tidak boleh memodifikasinya. Sebenarnya, tabel-tabel itu tidak
    186 terlihat kecuali jika diakses sebagai adaptor sinkronisasi. Untuk informasi selengkapnya tentang
    187 adaptor sinkronisasi, lihat <a href="#sync-adapter">Adaptor Sinkronisasi</a>.</li>
    188 
    189 </ul>
    190 
    191 
    192 <h2 id="manifest">Izin Pengguna</h2>
    193 
    194 <p>Untuk membaca data kalender, aplikasi harus menyertakan izin {@link
    195 android.Manifest.permission#READ_CALENDAR} dalam file manifesnya. File
    196 harus menyertakan izin {@link android.Manifest.permission#WRITE_CALENDAR}
    197 untuk menghapus, menyisipkan, atau memperbarui data kalender:</p>
    198 
    199 <pre>
    200 &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
    201 &lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android"...>;
    202     &lt;uses-sdk android:minSdkVersion=&quot;14&quot; /&gt;
    203     &lt;uses-permission android:name=&quot;android.permission.READ_CALENDAR&quot; /&gt;
    204     &lt;uses-permission android:name=&quot;android.permission.WRITE_CALENDAR&quot; /&gt;
    205     ...
    206 &lt;/manifest&gt;
    207 </pre>
    208 
    209 
    210 <h2 id="calendar">Tabel Kalender</h2>
    211 
    212 <p>Tabel {@link android.provider.CalendarContract.Calendars} berisi data
    213 untuk tiap kalender. Kolom-kolom
    214 berikut ini bisa ditulisi oleh aplikasi maupun <a href="#sync-adapter">adaptor sinkronisasi</a>. 
    215 Untuk mengetahui daftar lengkap bidang-bidang yang didukung, lihat
    216 acuan {@link android.provider.CalendarContract.Calendars}.</p>
    217 <table>
    218   <tr>
    219     <th>Konstanta</th>
    220     <th>Keterangan</th>
    221   </tr>
    222   <tr>
    223     <td>{@link android.provider.CalendarContract.Calendars#NAME}</td>
    224     <td>Nama kalender.</td>
    225   </tr>
    226   <tr>
    227     <td>{@link android.provider.CalendarContract.Calendars#CALENDAR_DISPLAY_NAME}</td>
    228     <td>Nama kalender ini yang ditampilkan kepada pengguna.</td>
    229   </tr>
    230   <tr>
    231     <td>{@link android.provider.CalendarContract.Calendars#VISIBLE}</td>
    232     
    233     <td>Sebuah boolean yang menunjukkan apakah kalender dipilih untuk ditampilkan. Nilai
    234 0 menunjukkan bahwa kejadian yang terkait dengan kalender ini tidak boleh
    235 ditampilkan.  Nilai 1 menunjukkan bahwa kejadian yang terkait dengan kalender ini harus
    236 ditampilkan. Nilai ini memengaruhi pembuatan baris dalam tabel {@link
    237 android.provider.CalendarContract.Instances}.</td>
    238 
    239 
    240   </tr>
    241   <tr>
    242     <td>{@link android.provider.CalendarContract.CalendarColumns#SYNC_EVENTS}</td>
    243     
    244     <td>Sebuah boolean yang menunjukkan apakah kalender harus disinkronkan dan apakah
    245 kejadiannya harus disimpan pada perangkat. Nilai 0 berarti jangan menyinkronkan kalender ini atau
    246 simpan kejadiannya pada perangkat.  Nilai 1 berarti menyinkronkan kejadian untuk kalender ini
    247 dan simpan kejadiannya pada perangkat.</td>
    248   </tr>
    249 </table>
    250 
    251 <h3 id="query">Membuat query kalender</h3>
    252 
    253 <p>Berikut ini adalah contoh yang menampilkan cara mendapatkan kalender yang dimiliki oleh
    254 pengguna tertentu. Untuk memudahkan, dalam contoh ini, operasi query ditampilkan dalam
    255 thread antarmuka pengguna ("thread utama"). Dalam praktiknya, hal ini harus dilakukan dalam
    256 thread asinkron, sebagai ganti pada thread utama. Untuk diskusi selengkapnya, lihat 
    257 <a href="{@docRoot}guide/components/loaders.html">Loader</a>. Jika Anda tidak sekadar 
    258 membaca data melainkan memodifikasinya, lihat {@link android.content.AsyncQueryHandler}.
    259 </p>
    260 
    261 
    262 <pre>
    263 // Projection array. Creating indices for this array instead of doing
    264 // dynamic lookups improves performance.
    265 public static final String[] EVENT_PROJECTION = new String[] {
    266     Calendars._ID,                           // 0
    267     Calendars.ACCOUNT_NAME,                  // 1
    268     Calendars.CALENDAR_DISPLAY_NAME,         // 2
    269     Calendars.OWNER_ACCOUNT                  // 3
    270 };
    271   
    272 // The indices for the projection array above.
    273 private static final int PROJECTION_ID_INDEX = 0;
    274 private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
    275 private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;
    276 private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;</pre>
    277   
    278 
    279 <div class="sidebox-wrapper"> <div class="sidebox"> <h3>Mengapa Anda harus menyertakan
    280 ACCOUNT_TYPE?</h3> <p>Jika Anda membuat query pada {@link
    281 android.provider.CalendarContract.Calendars#ACCOUNT_NAME
    282 Calendars.ACCOUNT_NAME}, Anda juga harus menyertakan 
    283 {@link android.provider.CalendarContract.Calendars#ACCOUNT_TYPE Calendars.ACCOUNT_TYPE}
    284 dalam pemilihan. Itu karena akun yang bersangkutan
    285 hanya dianggap unik mengingat <code>ACCOUNT_NAME</code> dan
    286 <code>ACCOUNT_TYPE</code>-nya. <code>ACCOUNT_TYPE</code> adalah string yang sesuai dengan
    287 autentikator akun yang digunakan bila akun didaftarkan dengan
    288 {@link android.accounts.AccountManager}. Ada juga sebuah tipe akun khusus yang disebut {@link
    289 android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} untuk kalender
    290 yang tidak terkait dengan akun perangkat. Akun {@link
    291 android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} tidak
    292 disinkronkan.</p> </div> </div> 
    293 
    294 
    295 <p> Di bagian berikutnya pada contoh ini, Anda akan membuat query. Pemilihan
    296 akan menetapkan kriteria untuk query. Dalam contoh ini, query mencari
    297 kalender yang memiliki <code>ACCOUNT_NAME</code>
    298 "sampleuser (a] google.com", <code>ACCOUNT_TYPE</code>
    299 "com.google", dan <code>OWNER_ACCOUNT</code>
    300 "sampleuser (a] google.com". Jika Anda ingin melihat semua kalender yang
    301 telah ditampilkan pengguna, bukan hanya kalender yang dimiliki pengguna, hilangkan <code>OWNER_ACCOUNT</code>.
    302 Query tersebut akan menghasilkan objek {@link android.database.Cursor}
    303 yang bisa Anda gunakan untuk menyusuri set hasil yang dikembalikan oleh
    304 query database. Untuk diskusi selengkapnya tentang penggunaan query dalam penyedia konten, 
    305 lihat <a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Kalender</a>.</p>
    306 
    307 
    308 <pre>// Run query
    309 Cursor cur = null;
    310 ContentResolver cr = getContentResolver();
    311 Uri uri = Calendars.CONTENT_URI;   
    312 String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
    313                         + Calendars.ACCOUNT_TYPE + " = ?) AND ("
    314                         + Calendars.OWNER_ACCOUNT + " = ?))";
    315 String[] selectionArgs = new String[] {"sampleuser (a] gmail.com", "com.google",
    316         "sampleuser (a] gmail.com"}; 
    317 // Submit the query and get a Cursor object back. 
    318 cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);</pre>
    319 
    320 <p>Bagian berikutnya ini menggunakan kursor untuk merunut set hasil. Bagian ini menggunakan
    321 konstanta yang disiapkan pada awal contoh ini untuk menghasilkan nilai-nilai
    322 bagi tiap bidang.</p>
    323     
    324 <pre>// Use the cursor to step through the returned records
    325 while (cur.moveToNext()) {
    326     long calID = 0;
    327     String displayName = null;
    328     String accountName = null;
    329     String ownerName = null;
    330       
    331     // Get the field values
    332     calID = cur.getLong(PROJECTION_ID_INDEX);
    333     displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
    334     accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
    335     ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
    336               
    337     // Do something with the values...
    338 
    339    ...
    340 }
    341 </pre>
    342   
    343 <h3 id="modify-calendar">Memodifikasi kalender</h3>
    344 
    345 <p>Untuk melakukan pembaruan kalender, Anda bisa menyediakan {@link
    346 android.provider.BaseColumns#_ID} kalender itu baik sebagai ID yang ditambahkan ke
    347 URI 
    348 
    349 ({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 
    350 atau sebagai item pemilihan pertama. Pemilihan
    351 harus diawali dengan <code>&quot;_id=?&quot;</code>, dan
    352 <code>selectionArg</code> pertama harus berupa {@link
    353 android.provider.BaseColumns#_ID} kalender. 
    354 Anda juga bisa melakukan pembaruan dengan menuliskan kode ID dalam URI. Contoh ini mengubah
    355 nama tampilan kalender dengan pendekatan 
    356 ({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 
    357 :</p>
    358 
    359 <pre>private static final String DEBUG_TAG = "MyActivity";
    360 ...
    361 long calID = 2;
    362 ContentValues values = new ContentValues();
    363 // The new display name for the calendar
    364 values.put(Calendars.CALENDAR_DISPLAY_NAME, &quot;Trevor's Calendar&quot;);
    365 Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID);
    366 int rows = getContentResolver().update(updateUri, values, null, null);
    367 Log.i(DEBUG_TAG, &quot;Rows updated: &quot; + rows);</pre>
    368 
    369 <h3 id="insert-calendar">Menyisipkan kalender</h2>
    370 
    371 <p>Kalender didesain untuk dikelola terutama oleh sebuah adaptor sinkronisasi, sehingga Anda
    372 hanya boleh menyisipkan kalender baru sebagai adaptor sinkronisasi. Biasanya,
    373 aplikasi hanya bisa membuat perubahan semu pada kalender, misalnya mengubah nama tampilan. Jika
    374 perlu membuat sebuah kalender lokal, aplikasi bisa melakukannya dengan melakukan
    375 penyisipan kalender sebagai adaptor sinkronisasi, menggunakan {@link
    376 android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} dari {@link
    377 android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}.
    378 {@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} 
    379 adalah sebuah tipe akun khusus untuk kalender yang tidak
    380 terkait dengan akun perangkat. Kalender tipe ini tidak disinkronkan dengan server. Untuk
    381 diskusi tentang adaptor sinkronisasi, lihat <a href="#sync-adapter">Adaptor Sinkronisasi</a>.</p>
    382 
    383 <h2 id="events">Tabel Events</h2>
    384 
    385 <p>Tabel {@link android.provider.CalendarContract.Events} berisi detail
    386 untuk tiap kejadian. Untuk menambah, memperbarui, atau menghapus kejadian, aplikasi harus
    387 menyertakan izin {@link android.Manifest.permission#WRITE_CALENDAR} dalam
    388 <a href="#manifest">file manifesnya</a>.</p>
    389 
    390 <p>Kolom-kolom Events berikut ini bisa ditulis oleh aplikasi maupun
    391 adaptor sinkronisasi. Untuk mengetahui daftar lengkap bidang-bidang yang didukung, lihat acuan {@link
    392 android.provider.CalendarContract.Events}.</p>
    393 
    394 <table>
    395   <tr>
    396     <th>Konstanta</th>
    397     <th>Keterangan</th>
    398   </tr>
    399   <tr>
    400     <td>{@link android.provider.CalendarContract.EventsColumns#CALENDAR_ID}</td>
    401     <td>{@link android.provider.BaseColumns#_ID} kalender yang dimiliki kejadian.</td>
    402   </tr>
    403   <tr>
    404     <td>{@link android.provider.CalendarContract.EventsColumns#ORGANIZER}</td>
    405     <td>Email pengatur (pemilik) kejadian.</td>
    406   </tr>
    407   <tr>
    408     <td>{@link android.provider.CalendarContract.EventsColumns#TITLE}</td>
    409     <td>Judul kejadian.</td>
    410   </tr>
    411   <tr>
    412     <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION}</td>
    413     <td>Tempat kejadian. </td>
    414   </tr>
    415   <tr>
    416     <td>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION}</td>
    417     <td>Keterangan kejadian.</td>
    418   </tr>
    419   <tr>
    420     <td>{@link android.provider.CalendarContract.EventsColumns#DTSTART}</td>
    421     <td>Waktu mulai kejadian dalam milidetik UTC sejak waktu patokan. </td>
    422   </tr>
    423   <tr>
    424     <td>{@link android.provider.CalendarContract.EventsColumns#DTEND}</td>
    425     <td>Waktu selesai kejadian dalam milidetik UTC sejak waktu patokan. </td>
    426   </tr>
    427   <tr>
    428     <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}</td>
    429     <td>Zona waktu kejadian.</td>
    430   </tr>
    431   <tr>
    432     <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_END_TIMEZONE}</td>
    433     <td>Zona waktu untuk waktu selesai kejadian.</td>
    434   </tr>
    435   <tr>
    436     <td>{@link android.provider.CalendarContract.EventsColumns#DURATION}</td>
    437     
    438     <td>Durasi kejadian dalam format <a href="http://tools.ietf.org/html/rfc5545#section-3.8.2.5">RFC5545</a>.
    439 Misalnya, nilai <code>&quot;PT1H&quot;</code> menyatakan bahwa kejadian
    440 akan berlangsung satu jam, dan nilai <code>&quot;P2W&quot;</code> menunjukkan
    441 durasi 2 minggu. </td>
    442 
    443 
    444   </tr>
    445   <tr>
    446     <td>{@link android.provider.CalendarContract.EventsColumns#ALL_DAY}</td>
    447     
    448     <td>Nilai 1 menunjukkan kejadian ini memakan waktu sehari penuh, seperti yang didefinisikan oleh
    449 zona waktu lokal. Nilai 0 menunjukkan kejadian adalah kejadian biasa yang mungkin dimulai
    450 dan selesai pada sembarang waktu selama suatu hari.</td>
    451 
    452     
    453   </tr>
    454   
    455   
    456   <tr>
    457     <td>{@link android.provider.CalendarContract.EventsColumns#RRULE}</td>
    458     
    459     <td>Aturan perulangan untuk format kejadian. Misalnya,
    460 <code>&quot;FREQ=WEEKLY;COUNT=10;WKST=SU&quot;</code>. Anda bisa menemukan
    461 contoh selengkapnya <a href="http://tools.ietf.org/html/rfc5545#section-3.8.5.3">di sini</a>.</td>
    462     
    463   </tr>
    464   
    465   <tr>
    466     <td>{@link android.provider.CalendarContract.EventsColumns#RDATE}</td>
    467     <td>Tanggal perulangan kejadian. 
    468     Anda biasanya menggunakan {@link android.provider.CalendarContract.EventsColumns#RDATE} 
    469     bersama dengan {@link android.provider.CalendarContract.EventsColumns#RRULE} 
    470     untuk mendefinisikan satu set agregat
    471 kejadian berulang. Untuk diskusi selengkapnya, lihat <a href="http://tools.ietf.org/html/rfc5545#section-3.8.5.2">Spesifikasi RFC5545</a>.</td>
    472 </tr>
    473  
    474   <tr>
    475     <td>{@link android.provider.CalendarContract.EventsColumns#AVAILABILITY}</td>
    476     
    477     <td>Jika kejadian ini dihitung sebagai waktu sibuk atau waktu bebas yang bisa 
    478 dijadwalkan. </td>
    479     
    480   </tr>
    481   <tr>
    482     <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_MODIFY}</td>
    483     <td>Apakah tamu bisa memodifikasi kejadian atau tidak. </td>
    484   </tr>
    485   <tr>
    486     <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_INVITE_OTHERS}</td>
    487     <td>Apakah tamu bisa mengundang tamu lain atau tidak. </td>
    488   </tr>
    489   <tr>
    490     <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_SEE_GUESTS}</td>
    491     <td>Apakah tamu bisa membaca daftar peserta atau tidak.</td>
    492   </tr>
    493 </table>
    494 
    495 <h3 id="add-event">Menambahkan Kejadian</h3>
    496 
    497 <p>Bila aplikasi Anda menyisipkan kejadian baru, sebaiknya Anda menggunakan
    498 Intent {@link android.content.Intent#ACTION_INSERT INSERT}, seperti dijelaskan dalam <a href="#intent-insert">Menggunakan intent untuk menyisipkan kejadian</a>. Akan tetapi, jika
    499 perlu, Anda bisa menyisipkan kejadian secara langsung. Bagian ini menjelaskan
    500 caranya.</p>
    501 
    502 
    503 <p>Berikut ini adalah aturan untuk menyisipkan kejadian baru: </p>
    504 <ul>
    505 
    506   <li>Anda harus menyertakan {@link
    507 android.provider.CalendarContract.EventsColumns#CALENDAR_ID} dan {@link
    508 android.provider.CalendarContract.EventsColumns#DTSTART}.</li>
    509 
    510 <li>Anda harus menyertakan {@link
    511 android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}. Untuk mendapatkan daftar
    512 ID zona waktu yang diinstal pada sistem, gunakan {@link
    513 java.util.TimeZone#getAvailableIDs()}. Perhatikan bahwa aturan ini tidak berlaku jika
    514 Anda menyisipkan kejadian melalui Intent {@link
    515 android.content.Intent#ACTION_INSERT INSERT}, yang dijelaskan dalam <a href="#intent-insert">Menggunakan intent untuk menyisipkan kejadian</a>&mdash;dalam
    516 skenario itu, sebuah zona waktu default akan diberikan.</li>
    517   
    518   <li>Untuk kejadian tidak-berulang, Anda harus menyertakan {@link
    519 android.provider.CalendarContract.EventsColumns#DTEND}. </li>
    520   
    521   
    522   <li>Untuk kejadian berulang, Anda harus menyertakan sebuah {@link
    523 android.provider.CalendarContract.EventsColumns#DURATION} selain {@link
    524 android.provider.CalendarContract.EventsColumns#RRULE} atau {@link
    525 android.provider.CalendarContract.EventsColumns#RDATE}. Perhatikan bahwa aturan ini tidak berlaku jika
    526 Anda menyisipkan kejadian melalui Intent {@link
    527 android.content.Intent#ACTION_INSERT INSERT}, yang dijelaskan dalam <a href="#intent-insert">Menggunakan intent untuk menyisipkan kejadian</a>&mdash;dalam
    528 skenario itu, Anda bisa menggunakan {@link
    529 android.provider.CalendarContract.EventsColumns#RRULE} bersama {@link android.provider.CalendarContract.EventsColumns#DTSTART} dan {@link android.provider.CalendarContract.EventsColumns#DTEND}, dan aplikasi Calendar 
    530 akan mengubahnya menjadi durasi secara otomatis.</li>
    531   
    532 </ul>
    533 
    534 <p>Berikut ini adalah contoh penyisipan kejadian. Penyisipan ini dilakukan dalam thread UI
    535 demi kemudahan. Dalam praktiknya, penyisipan dan pembaruan harus dilakukan di
    536 thread asinkron untuk memindahkan tindakan ke dalam thread latar belakang. Untuk
    537 informasi selengkapnya, lihat {@link android.content.AsyncQueryHandler}.</p>
    538 
    539 
    540 <pre>
    541 long calID = 3;
    542 long startMillis = 0; 
    543 long endMillis = 0;     
    544 Calendar beginTime = Calendar.getInstance();
    545 beginTime.set(2012, 9, 14, 7, 30);
    546 startMillis = beginTime.getTimeInMillis();
    547 Calendar endTime = Calendar.getInstance();
    548 endTime.set(2012, 9, 14, 8, 45);
    549 endMillis = endTime.getTimeInMillis();
    550 ...
    551 
    552 ContentResolver cr = getContentResolver();
    553 ContentValues values = new ContentValues();
    554 values.put(Events.DTSTART, startMillis);
    555 values.put(Events.DTEND, endMillis);
    556 values.put(Events.TITLE, &quot;Jazzercise&quot;);
    557 values.put(Events.DESCRIPTION, &quot;Group workout&quot;);
    558 values.put(Events.CALENDAR_ID, calID);
    559 values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles");
    560 Uri uri = cr.insert(Events.CONTENT_URI, values);
    561 
    562 // get the event ID that is the last element in the Uri
    563 long eventID = Long.parseLong(uri.getLastPathSegment());
    564 // 
    565 // ... do something with event ID
    566 //
    567 //</pre>
    568 
    569 <p class="note"><strong>Catatan:</strong> Perhatikan cara contoh ini menangkap ID kejadian
    570 setelah kejadian dibuat. Inilah cara termudah untuk mendapatkan ID kejadian. Anda akan sering
    571 memerlukan ID kejadian untuk melakukan operasi kalender lainnya&mdash;misalnya, untuk menambahkan
    572 peserta atau pengingat ke kejadian.</p>
    573 
    574 
    575 <h3 id="update-event">Memperbarui Kejadian</h3>
    576 
    577 <p>Bila aplikasi Anda ingin memperbolehkan pengguna mengedit kejadian, sebaiknya
    578 gunakan Intent {@link android.content.Intent#ACTION_EDIT EDIT}, seperti
    579 dijelaskan dalam <a href="#intent-edit">Menggunakan intent untuk mengedit kejadian</a>.
    580 Akan tetapi, jika perlu, Anda bisa mengedit kejadian secara langsung. Untuk melakukan pembaruan
    581 suatu kejadian, Anda bisa memberikan <code>_ID</code> 
    582 kejadian itu sebagai ID yang ditambahkan ke URI ({@link
    583 android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 
    584 atau sebagai item pemilihan pertama. 
    585 Pemilihan harus dimulai dengan <code>&quot;_id=?&quot;</code>, dan
    586 <code>selectionArg</code> yang pertama harus berupa <code>_ID</code> kejadian. Anda juga bisa
    587 melakukan pembaruan dengan menggunakan pemilihan tanpa ID. Berikut ini adalah contoh pembaruan
    588 kejadian. Contoh ini mengubah judul kejadian dengan pendekatan 
    589 {@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}
    590 :</p>
    591 
    592 
    593 <pre>private static final String DEBUG_TAG = "MyActivity";
    594 ...
    595 long eventID = 188;
    596 ...
    597 ContentResolver cr = getContentResolver();
    598 ContentValues values = new ContentValues();
    599 Uri updateUri = null;
    600 // The new title for the event
    601 values.put(Events.TITLE, &quot;Kickboxing&quot;); 
    602 updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
    603 int rows = getContentResolver().update(updateUri, values, null, null);
    604 Log.i(DEBUG_TAG, &quot;Rows updated: &quot; + rows);  </pre>
    605 
    606 <h3 id="delete-event">Menghapus Kejadian</h3>
    607 
    608 <p>Anda bisa menghapus kejadian dengan {@link
    609 android.provider.BaseColumns#_ID} sebagai ID yang ditambahkan pada URI, atau dengan
    610 pemilihan standar. Jika Anda menggunakan ID yang ditambahkan, Anda tidak bisa melakukan pemilihan.
    611 Ada dua versi penghapusan: sebagai aplikasi dan sebagai adaptor sinkronisasi. Penghapusan
    612 aplikasi mengatur kolom yang <em>dihapus</em> ke 1. Flag ini yang memberi tahu
    613 adaptor sinkronisasi bahwa baris telah dihapus dan bahwa penghapusan ini harus
    614 diberitahukan ke server. Penghapusan adaptor sinkronisasi menghapus kejadian dari
    615 database bersama semua data terkaitnya. Berikut ini adalah contoh aplikasi
    616 yang menghapus kejadian melalui {@link android.provider.BaseColumns#_ID}-nya:</p>
    617 
    618 
    619 <pre>private static final String DEBUG_TAG = "MyActivity";
    620 ...
    621 long eventID = 201;
    622 ...
    623 ContentResolver cr = getContentResolver();
    624 ContentValues values = new ContentValues();
    625 Uri deleteUri = null;
    626 deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
    627 int rows = getContentResolver().delete(deleteUri, null, null);
    628 Log.i(DEBUG_TAG, &quot;Rows deleted: &quot; + rows);  
    629 </pre>
    630 
    631 <h2 id="attendees">Tabel Peserta</h2>
    632 
    633 <p>Tiap baris tabel {@link android.provider.CalendarContract.Attendees}
    634 mewakili satu peserta atau tamu dari sebuah kejadian. Memanggil 
    635 {@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} 
    636 akan menghasilkan daftar peserta untuk
    637 kejadian dengan {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} yang diberikan. 
    638 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} ini 
    639 harus cocok dengan {@link
    640 android.provider.BaseColumns#_ID} kejadian tertentu.</p> 
    641 
    642 <p>Tabel berikut mencantumkan
    643 bidang-bidang yang bisa ditulis. Saat menyisipkan peserta baru, Anda harus menyertakan semuanya 
    644 kecuali <code>ATTENDEE_NAME</code>.
    645 </p>
    646 
    647 
    648 <table>
    649   <tr>
    650     <th>Konstanta</th>
    651     <th>Keterangan</th>
    652   </tr>
    653   <tr>
    654     <td>{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}</td>
    655     <td>ID kejadian.</td>
    656   </tr>
    657   <tr>
    658     <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_NAME}</td>
    659     <td>Nama peserta.</td>
    660   </tr>
    661   <tr>
    662     <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_EMAIL}</td>
    663     <td>Alamat email peserta.</td>
    664   </tr>
    665   <tr>
    666     <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_RELATIONSHIP}</td>
    667     <td><p>Hubungan peserta dengan kejadian. Salah satu dari:</p>
    668       <ul>
    669         <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_ATTENDEE}</li>
    670         <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_NONE}</li>
    671         <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_ORGANIZER}</li>
    672         <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_PERFORMER}</li>
    673         <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_SPEAKER}</li>
    674     </ul>
    675     </td>
    676   </tr>
    677   <tr>
    678     <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_TYPE}</td>
    679     <td><p>Tipe peserta. Salah satu dari: </p>
    680       <ul>
    681         <li>{@link android.provider.CalendarContract.AttendeesColumns#TYPE_REQUIRED}</li>
    682         <li>{@link android.provider.CalendarContract.AttendeesColumns#TYPE_OPTIONAL}</li>
    683     </ul></td>
    684   </tr>
    685   <tr>
    686     <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS}</td>
    687     <td><p>Status kehadiran peserta. Salah satu dari:</p>
    688       <ul>
    689         <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_ACCEPTED}</li>
    690         <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_DECLINED}</li>
    691         <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_INVITED}</li>
    692         <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_NONE}</li>
    693         <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_TENTATIVE}</li>
    694     </ul></td>
    695   </tr>
    696 </table>
    697 
    698 <h3 id="add-attendees">Menambahkan Peserta</h3>
    699 
    700 <p>Berikut ini adalah contoh yang menambahkan satu peserta ke kejadian. Perhatikan bahwa
    701 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 
    702 diperlukan:</p>
    703 
    704 <pre>
    705 long eventID = 202;
    706 ...
    707 ContentResolver cr = getContentResolver();
    708 ContentValues values = new ContentValues();
    709 values.put(Attendees.ATTENDEE_NAME, &quot;Trevor&quot;);
    710 values.put(Attendees.ATTENDEE_EMAIL, &quot;trevor (a] example.com&quot;);
    711 values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
    712 values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL);
    713 values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED);
    714 values.put(Attendees.EVENT_ID, eventID);
    715 Uri uri = cr.insert(Attendees.CONTENT_URI, values);
    716 </pre>
    717 
    718 <h2 id="reminders">Tabel Pengingat</h2>
    719 
    720 <p>Tiap baris tabel {@link android.provider.CalendarContract.Reminders}
    721 mewakili satu pengingat untuk sebuah kejadian. Memanggil 
    722 {@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} akan menghasilkan daftar pengingat untuk
    723 kejadian dengan 
    724 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} yang diberikan.</p>
    725 
    726 
    727 <p>Tabel berikut mencantumkan bidang-bidang yang bisa ditulis untuk pengingat. Semua bidang harus
    728 disertakan saat menyisipkan pengingat baru. Perhatikan bahwa adaptor sinkronisasi menetapkan
    729 tipe pengingat yang didukungnya dalam tabel {@link
    730 android.provider.CalendarContract.Calendars}. Lihat 
    731 {@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS} 
    732 untuk detailnya.</p>
    733 
    734 
    735 <table>
    736   <tr>
    737     <th>Konstanta</th>
    738     <th>Keterangan</th>
    739   </tr>
    740   <tr>
    741     <td>{@link android.provider.CalendarContract.RemindersColumns#EVENT_ID}</td>
    742     <td>ID kejadian.</td>
    743   </tr>
    744   <tr>
    745     <td>{@link android.provider.CalendarContract.RemindersColumns#MINUTES}</td>
    746     <td>Menit yang ditunggu untuk memicu kejadian pengingat.</td>
    747   </tr>
    748   <tr>
    749     <td>{@link android.provider.CalendarContract.RemindersColumns#METHOD}</td>
    750     <td><p>Metode alarm, seperti yang diatur pada server. Salah satu dari:</p>
    751       <ul>
    752         <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_ALERT}</li>
    753         <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_DEFAULT}</li>
    754         <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_EMAIL}</li>
    755         <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_SMS}</li>
    756     </ul></td>
    757   </tr>
    758 </table>
    759 
    760 <h3 id="add-reminders">Menambahkan Pengingat</h3>
    761 
    762 <p>Contoh ini menambahkan pengingat ke kejadian. Pengingat dipicu 15
    763 menit sebelum kejadian.</p>
    764 <pre>
    765 long eventID = 221;
    766 ...
    767 ContentResolver cr = getContentResolver();
    768 ContentValues values = new ContentValues();
    769 values.put(Reminders.MINUTES, 15);
    770 values.put(Reminders.EVENT_ID, eventID);
    771 values.put(Reminders.METHOD, Reminders.METHOD_ALERT);
    772 Uri uri = cr.insert(Reminders.CONTENT_URI, values);</pre>
    773 
    774 <h2 id="instances">Tabel Instances</h2>
    775 
    776 <p>Tabel 
    777 {@link android.provider.CalendarContract.Instances} menyimpan
    778 waktu mulai dan waktu selesai kejadian. Tiap baris dalam tabel ini
    779 mewakili satu bentuk kejadian. Tabel instance tidak bisa ditulis dan hanya
    780 menyediakan sebuah cara untuk membuat query kejadian. </p>
    781 
    782 <p>Tabel berikut mencantumkan beberapa bidang yang bisa Anda query untuk suatu instance. Perhatikan 
    783 bahwa zona waktu didefinisikan oleh 
    784 {@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} 
    785 dan 
    786 {@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_INSTANCES}.</p>
    787 
    788 
    789 <table>
    790   <tr>
    791     <th>Konstanta</th>
    792     <th>Keterangan</th>
    793   </tr>
    794   <tr>
    795     <td>{@link android.provider.CalendarContract.Instances#BEGIN}</td>
    796     <td>Waktu mulai instance, dalam milidetik UTC.</td>
    797   </tr>
    798   <tr>
    799     <td>{@link android.provider.CalendarContract.Instances#END}</td>
    800     <td>Waktu selesai instance, dalam milidetik UTC.</td>
    801   </tr>
    802   <tr>
    803     <td>{@link android.provider.CalendarContract.Instances#END_DAY}</td>
    804     
    805     <td>Hari selesai Julian dari instance, relatif terhadap
    806 zona waktu Kalender. 
    807     
    808 </td>
    809   </tr>
    810   <tr>
    811     <td>{@link android.provider.CalendarContract.Instances#END_MINUTE}</td>
    812     
    813     <td>Menit selesai dari instance yang diukur dari tengah malam di zona waktu
    814 Kalender.</td>
    815     
    816   </tr>
    817   <tr>
    818     <td>{@link android.provider.CalendarContract.Instances#EVENT_ID}</td>
    819     <td>Kejadian <code>_ID</code> untuk instance ini.</td>
    820   </tr>
    821     <tr>
    822     <td>{@link android.provider.CalendarContract.Instances#START_DAY}</td>
    823     <td>Hari mulai Julian dari instance, relatif terhadap zona waktu Kalender. 
    824  </td>
    825   </tr>
    826   <tr>
    827     <td>{@link android.provider.CalendarContract.Instances#START_MINUTE}</td>
    828     
    829     <td>Menit mulai dari instance yang diukur dari tengah malam, relatif terhadap
    830 zona waktu Kalender. 
    831 </td>
    832     
    833   </tr>
    834 
    835 </table>
    836 
    837 <h3 id="query-instances">Membuat query tabel Instance</h3>
    838 
    839 <p>Untuk membuat query tabel Instances, Anda perlu menetapkan rentang waktu query
    840 dalam URI. Dalam contoh ini, {@link android.provider.CalendarContract.Instances}
    841 mendapatkan akses ke bidang {@link
    842 android.provider.CalendarContract.EventsColumns#TITLE} melalui
    843 implementasi antarmuka {@link android.provider.CalendarContract.EventsColumns}-nya. 
    844 Dengan kata lain, {@link
    845 android.provider.CalendarContract.EventsColumns#TITLE} dihasilkan melalui
    846 tampilan database, bukan melalui query terhadap tabel {@link
    847 android.provider.CalendarContract.Instances} mentah.</p>
    848 
    849 <pre>
    850 private static final String DEBUG_TAG = "MyActivity";
    851 public static final String[] INSTANCE_PROJECTION = new String[] {
    852     Instances.EVENT_ID,      // 0
    853     Instances.BEGIN,         // 1
    854     Instances.TITLE          // 2
    855   };
    856   
    857 // The indices for the projection array above.
    858 private static final int PROJECTION_ID_INDEX = 0;
    859 private static final int PROJECTION_BEGIN_INDEX = 1;
    860 private static final int PROJECTION_TITLE_INDEX = 2;
    861 ...
    862 
    863 // Specify the date range you want to search for recurring
    864 // event instances
    865 Calendar beginTime = Calendar.getInstance();
    866 beginTime.set(2011, 9, 23, 8, 0);
    867 long startMillis = beginTime.getTimeInMillis();
    868 Calendar endTime = Calendar.getInstance();
    869 endTime.set(2011, 10, 24, 8, 0);
    870 long endMillis = endTime.getTimeInMillis();
    871   
    872 Cursor cur = null;
    873 ContentResolver cr = getContentResolver();
    874 
    875 // The ID of the recurring event whose instances you are searching
    876 // for in the Instances table
    877 String selection = Instances.EVENT_ID + " = ?";
    878 String[] selectionArgs = new String[] {"207"};
    879 
    880 // Construct the query with the desired date range.
    881 Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
    882 ContentUris.appendId(builder, startMillis);
    883 ContentUris.appendId(builder, endMillis);
    884 
    885 // Submit the query
    886 cur =  cr.query(builder.build(), 
    887     INSTANCE_PROJECTION, 
    888     selection, 
    889     selectionArgs, 
    890     null);
    891    
    892 while (cur.moveToNext()) {
    893     String title = null;
    894     long eventID = 0;
    895     long beginVal = 0;    
    896     
    897     // Get the field values
    898     eventID = cur.getLong(PROJECTION_ID_INDEX);
    899     beginVal = cur.getLong(PROJECTION_BEGIN_INDEX);
    900     title = cur.getString(PROJECTION_TITLE_INDEX);
    901               
    902     // Do something with the values. 
    903     Log.i(DEBUG_TAG, "Event:  " + title); 
    904     Calendar calendar = Calendar.getInstance();
    905     calendar.setTimeInMillis(beginVal);  
    906     DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
    907     Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime()));    
    908     }
    909  }</pre>
    910 
    911 <h2 id="intents">Intent Kalender</h2>
    912 <p>Aplikasi Anda tidak memerlukan <a href="#manifest">izin</a> untuk membaca dan menulis data kalender. Sebagai gantinya, aplikasi bisa menggunakan intent yang didukung oleh aplikasi Kalender Android untuk menyerahkan operasi baca dan tulis ke aplikasi itu. Tabel berikut mencantumkan intent yang didukung oleh Penyedia Kalender:</p>
    913 <table>
    914   <tr>
    915     <th>Tindakan</th>
    916     <th>URI</th>
    917 
    918     <th>Keterangan</th>
    919     <th>Ekstra</th>
    920   </tr>
    921   <tr>
    922     <td><br>
    923     {@link android.content.Intent#ACTION_VIEW VIEW} <br></td>
    924     <td><p><code>content://com.android.calendar/time/&lt;ms_since_epoch&gt;</code></p>
    925     Anda juga bisa mengacu ke URI dengan 
    926 {@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}. 
    927 Untuk contoh yang menggunakan intent ini, lihat <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-view">Menggunakan intent untuk menampilkan data kalender</a>. 
    928 
    929     </td>
    930     <td>Membuka kalender pada waktu yang ditetapkan oleh <code>&lt;ms_since_epoch&gt;</code>.</td>
    931     <td>Tidak ada.</td>
    932   </tr>
    933   <tr>
    934     <td><p>{@link android.content.Intent#ACTION_VIEW VIEW} </p>
    935 
    936      </td>
    937     <td><p><code>content://com.android.calendar/events/&lt;event_id&gt;</code></p>
    938     
    939     Anda juga bisa mengacu ke URI dengan 
    940 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}. 
    941 Untuk contoh yang menggunakan intent ini, lihat <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-view">Menggunakan intent untuk menampilkan data kalender</a>.
    942     
    943     </td>
    944     <td>Menampilkan kejadian yang ditetapkan oleh <code>&lt;event_id&gt;</code>.</td>
    945 
    946     <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME}<br>
    947       <br>
    948       <br>
    949     {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME}</td>
    950   </tr>
    951 
    952   <tr>
    953     <td>{@link android.content.Intent#ACTION_EDIT EDIT} </td>
    954     <td><p><code>content://com.android.calendar/events/&lt;event_id&gt;</code></p>
    955     
    956   Anda juga bisa mengacu ke URI dengan 
    957 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}. 
    958 Untuk contoh penggunaan intent ini, lihat <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-edit">Menggunakan intent untuk mengedit kejadian</a>.
    959     
    960     
    961     </td>
    962     <td>Mengedit kejadian yang ditetapkan oleh <code>&lt;event_id&gt;</code>.</td>
    963 
    964     <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME}<br>
    965       <br>
    966       <br>
    967     {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME}</td>
    968   </tr>
    969 
    970   <tr>
    971     <td>{@link android.content.Intent#ACTION_EDIT EDIT} <br>
    972     <br>
    973     {@link android.content.Intent#ACTION_INSERT INSERT} </td>
    974     <td><p><code>content://com.android.calendar/events</code></p>
    975     
    976    Anda juga bisa mengacu ke URI dengan 
    977 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}. 
    978 Untuk contoh penggunaan intent ini, lihat <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-insert">Menggunakan intent untuk menyisipkan kejadian</a>.
    979     
    980     </td>
    981 
    982     <td>Membuat sebuah kejadian.</td>
    983     <td>Ekstra apa saja yang tercantum dalam tabel di bawah.</td>
    984   </tr>
    985 </table>
    986 
    987 <p>Tabel berikut mencantumkan ekstra intent yang didukung oleh Penyedia Kalender:
    988 </p>
    989 <table>
    990   <tr>
    991     <th>Ekstra Intent</th>
    992     <th>Keterangan</th>
    993   </tr>
    994   <tr>
    995     <td>{@link android.provider.CalendarContract.EventsColumns#TITLE Events.TITLE}</td>
    996     <td>Nama kejadian.</td>
    997   </tr>
    998   <tr>
    999   
   1000     <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME
   1001 CalendarContract.EXTRA_EVENT_BEGIN_TIME}</td>
   1002     <td>Waktu mulai kejadian dalam milidetik sejak waktu patokan.</td>
   1003   </tr>
   1004   <tr>
   1005     <td>{@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME
   1006 CalendarContract.EXTRA_EVENT_END_TIME}</td>
   1007     
   1008     <td>Waktu selesai kejadian dalam milidetik sejak waktu patokan.</td>
   1009   </tr>
   1010   <tr>
   1011     <td>{@link android.provider.CalendarContract#EXTRA_EVENT_ALL_DAY
   1012 CalendarContract.EXTRA_EVENT_ALL_DAY}</td>
   1013     
   1014     <td>Sebuah boolean yang menunjukkan bahwa kejadian sehari penuh. Nilai bisa
   1015 <code>true</code> atau <code>false</code>.</td> </tr>
   1016   <tr>
   1017     <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION
   1018 Events.EVENT_LOCATION}</td>
   1019     
   1020     <td>Lokasi kejadian.</td>
   1021   </tr>
   1022   <tr>
   1023     <td>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION
   1024 Events.DESCRIPTION}</td>
   1025     
   1026     <td>Keterangan kejadian.</td>
   1027   </tr>
   1028   <tr>
   1029     <td>
   1030     {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}</td>
   1031     <td>Alamat email mereka yang harus diundang berupa daftar yang dipisahkan koma.</td>
   1032   </tr>
   1033   <tr>
   1034     <td>
   1035     {@link android.provider.CalendarContract.EventsColumns#RRULE Events.RRULE}</td>
   1036     <td>Aturan perulangan kejadian.</td>
   1037   </tr>
   1038   <tr>
   1039     <td>
   1040     {@link android.provider.CalendarContract.EventsColumns#ACCESS_LEVEL
   1041 Events.ACCESS_LEVEL}</td>
   1042     
   1043     <td>Apakah kejadian bersifat privat atau publik.</td>
   1044   </tr>
   1045   <tr>
   1046     <td>{@link android.provider.CalendarContract.EventsColumns#AVAILABILITY
   1047 Events.AVAILABILITY}</td>
   1048     
   1049     <td>Jika kejadian ini dihitung sebagai waktu sibuk atau waktu bebas yang bisa dijadwalkan.</td>
   1050     
   1051 </table> 
   1052 <p>Bagian berikut menjelaskan cara menggunakan semua intent ini.</p>
   1053 
   1054 
   1055 <h3 id="intent-insert">Menggunakan intent untuk menyisipkan kejadian</h3>
   1056 
   1057 <p>Penggunaan Intent {@link android.content.Intent#ACTION_INSERT INSERT}
   1058 akan memungkinkan aplikasi Anda menyerahkan tugas penyisipan kejadian ke Kalender itu sendiri.
   1059 Dengan pendekatan ini, aplikasi Anda bahkan tidak perlu menyertakan izin {@link
   1060 android.Manifest.permission#WRITE_CALENDAR} dalam <a href="#manifest">file manifesnya</a>.</p>
   1061 
   1062   
   1063 <p>Bila pengguna menjalankan aplikasi yang menggunakan pendekatan ini, aplikasi akan mengirim
   1064 izin ke Kalender untuk menyelesaikan penambahan kejadian. Intent {@link
   1065 android.content.Intent#ACTION_INSERT INSERT} menggunakan bidang-bidang ekstra
   1066 untuk mengisi formulir lebih dahulu dengan detail kejadian dalam Kalender. Pengguna nanti bisa
   1067 membatalkan kejadian, mengedit formulir sebagaimana diperlukan, atau menyimpan kejadian ke
   1068 kalender mereka.</p>
   1069   
   1070 
   1071 
   1072 <p>Berikut ini adalah cuplikan kode yang menjadwalkan kejadian pada tanggal 19 Januari 2012, yang berjalan
   1073 dari 7:30 pagi hingga 8:30 pagi Perhatikan hal-hal berikut tentang cuplikan kode ini:</p>
   1074 
   1075 <ul>
   1076   <li>Cuplikan kode ini menetapkan {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} 
   1077   sebagai URI-nya.</li>
   1078   
   1079   <li>Cuplikan kode ini menggunakan bidang-bidang ekstra {@link
   1080 android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME
   1081 CalendarContract.EXTRA_EVENT_BEGIN_TIME} dan {@link
   1082 android.provider.CalendarContract#EXTRA_EVENT_END_TIME
   1083 CalendarContract.EXTRA_EVENT_END_TIME} untuk mengisi dahulu formulir
   1084 dengan waktu kejadian. Nilai-nilai untuk waktu ini harus dalam milidetik UTC
   1085 sejak waktu patokan.</li>
   1086   
   1087   <li>Cuplikan kode ini menggunakan bidang ekstra {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}
   1088 untuk memberikan daftar undangan yang dipisah koma, yang ditetapkan melalui alamat email.</li>
   1089   
   1090 </ul>
   1091 <pre>
   1092 Calendar beginTime = Calendar.getInstance();
   1093 beginTime.set(2012, 0, 19, 7, 30);
   1094 Calendar endTime = Calendar.getInstance();
   1095 endTime.set(2012, 0, 19, 8, 30);
   1096 Intent intent = new Intent(Intent.ACTION_INSERT)
   1097         .setData(Events.CONTENT_URI)
   1098         .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis())
   1099         .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis())
   1100         .putExtra(Events.TITLE, &quot;Yoga&quot;)
   1101         .putExtra(Events.DESCRIPTION, &quot;Group class&quot;)
   1102         .putExtra(Events.EVENT_LOCATION, &quot;The gym&quot;)
   1103         .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY)
   1104         .putExtra(Intent.EXTRA_EMAIL, &quot;rowan (a] example.com,trevor (a] example.com&quot;);
   1105 startActivity(intent);
   1106 </pre>
   1107 
   1108 <h3 id="intent-edit">Menggunakan intent untuk mengedit kejadian</h3>
   1109 
   1110 <p>Anda bisa memperbarui kejadian secara langsung, seperti dijelaskan dalam <a href="#update-event">Memperbarui kejadian</a>. Namun penggunaan Intent {@link
   1111 android.content.Intent#ACTION_EDIT EDIT} memungkinkan aplikasi yang
   1112 tidak memiliki izin untuk menyerahkan pengeditan kejadian ke aplikasi Kalender.
   1113 Bila pengguna selesai mengedit kejadian dalam Kalender, pengguna akan dikembalikan ke
   1114 aplikasi semula.</p> <p>Berikut ini adalah contoh intent yang mengatur
   1115 judul baru bagi kejadian yang ditetapkan dan memungkinkan pengguna mengedit kejadian dalam Kalender.</p>
   1116 
   1117 
   1118 <pre>long eventID = 208;
   1119 Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
   1120 Intent intent = new Intent(Intent.ACTION_EDIT)
   1121     .setData(uri)
   1122     .putExtra(Events.TITLE, &quot;My New Title&quot;);
   1123 startActivity(intent);</pre>
   1124 
   1125 <h3 id="intent-view">Menggunakan intent untuk menampilkan data kalender</h3>
   1126 <p>Penyedia Kalender menyediakan dua cara menggunakan Intent {@link android.content.Intent#ACTION_VIEW VIEW}:</p>
   1127 <ul>
   1128   <li>Untuk membuka Kalender pada tanggal tertentu.</li>
   1129   <li>Untuk menampilkan sebuah kejadian.</li>
   1130 
   1131 </ul>
   1132 <p>Berikut ini adalah contoh yang menampilkan cara membuka Kalender pada tanggal tertentu:</p>
   1133 <pre>// A date-time specified in milliseconds since the epoch.
   1134 long startMillis;
   1135 ...
   1136 Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
   1137 builder.appendPath(&quot;time&quot;);
   1138 ContentUris.appendId(builder, startMillis);
   1139 Intent intent = new Intent(Intent.ACTION_VIEW)
   1140     .setData(builder.build());
   1141 startActivity(intent);</pre>
   1142 
   1143 <p>Berikut ini adalah contoh yang menampilkan cara membuka kejadian untuk menampilkan:</p>
   1144 <pre>long eventID = 208;
   1145 ...
   1146 Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
   1147 Intent intent = new Intent(Intent.ACTION_VIEW)
   1148    .setData(uri);
   1149 startActivity(intent);
   1150 </pre>
   1151 
   1152 
   1153 <h2 id="sync-adapter">Adaptor Sinkronisasi</h2>
   1154 
   1155 
   1156 <p>Hanya ada perbedaan kecil dalam cara aplikasi dan adaptor sinkronisasi
   1157 mengakses Penyedia Kalender:</p>
   1158 
   1159 <ul>
   1160   <li>Adaptor sinkronisasi perlu menetapkan bahwa dirinya sebuah adaptor sinkronisasi dengan mengatur {@link android.provider.CalendarContract#CALLER_IS_SYNCADAPTER} ke <code>true</code>.</li>
   1161   
   1162   
   1163   <li>Adaptor sinkronisasi perlu memberikan {@link
   1164 android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME} dan {@link
   1165 android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} sebagai parameter query dalam URI. </li>
   1166   
   1167   <li>Adaptor sinkronisasi memiliki akses tulis ke lebih banyak kolom daripada aplikasi atau widget.
   1168   Misalnya, aplikasi hanya bisa mengubah sedikit karakteristik kalender, 
   1169   misalnya nama, nama tampilan, pengaturan visibilitas, dan apakah kalender
   1170   disinkronkan atau tidak. Sebagai perbandingan, adaptor sinkronisasi bisa mengakses bukan hanya kolom-kolom itu, namun banyak kolom lainnya,
   1171   misalnya warna kalender, zona waktu, tingkat akses, lokasi, dan seterusnya.
   1172 Akan tetapi, adaptor sinkronisasi dibatasi pada <code>ACCOUNT_NAME</code> dan 
   1173 <code>ACCOUNT_TYPE</code> yang ditetapkannya.</li> </ul>
   1174 
   1175 <p>Berikut ini adalah metode pembantu yang bisa Anda gunakan untuk menghasilkan URI bagi penggunaan dengan adaptor sinkronisasi:</p>
   1176 <pre> static Uri asSyncAdapter(Uri uri, String account, String accountType) {
   1177     return uri.buildUpon()
   1178         .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,&quot;true&quot;)
   1179         .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
   1180         .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
   1181  }
   1182 </pre>
   1183 <p>Untuk contoh implementasi adaptor sinkronisasi (yang tidak terkait secara khusus dengan Kalender), lihat 
   1184 <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">SampleSyncAdapter</a>.
   1185