diff options
author | Dirk Dougherty <ddougherty@google.com> | 2016-09-22 10:21:29 -0700 |
---|---|---|
committer | Dirk Dougherty <ddougherty@google.com> | 2016-09-22 10:21:29 -0700 |
commit | 9bbc0a2421f54cebb9ee55197d87aae2f4b366d1 (patch) | |
tree | 11cb819a72c07ee7b342f72f247752a9748ddd28 /docs/html-intl/intl/id/guide/components | |
parent | 8b05feb5b4f4a2ca44eaf3b66c416d17e66308fb (diff) |
Copy IN files to ID, temporarily leaving IN in place.
Change-Id: I1a92e4254fe57817cb555629059539aaec47e182
Diffstat (limited to 'docs/html-intl/intl/id/guide/components')
-rw-r--r-- | docs/html-intl/intl/id/guide/components/activities.jd | 756 | ||||
-rw-r--r-- | docs/html-intl/intl/id/guide/components/bound-services.jd | 658 | ||||
-rw-r--r-- | docs/html-intl/intl/id/guide/components/fragments.jd | 812 | ||||
-rw-r--r-- | docs/html-intl/intl/id/guide/components/fundamentals.jd | 480 | ||||
-rw-r--r-- | docs/html-intl/intl/id/guide/components/index.jd | 57 | ||||
-rw-r--r-- | docs/html-intl/intl/id/guide/components/intents-filters.jd | 899 | ||||
-rw-r--r-- | docs/html-intl/intl/id/guide/components/loaders.jd | 494 | ||||
-rw-r--r-- | docs/html-intl/intl/id/guide/components/processes-and-threads.jd | 411 | ||||
-rw-r--r-- | docs/html-intl/intl/id/guide/components/recents.jd | 256 | ||||
-rw-r--r-- | docs/html-intl/intl/id/guide/components/services.jd | 813 | ||||
-rw-r--r-- | docs/html-intl/intl/id/guide/components/tasks-and-back-stack.jd | 578 |
11 files changed, 6214 insertions, 0 deletions
diff --git a/docs/html-intl/intl/id/guide/components/activities.jd b/docs/html-intl/intl/id/guide/components/activities.jd new file mode 100644 index 000000000000..bbc061cdc8cb --- /dev/null +++ b/docs/html-intl/intl/id/guide/components/activities.jd @@ -0,0 +1,756 @@ +page.title=Aktivitas +page.tags=aktivitas,intent +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> +<h2>Dalam dokumen ini</h2> +<ol> + <li><a href="#Creating">Membuat Aktivitas</a> + <ol> + <li><a href="#UI">Mengimplementasikan antarmuka pengguna</a></li> + <li><a href="#Declaring">Mendeklarasikan aktivitas dalam manifes</a></li> + </ol> + </li> + <li><a href="#StartingAnActivity">Memulai Aktivitas</a> + <ol> + <li><a href="#StartingAnActivityForResult">Memulai aktivitas agar berhasil</a></li> + </ol> + </li> + <li><a href="#ShuttingDown">Mematikan Aktivitas</a></li> + <li><a href="#Lifecycle">Mengelola Daur Hidup Aktivitas</a> + <ol> + <li><a href="#ImplementingLifecycleCallbacks">Mengimplementasikan callback daur hidup</a></li> + <li><a href="#SavingActivityState">Menyimpan status aktivitas</a></li> + <li><a href="#ConfigurationChanges">Menangani perubahan konfigurasi</a></li> + <li><a href="#CoordinatingActivities">Mengoordinasikan aktivitas</a></li> + </ol> + </li> +</ol> + +<h2>Kelas-kelas utama</h2> +<ol> + <li>{@link android.app.Activity}</li> +</ol> + +<h2>Lihat juga</h2> +<ol> + <li><a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tugas dan +Back-Stack</a></li> +</ol> + +</div> +</div> + + + +<p>{@link android.app.Activity} adalah sebuah komponen aplikasi yang menyediakan layar yang digunakan +pengguna untuk berinteraksi guna melakukan sesuatu, misalnya memilih nomor telepon, mengambil foto, mengirim email, atau +menampilkan peta. Tiap aktivitas diberi sebuah jendela untuk menggambar antarmuka penggunanya. Jendela ini +biasanya mengisi layar, namun mungkin lebih kecil daripada layar dan mengambang di atas +jendela lain.</p> + +<p> Sebuah aplikasi biasanya terdiri atas beberapa aktivitas yang terikat secara longgar +satu sama lain. Biasanya, satu aktivitas dalam aplikasi ditetapkan sebagai aktivitas "utama", yang +ditampilkan kepada pengguna saat membuka aplikasi untuk pertama kali. Tiap +aktivitas kemudian bisa memulai aktivitas lain untuk melakukan berbagai tindakan. Tiap kali +aktivitas baru dimulai, aktivitas sebelumnya akan dihentikan, namun sistem mempertahankan aktivitas +dalam sebuah tumpukan ("back-stack"). Bila sebuah aktivitas baru dimulai, aktivitas itu akan didorong ke atas back-stack dan +mengambil fokus pengguna. Back-stack mematuhi mekanisme dasar tumpukan "masuk terakhir, keluar pertama", +jadi, bila pengguna selesai dengan aktivitas saat ini dan menekan tombol <em>Back</em>, aktivitas +akan dikeluarkan dari tumpukan (dan dimusnahkan) dan aktivitas sebelumnya akan dilanjutkan. (Back-stack +dibahas selengkapnya dalam dokumen <a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tugas +dan Back-Stack</a>.)</p> + +<p>Bila aktivitas dihentikan karena ada aktivitas baru yang dimulai, aktivitas lama akan diberi tahu tentang perubahan status ini +melalui metode callback daur hidupnya. +Ada beberapa metode callback yang mungkin diterima aktivitas, karena sebuah perubahan dalam +statusnya—apakah sistem sedang membuatnya, menghentikannya, melanjutkannya, atau menghapuskannya—dan +masing-masing callback memberi Anda kesempatan melakukan pekerjaan tertentu yang +sesuai untuk perubahan status itu. Misalnya, bila dihentikan, aktivitas Anda harus melepas +objek besar, seperti koneksi jaringan atau database. Bila aktivitas dilanjutkan, Anda bisa +memperoleh kembali sumber daya yang diperlukan dan melanjutkan tindakan yang terputus. Transisi status ini +semuanya bagian dari daur hidup aktivitas.</p> + +<p>Bagian selebihnya dari dokumen ini membahas dasar-dasar cara membuat dan menggunakan aktivitas, +yang meliputi satu pembahasan lengkap tentang cara kerja daur hidup aktivitas, sehingga Anda bisa dengan benar mengelola +transisi di antara berbagai status aktivitas.</p> + + + +<h2 id="Creating">Membuat Aktivitas</h2> + +<p>Untuk membuat sebuah aktivitas, Anda harus membuat subkelas {@link android.app.Activity} (atau +subkelasnya yang ada). Dalam subkelas itu, Anda perlu mengimplementasikan metode-metode callback yang +dipanggil sistem saat aktivitas bertransisi di antara berbagai status daur hidupnya, misalnya saat +aktivitas sedang dibuat, dihentikan, dilanjutkan, atau dimusnahkan. Dua metode callback +terpenting adalah:</p> + +<dl> + <dt>{@link android.app.Activity#onCreate onCreate()}</dt> + <dd>Anda harus mengimplementasikan metode ini. Sistem memanggilnya saat membuat + aktivitas Anda. Dalam implementasi, Anda harus menginisialisasi komponen-komponen esensial +aktivitas. + Yang terpenting, inilah tempat Anda harus memanggil {@link android.app.Activity#setContentView + setContentView()} untuk mendefinisikan layout untuk antarmuka pengguna aktivitas.</dd> + <dt>{@link android.app.Activity#onPause onPause()}</dt> + <dd>Sistem memanggil metode ini sebagai pertanda pertama bahwa pengguna sedang meninggalkan +aktivitas Anda (walau itu tidak selalu berarti aktivitas sedang dimusnahkan). Inilah biasanya tempat Anda +harus mengikat setiap perubahan yang harus dipertahankan selepas sesi pengguna saat ini (karena +pengguna mungkin tidak kembali).</dd> +</dl> + +<p>Ada beberapa metode callback daur hidup lainnya yang harus Anda gunakan untuk memberikan +pengalaman pengguna yang mengalir di antara aktivitas dan menangani interupsi tidak terduga yang menyebabkan aktivitas Anda +dihentikan dan bahkan dimusnahkan. Semua metode callback daur hidup akan dibahas nanti, di +bagian tentang <a href="#Lifecycle">Mengelola Daur Hidup Aktivitas</a>.</p> + + + +<h3 id="UI">Mengimplementasikan antarmuka pengguna</h3> + +<p> Antarmuka pengguna aktivitas disediakan oleh hierarki objek—tampilan yang diturunkan +dari kelas {@link android.view.View}. Tiap tampilan mengontrol sebuah ruang persegi panjang tertentu +dalam jendela aktivitas dan bisa merespons interaksi pengguna. Misalnya, sebuah tampilan mungkin berupa sebuah +tombol yang mengawali suatu tindakan bila pengguna menyentuhnya.</p> + +<p>Android menyediakan sejumlah tampilan siap-dibuat yang bisa Anda gunakan untuk mendesain dan mengatur +layout. "Widget" adalah tampilan yang menyediakan elemen-elemen visual (dan interaktif) untuk layar, +misalnya tombol, bidang teks, kotak cek, atau sekadar sebuah gambar. "Layout" adalah tampilan yang diturunkan dari {@link +android.view.ViewGroup} yang memberikan sebuah model layout unik untuk tampilan anaknya, misalnya +layout linier, layout grid, atau layout relatif. Anda juga bisa mensubkelaskan kelas-kelas {@link android.view.View} dan +{@link android.view.ViewGroup} (atau subkelas yang ada) untuk membuat widget dan +layout Anda sendiri dan menerapkannya ke layout aktivitas Anda.</p> + +<p>Cara paling umum untuk mendefinisikan layout dengan menggunakan tampilan adalah dengan file layout XML yang disimpan dalam +sumber daya aplikasi Anda. Dengan cara ini, Anda bisa memelihara desain antarmuka pengguna Anda secara terpisah dari +kode yang mendefinisikan perilaku aktivitas. Anda bisa mengatur layout sebagai UI +aktivitas Anda dengan {@link android.app.Activity#setContentView(int) setContentView()}, dengan meneruskan +ID sumber daya untuk layout itu. Akan tetapi, Anda juga bisa membuat {@link android.view.View} baru dalam +kode aktivitas dan membuat hierarki tampilan dengan menyisipkan {@link +android.view.View} baru ke dalam {@link android.view.ViewGroup}, kemudian menggunakan layout itu dengan meneruskan akar +{@link android.view.ViewGroup} ke {@link android.app.Activity#setContentView(View) +setContentView()}.</p> + +<p>Untuk informasi tentang cara membuat antarmuka pengguna, lihat dokumentasi <a href="{@docRoot}guide/topics/ui/index.html">Antarmuka Pengguna</a>.</p> + + + +<h3 id="Declaring">Mendeklarasikan aktivitas dalam manifes</h3> + +<p>Anda harus mendeklarasikan aktivitas dalam file manifes agar file itu +bisa diakses oleh sistem. Untuk mendeklarasikan aktivitas, bukalah file manifes Anda dan tambahkan sebuah elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> +sebagai anak elemen <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a> +. Misalnya:</p> + +<pre> +<manifest ... > + <application ... > + <activity android:name=".ExampleActivity" /> + ... + </application ... > + ... +</manifest > +</pre> + +<p>Ada beberapa atribut lain yang bisa Anda sertakan dalam elemen ini, untuk mendefinisikan properti +misalnya label untuk aktivitas, ikon untuk aktivitas, atau tema untuk memberi gaya ke +UI aktivitas. Atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">{@code android:name}</a> + adalah satu-satunya atribut yang diperlukan—atribut ini menetapkan nama kelas aktivitas. Setelah +Anda mempublikasikan aplikasi, Anda tidak boleh mengubah nama ini, karena jika melakukannya, Anda bisa merusak +sebagian fungsionalitas, misalnya pintasan aplikasi (bacalah posting blog berjudul <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things +That Cannot Change</a>).</p> + +<p>Lihat acuan elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> +untuk informasi selengkapnya tentang cara mendeklarasikan aktivitas Anda dalam manifes.</p> + + +<h4>Menggunakan filter intent</h4> + +<p>Elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code +<activity>}</a> juga bisa menetapkan berbagai filter intent—dengan menggunakan elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code +<intent-filter>}</a> —untuk mendeklarasikan cara komponen aplikasi lain +mengaktifkannya.</p> + +<p>Bila Anda membuat aplikasi baru dengan Android SDK Tools, aktivitas stub +yang dibuat untuk Anda secara otomatis menyertakan filter intent yang mendeklarasikan respons +aktivitas pada tindakan "main" (utama) dan harus diletakkan dalam kategori "launcher"). Filter intent +terlihat seperti ini:</p> + +<pre> +<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> +</activity> +</pre> + +<p>Elemen <a href="{@docRoot}guide/topics/manifest/action-element.html">{@code +<action>}</a> menetapkan bahwa ini adalah titik masuk "main" ke aplikasi. Elemen <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code +<category>}</a> menetapkan bahwa aktivitas ini harus tercantum dalam launcher aplikasi +sistem (untuk memungkinkan pengguna meluncurkan aktivitas ini).</p> + +<p>Jika Anda bermaksud agar aplikasi dimuat dengan sendirinya dan tidak memperbolehkan aplikasi lain +mengaktifkan aktivitasnya, maka Anda tidak memerlukan filter intent lain. Hanya satu aktivitas yang boleh +memiliki tindakan "main" dan kategori "launcher", seperti dalam contoh sebelumnya. Aktivitas yang +tidak ingin Anda sediakan untuk aplikasi lain tidak boleh memiliki filter intent dan Anda bisa +memulai sendiri aktivitas dengan menggunakan intent secara eksplisit (seperti dibahas di bagian berikut).</p> + +<p>Akan tetapi, jika ingin aktivitas Anda merespons intent implisit yang dikirim dari +aplikasi lain (dan aplikasi Anda sendiri), maka Anda harus mendefinisikan filter intent tambahan untuk +aktivitas. Untuk masing-masing tipe intent yang ingin direspons, Anda harus menyertakan sebuah <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code +<intent-filter>}</a> yang menyertakan elemen +<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code +<action>}</a> dan, opsional, sebuah elemen <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code +<category>}</a> dan/atau elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code +<data>}</a>. Elemen-elemen ini menetapkan tipe intent yang bisa +direspons oleh aktivitas Anda.</p> + +<p>Untuk informasi selengkapnya tentang cara aktivitas Anda merespons intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>. +</p> + + + +<h2 id="StartingAnActivity">Memulai Aktivitas</h2> + +<p>Anda bisa memulai aktivitas lain dengan memanggil {@link android.app.Activity#startActivity + startActivity()}, dengan meneruskan sebuah {@link android.content.Intent} yang menjelaskan aktivitas + yang ingin Anda mulai. Intent menetapkan aktivitas persis yang ingin Anda mulai atau menjelaskan + tipe tindakan yang ingin Anda lakukan (dan sistem akan memilih aktivitas yang sesuai untuk Anda, +yang bahkan + bisa berasal dari aplikasi berbeda). Intent juga bisa membawa sejumlah kecil data untuk + digunakan oleh aktivitas yang dimulai.</p> + +<p>Saat bekerja dalam aplikasi sendiri, Anda nanti akan sering meluncurkan aktivitas yang dikenal saja. + Anda bisa melakukannya dengan membuat intent yang mendefinisikan secara eksplisit aktivitas yang ingin Anda mulai, +dengan menggunakan nama kelas. Misalnya, beginilah cara satu aktivitas memulai aktivitas lain bernama {@code +SignInActivity}:</p> + +<pre> +Intent intent = new Intent(this, SignInActivity.class); +startActivity(intent); +</pre> + +<p>Akan tetapi, aplikasi Anda mungkin juga perlu melakukan beberapa tindakan, misalnya mengirim email, + pesan teks, atau pembaruan status, dengan menggunakan data dari aktivitas Anda. Dalam hal ini, aplikasi Anda mungkin + tidak memiliki aktivitasnya sendiri untuk melakukan tindakan tersebut, sehingga Anda bisa memanfaatkan aktivitas + yang disediakan oleh aplikasi lain pada perangkat, yang bisa melakukan tindakan itu untuk Anda. Inilah saatnya +intent benar-benar berharga—Anda bisa membuat intent yang menjelaskan tindakan yang ingin +dilakukan dan sistem + akan meluncurkan aktivitas yang tepat dari aplikasi lain. Jika ada + beberapa aktivitas yang bisa menangani intent itu, pengguna bisa memilih aktivitas yang akan digunakan. Misalnya, + jika Anda ingin memperbolehkan pengguna mengirim pesan email, Anda bisa membuat + intent berikut:</p> + +<pre> +Intent intent = new Intent(Intent.ACTION_SEND); +intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); +startActivity(intent); +</pre> + +<p>Ekstra {@link android.content.Intent#EXTRA_EMAIL} yang ditambahkan ke intent adalah sebuah larik string + alamat email yang menjadi tujuan pengiriman email. Bila aplikasi email merespons intent ini, + aplikasi itu akan membaca larik string yang disediakan dalam ekstra dan meletakkannya dalam bidang "to" + pada formulir penulisan email. Dalam situasi ini, aktivitas aplikasi email dimulai dan bila + pengguna selesai, aktivitas Anda akan dilanjutkan.</p> + + + + +<h3 id="StartingAnActivityForResult">Memulai aktivitas agar berhasil</h3> + +<p>Kadang-kadang, Anda mungkin ingin menerima hasil dari aktivitas yang Anda mulai. Dalam hal itu, + mulailah aktivitas dengan memanggil {@link android.app.Activity#startActivityForResult + startActivityForResult()} (sebagai ganti {@link android.app.Activity#startActivity + startActivity()}). Untuk menerima hasil dari +aktivitas selanjutnya nanti, implementasikan metode callback {@link android.app.Activity#onActivityResult onActivityResult()} +. Bila aktivitas selanjutnya selesai, aktivitas akan mengembalikan hasil dalam {@link +android.content.Intent} kepada metode {@link android.app.Activity#onActivityResult onActivityResult()} +Anda.</p> + +<p>Misalnya, mungkin Anda ingin pengguna mengambil salah satu kontaknya, sehingga aktivitas Anda bisa +melakukan sesuatu dengan informasi dalam kontak itu. Begini caranya membuat intent tersebut dan +menangani hasilnya:</p> + +<pre> +private void pickContact() { + // Create an intent to "pick" a contact, as defined by the content provider URI + Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); + startActivityForResult(intent, PICK_CONTACT_REQUEST); +} + +@Override +protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // If the request went well (OK) and the request was PICK_CONTACT_REQUEST + if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) { + // Perform a query to the contact's content provider for the contact's name + Cursor cursor = getContentResolver().query(data.getData(), + new String[] {Contacts.DISPLAY_NAME}, null, null, null); + if (cursor.moveToFirst()) { // True if the cursor is not empty + int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME); + String name = cursor.getString(columnIndex); + // Do something with the selected contact's name... + } + } +} +</pre> + +<p>Contoh ini menunjukkan logika dasar yang harus Anda gunakan dalam metode {@link +android.app.Activity#onActivityResult onActivityResult()} Anda untuk menangani +hasil aktivitas. Syarat pertama memeriksa apakah permintaan berhasil—jika ya, maka + {@code resultCode} akan berupa {@link android.app.Activity#RESULT_OK}—dan apakah permintaan +yang direspons hasil ini dikenal—dalam hal ini, {@code requestCode} cocok dengan +parameter kedua yang dikirim dengan {@link android.app.Activity#startActivityForResult +startActivityForResult()}. Dari sana, kode akan menangani hasil aktivitas dengan membuat query +data yang dihasilkan dalam{@link android.content.Intent} (parameter {@code data}).</p> + +<p>Yang terjadi adalah {@link +android.content.ContentResolver} melakukan query terhadap penyedia konten, yang menghasilkan +{@link android.database.Cursor} yang memperbolehkan data query dibaca. Untuk informasi selengkapnya, lihat dokumen +<a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p> + +<p>Untuk informasi selengkapnya tentang menggunakan intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter +Intent</a>.</p> + + +<h2 id="ShuttingDown">Mematikan Aktivitas</h2> + +<p>Anda bisa mematikan aktivitas dengan memanggil metode {@link android.app.Activity#finish +finish()}-nya. Anda juga bisa mematikan aktivitas terpisah yang sebelumnya Anda mulai dengan memanggil +{@link android.app.Activity#finishActivity finishActivity()}.</p> + +<p class="note"><strong>Catatan:</strong> Pada umumnya, Anda tidak boleh secara eksplisit mengakhiri aktivitas +dengan menggunakan metode-metode ini. Seperti yang dibahas di bagian berikut tentang daur hidup aktivitas, +sistem Android mengelola hidup aktivitas untuk Anda, sehingga Anda tidak perlu menyelesaikan sendiri +aktivitas tersebut. Memanggil metode-metode ini bisa berpengaruh negatif pada pengalaman +pengguna yang diharapkan dan hanya boleh digunakan bila Anda benar-benar tidak ingin pengguna kembali ke +instance aktivitas ini.</p> + + +<h2 id="Lifecycle">Mengelola Daur Hidup Aktivitas</h2> + +<p>Mengelola daur hidup aktivitas dengan mengimplementasikan metode-metode callback sangat +penting untuk mengembangkan +aplikasi yang kuat dan fleksibel. Daur hidup aktivitas dipengaruhi langsung oleh kaitannya dengan +aktivitas lain, tugasnya, serta back-stack.</p> + +<p>Pada dasarnya, sebuah aktivitas bisa berada dalam tiga status:</p> + +<dl> + <dt><i>Dilanjutkan</i></dt> + <dd>Aktivitas berada di latar depan layar dan mendapatkan fokus pengguna. (Status ini +kadang-kadang disebut juga dengan "running" (berjalan).)</dd> + + <dt><i>Dihentikan sementara</i></dt> + <dd>Aktivitas lain berada di latar depan dan mendapat fokus, namun aktivitas ini masih terlihat. Yakni, +aktivitas lain terlihat di atas aplikasi ini dan aktivitas itu setengah transparan atau tidak +menuutpi seluruh layar. Aktivitas yang dihentikan sementara adalah benar-benar hidup (objek {@link android.app.Activity} +dipertahankan dalam memori, objek itu memelihara semua informasi status dan anggota, dan tetap dikaitkan dengan +window manager), namun bisa dimatikan oleh sistem dalam situasi memori sangat rendah.</dd> + + <dt><i>Dihentikan</i></dt> + <dd>Aktivitas ditutupi sepenuhnya oleh aktivitas lain (aktivitas sekarang berada di +"latar belakang"). Aktivitas yang dihentikan juga masih hidup (objek {@link android.app.Activity} +dipertahankan dalam memori, objek itu menjaga semua informasi status dan anggota, namun <em>tidak</em> +dikaitkan dengan window manager). Akan tetapi, aktivitas tidak lagi terlihat bagi pengguna dan +bisa dimatikan oleh sistem bila memori diperlukan di lain.</dd> +</dl> + +<p>Jika aktivitas dihentikan sementara atau dihentikan, sistem bisa mengeluarkannya dari memori baik dengan memintanya agar +diakhiri (memanggil metode {@link android.app.Activity#finish finish()}-nya), atau sekadar mematikan +prosesnya. Bila dibuka lagi (setelah diakhiri atau dimatikan), aktivitas harus dibuat dari +awal.</p> + + + +<h3 id="ImplementingLifecycleCallbacks">Mengimplementasikan callback daur hidup</h3> + +<p>Saat bertransisi ke dalam dan ke luar berbagai status yang dijelaskan di atas, aktivitas diberi tahu +melalui berbagai metode callback. Semua metode callback adalah sangkutan yang +bisa Anda kesampingkan untuk melakukan pekerjaan yang sesuai saat status aktivitas Anda berubah. Aktivitas skeleton +berikut menyertakan setiap metode daur hidup mendasar:</p> + + +<pre> +public class ExampleActivity extends Activity { + @Override + public void {@link android.app.Activity#onCreate onCreate}(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // The activity is being created. + } + @Override + protected void {@link android.app.Activity#onStart onStart()} { + super.onStart(); + // The activity is about to become visible. + } + @Override + protected void {@link android.app.Activity#onResume onResume()} { + super.onResume(); + // The activity has become visible (it is now "resumed"). + } + @Override + protected void {@link android.app.Activity#onPause onPause()} { + super.onPause(); + // Another activity is taking focus (this activity is about to be "paused"). + } + @Override + protected void {@link android.app.Activity#onStop onStop()} { + super.onStop(); + // The activity is no longer visible (it is now "stopped") + } + @Override + protected void {@link android.app.Activity#onDestroy onDestroy()} { + super.onDestroy(); + // The activity is about to be destroyed. + } +} +</pre> + +<p class="note"><strong>Catatan:</strong> Implementasi Anda terhadap metode-metode daur hidup ini harus +selalu memanggil implementasi superkelas sebelum melakukan pekerjaan apa pun, seperti yang ditampilkan dalam contoh-contoh di atas.</p> + +<p>Bersama-sama, semua metode ini mendefinisikan seluruh daur hidup sebuah aktivitas. Dengan mengimplementasikan +metode-metode ini, Anda bisa memantau tiga loop tersarang (nested loop) dalam daur hidup aktivitas: </p> + +<ul> +<li><b>Seluruh masa hidup</b> aktivitas berlangsung antara panggilan ke {@link +android.app.Activity#onCreate onCreate()} dan panggilan ke {@link +android.app.Activity#onDestroy}. Aktivitas Anda harus melakukan penyiapan +status "global" (misalnya mendefinisikan layout) dalam {@link android.app.Activity#onCreate onCreate()}, dan +melepas semua sisa sumber daya dalam {@link android.app.Activity#onDestroy}. Misalnya, jika +aktivitas Anda memiliki sebuah thread yang berjalan di latar belakang untuk mengunduh data dari jaringan, aktivitas itu bisa membuat +thread itu dalam {@link android.app.Activity#onCreate onCreate()} kemudian menghentikan thread dalam {@link +android.app.Activity#onDestroy}.</li> + +<li><p><b>Masa pakai terlihat</b> (visible lifetime) aktivitas berlangsung antara panggilan ke {@link +android.app.Activity#onStart onStart()} dan panggilan ke {@link +android.app.Activity#onStop onStop()}. Selama ini, pengguna bisa melihat aktivitas +pada layar dan berinteraksi dengannya. Misalnya, {@link android.app.Activity#onStop onStop()} dipanggil +bila sebuah aktivitas baru dimulai dan aktivitas ini tidak lagi terlihat. Di antara dua metode ini, Anda bisa +memelihara sumber daya yang diperlukan untuk menampilkan aktivitas kepada pengguna. Misalnya, Anda bisa mendaftarkan sebuah +{@link android.content.BroadcastReceiver} dalam {@link +android.app.Activity#onStart onStart()} untuk memantau perubahan yang berdampak pada UI Anda, dan mencabut pendaftarannya +dalam {@link android.app.Activity#onStop onStop()} bila pengguna tidak bisa lagi melihat apa yang sedang Anda +tampilkan. Sistem bisa memanggil {@link android.app.Activity#onStart onStart()} dan {@link +android.app.Activity#onStop onStop()} beberapa kali selama masa pakai aktivitas, sambil +aktivitas berganti-ganti antara terlihat dan tersembunyi bagi pengguna.</p></li> + +<li><p><b>Masa pakai latar depan</b> aktivitas berlangsung antara panggilan ke {@link +android.app.Activity#onResume onResume()} dan panggilan ke {@link android.app.Activity#onPause +onPause()}. Selama waktu ini, aktivitas berada di depan semua aktivitas lain pada layar dan mendapatkan +fokus input pengguna. Aktivitas bisa sering bertransisi ke dalam dan ke luar latar depan—misalnya, + {@link android.app.Activity#onPause onPause()} dipanggil bila perangkat masuk ke mode tidur atau +bila dialog muncul. Karena status ini bisa sering bertransisi, kode dalam dua metode ini harus +cukup ringan untuk menghindari transisi lamban yang membuat pengguna menunggu.</p></li> +</ul> + +<p>Gambar 1 mengilustrasikan loop dan path yang mungkin diambil sebuah aktivitas di antara status-status. +Persegi panjang mewakili metode callback yang bisa Anda implementasikan untuk melakukan operasi saat +aktivitas bertransisi di antara status. <p> + +<img src="{@docRoot}images/activity_lifecycle.png" alt="" /> +<p class="img-caption"><strong>Gambar 1.</strong> Daur hidup aktivitas.</p> + +<p>Metode-metode callback daur hidup yang sama tercantum dalam tabel 1, yang menjelaskan setiap metode callback +secara lebih detail dan menentukan lokasinya masing-masing dalam +daur hidup aktivitas keseluruhan, termasuk apakah sistem bisa mematikan aktivitas setelah +metode callback selesai.</p> + +<p class="table-caption"><strong>Tabel 1.</strong> Rangkuman metode callback +daur hidup aktivitas.</p> + +<table border="2" width="85%" frame="hsides" rules="rows"> +<colgroup align="left" span="3"></colgroup> +<colgroup align="left"></colgroup> +<colgroup align="center"></colgroup> +<colgroup align="center"></colgroup> + +<thead> +<tr><th colspan="3">Metode</th> <th>Keterangan</th> <th>Bisa dimatikan setelahnya?</th> <th>Berikutnya</th></tr> +</thead> + +<tbody> +<tr> + <td colspan="3" align="left"><code>{@link android.app.Activity#onCreate onCreate()}</code></td> + <td>Dipanggil saat aktivitas pertama kali dibuat. + Di sinilah Anda harus melakukan semua persiapan statis normal — + membuat tampilan, mengikat data ke daftar, dan sebagainya. Metode ini diberi + sebuah objek Bundle yang berisi status aktivitas sebelumnya, jika + status itu tertangkap (lihat <a href="#actstate">Menyimpan Status Aktivitas</a>, + nanti). + <p>Selalu diikuti oleh {@code onStart()}.</p></td> + <td align="center">Tidak</td> + <td align="center">{@code onStart()}</td> +</tr> + +<tr> + <td rowspan="5" style="border-left: none; border-right: none;"> </td> + <td colspan="2" align="left"><code>{@link android.app.Activity#onRestart +onRestart()}</code></td> + <td>Dipanggil setelah aktivitas dihentikan, tepat sebelum + dimulai lagi. + <p>Selalu diikuti oleh {@code onStart()}</p></td> + <td align="center">Tidak</td> + <td align="center">{@code onStart()}</td> +</tr> + +<tr> + <td colspan="2" align="left"><code>{@link android.app.Activity#onStart onStart()}</code></td> + <td>Dipanggil tepat sebelum aktivitas menjadi terlihat bagi pengguna. + <p>Diikuti oleh {@code onResume()} jika aktivitas maju + ke latar depan, atau {@code onStop()} jika menjadi tersembunyi.</p></td> + <td align="center">Tidak</td> + <td align="center">{@code onResume()} <br/>atau<br/> {@code onStop()}</td> +</tr> + +<tr> + <td rowspan="2" style="border-left: none;"> </td> + <td align="left"><code>{@link android.app.Activity#onResume onResume()}</code></td> + <td>Dipanggil tepat sebelum aktivitas mulai + berinteraksi dengan pengguna. Pada titik ini, aktivitas berada di + puncak tumpukan aktivitas, dengan input pengguna menuju kepadanya. + <p>Selalu diikuti oleh {@code onPause()}.</p></td> + <td align="center">Tidak</td> + <td align="center">{@code onPause()}</td> +</tr> + +<tr> + <td align="left"><code>{@link android.app.Activity#onPause onPause()}</code></td> + <td>Dipanggil bila sistem akan memulai pelanjutan + aktivitas lain. Metode ini biasanya digunakan untuk menerapkan (commit) perubahan yang tidak tersimpan pada + data persisten, menghentikan animasi dan hal-hal lain yang mungkin menghabiskan + CPU, dan sebagainya. Metode ini harus melakukan apa saja yang dilakukannya dengan sangat cepat, karena + aktivitas berikutnya tidak akan dilanjutkan hingga aktivitas ini kembali. + <p>Diikuti oleh {@code onResume()} jika aktivitas + kembali ke depan, atau oleh {@code onStop()} jika menjadi + tidak terlihat bagi pengguna.</td> + <td align="center"><strong style="color:#800000">Ya</strong></td> + <td align="center">{@code onResume()} <br/>atau<br/> {@code onStop()}</td> +</tr> + +<tr> + <td colspan="2" align="left"><code>{@link android.app.Activity#onStop onStop()}</code></td> + <td>Dipanggil bila aktivitas tidak lagi terlihat bagi pengguna. Hal ini + bisa terjadi karena aktivitas sedang dimusnahkan, atau karena aktivitas lain + (aktivitas yang ada atau yang baru) telah dilanjutkan dan sedang menutupinya. + <p>Diikuti oleh {@code onRestart()} jika + aktivitas kembali untuk berinteraksi dengan pengguna, atau oleh + {@code onDestroy()} jika aktivitas ini akan menghilang.</p></td> + <td align="center"><strong style="color:#800000">Ya</strong></td> + <td align="center">{@code onRestart()} <br/>atau<br/> {@code onDestroy()}</td> +</tr> + +<tr> + <td colspan="3" align="left"><code>{@link android.app.Activity#onDestroy +onDestroy()}</code></td> + <td>Dipanggil sebelum aktivitas dimusnahkan. Inilah panggilan terakhir + yang akan diterima aktivitas. Metode ini bisa dipanggil karena + aktivitas selesai (seseorang memanggil <code>{@link android.app.Activity#finish + finish()}</code> padanya), atau karena sistem memusnahkan sementara + instance aktivitas ini untuk menghemat tempat. Anda bisa membedakan + kedua skenario ini dengan metode <code>{@link + android.app.Activity#isFinishing isFinishing()}</code>.</td> + <td align="center"><strong style="color:#800000">Ya</strong></td> + <td align="center"><em>tidak ada</em></td> +</tr> +</tbody> +</table> + +<p>Kolom berlabel "Bisa dimatikan setelahnya?" menunjukkan apakah sistem bisa +atau tidak mematikan proses yang menjadi host aktivitas kapan saja <em>setelah metode kembali</em>, tanpa +menjalankan baris lain pada kode aktivitas. Tiga metode ini ditandai "ya": ({@link +android.app.Activity#onPause +onPause()}, {@link android.app.Activity#onStop onStop()}, dan {@link android.app.Activity#onDestroy +onDestroy()}). Karena {@link android.app.Activity#onPause onPause()} adalah yang pertama +dari tiga, begitu aktivitas dibuat, {@link android.app.Activity#onPause onPause()} adalah +metode terakhir yang dipastikan akan dipanggil sebelum proses <em>bisa</em> dimatikan—jika +sistem harus memulihkan memori dalam keadaan darurat, maka {@link +android.app.Activity#onStop onStop()} dan {@link android.app.Activity#onDestroy onDestroy()} mungkin +tidak dipanggil. Karena itu, Anda harus menggunakan {@link android.app.Activity#onPause onPause()} untuk menulis +data persisten yang penting (misalnya hasil edit pengguna) ke penyimpanan. Akan tetapi, Anda harus selektif dalam hal +informasi yang harus dipertahankan selama {@link android.app.Activity#onPause onPause()}, karena setiap +prosedur pemblokiran dalam metode ini akan memblokir transisi ke aktivitas berikutnya dan memperlambat +pengalaman pengguna.</p> + +<p> Metode-metode yang ditandai "Tidak" dalam kolom <b>Bisa dimatikan</b> melindungi proses yang menjadi host +aktivitas dari dimatikan sejak saat metode dipanggil. Jadi, aktivitas bisa dimatikan +sejak {@link android.app.Activity#onPause onPause()} kembali hingga waktu +{@link android.app.Activity#onResume onResume()} dipanggil. Aktivitas tidak akan lagi bisa dimatikan hingga +{@link android.app.Activity#onPause onPause()} dipanggil lagi dan kembali. </p> + +<p class="note"><strong>Catatan:</strong> Aktivitas yang tidak "bisa dimatikan" secara teknis oleh +definisi dalam tabel 1 masih bisa dimatikan oleh sistem—namun itu hany terjadi dalam +situasi ekstrem bila tidak ada jalan lain. Kapan aktivitas bisa dimatikan +akan dibahas selengkapnya dalam dokumen <a href="{@docRoot}guide/components/processes-and-threads.html">Proses dan +Threading</a>.</p> + + +<h3 id="SavingActivityState">Menyimpan status aktivitas</h3> + +<p>Pengantar untuk <a href="#Lifecycle">Mengelola Daur Hidup Aktivitas</a> secara ringkas menyebutkan +bahwa +bila aktivitas dihentikan sementara atau dihentikan, status aktivitas akan dipertahankan. Hal itu terjadi karena +objek {@link android.app.Activity} masih ditahan dalam memori saat aktivitas dihentikan sementara atau +dihentikan—semua informasi tentang anggota dan statusnya saat ini masih hidup. Jadi, setiap perubahan +yang dibuat pengguna dalam aktivitas akan dipertahankan sehingga bila aktivitas kembali ke +latar depan (bila "dilanjutkan"), perubahan itu masih ada.</p> + +<p>Akan tetapi, bila sistem memusnahkan aktivitas untuk memulihkan memori, objek {@link +android.app.Activity} akan dimusnahkan, sehingga sistem tidak bisa sekadar melanjutkan aktivitas dengan status +tidak berubah. Sebagai gantinya, sistem harus membuat ulang objek {@link android.app.Activity} jika pengguna +menyusuri kembali ke aktivitas tersebut. Namun, pengguna tidak menyadari +bahwa sistem memusnahkan aktivitas dan membuatnya kembali dan, karena itu, mungkin +mengharapkan aktivitas untuk sama persis dengan sebelumnya. Dalam situasi ini, Anda bisa memastikan bahwa +informasi penting tentang status aktivitas tetap terjaga dengan mengimplementasikan +metode callback tambahan yang memungkinkan Anda menyimpan informasi tentang status aktivitas: {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()}.</p> + +<p>Sistem memanggil {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()} +sebelum membuat aktivitas rawan terhadap pemusnahan. Sistem meneruskan ke metode ini +sebuah {@link android.os.Bundle} tempat Anda bisa menyimpan +informasi status tentang aktivitas sebagai pasangan nama-nilai, dengan menggunakan metode-metode misalnya {@link +android.os.Bundle#putString putString()} dan {@link +android.os.Bundle#putInt putInt()}. Kemudian, jika sistem mematikan proses aplikasi Anda +dan pengguna menyusuri kembali ke aktivitas tersebut, sistem akan membuat kembali aktivitas dan meneruskan +{@link android.os.Bundle} ke {@link android.app.Activity#onCreate onCreate()} maupun {@link +android.app.Activity#onRestoreInstanceState onRestoreInstanceState()}. Dengan menggunakan salah satu +metode ini, Anda bisa mengekstrak status tersimpan dari {@link android.os.Bundle} dan memulihkan +status aktivitas. Jika tidak ada informasi status untuk dipulihkan, maka {@link +android.os.Bundle} yang diteruskan kepada adalah Anda null (yang akan terjadi bila aktivitas dibuat untuk +pertama kali).</p> + +<img src="{@docRoot}images/fundamentals/restore_instance.png" alt="" /> +<p class="img-caption"><strong>Gambar 2.</strong> Ada dua cara yang bisa digunakan aktivitas untuk kembali ke fokus pengguna +dengan status tetap: aktivitas dimusnahkan, kemudian dibuat kembali, dan aktivitas harus memulihkan +status yang disimpan sebelumnya, atau aktivitas dihentikan, kemudian dilanjutkan dengan status aktivitas +tetap.</p> + +<p class="note"><strong>Catatan:</strong> Tidak ada jaminan bahwa {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()} akan dipanggil sebelum +aktivitas Anda dimusnahkan, karena bisa saja terjadi aktivitas tidak perlu menyimpan status +(misalnya saat pengguna meninggalkan aktivitas Anda dengan menggunakan tombol <em>Back</em>, karena pengguna menutup aktivitas +secara eksplisit +). Jika sistem memanggil {@link android.app.Activity#onSaveInstanceState +onSaveInstanceState()}, ini akan dilakukan sebelum {@link +android.app.Activity#onStop onStop()} dan mungkin sebelum {@link android.app.Activity#onPause +onPause()}.</p> + +<p>Akan tetapi, sekalipun Anda tidak melakukan apa-apa dan tidak mengimplementasikan {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()}, beberapa status aktivitas +akan dipulihkan oleh implementasi default {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()} dalam kelas {@link android.app.Activity}. Khususnya, +implementasi default akan memanggil metode {@link +android.view.View#onSaveInstanceState onSaveInstanceState()} yang sesuai untuk setiap {@link +android.view.View} dalam layout, yang memungkinkan setiap tampilan untuk memberi informasi tentang dirinya +yang harus disimpan. Hampir setiap widget dalam kerangka kerja Android mengimplementasikan metode ini +sebagaimana mestinya, sehingga setiap perubahan yang terlihat pada UI akan disimpan dan dipulihkan secara otomatis bila +aktivitas Anda dibuat kembali. Misalnya, widget {@link android.widget.EditText} menyimpan teks apa saja +yang dimasukkan oleh pengguna dan widget {@link android.widget.CheckBox} menyimpan baik teks itu diperiksa maupun +tidak. Satu-satunya pekerjaan yang Anda perlukan adalah memberikan ID unik (dengan atribut <a href="{@docRoot}guide/topics/resources/layout-resource.html#idvalue">{@code android:id}</a> +) untuk masing-masing widget yang ingin disimpan statusnya. Jika widget tidak memiliki ID, maka sistem +tidak bisa menyimpan statusnya.</p> + +<div class="sidebox-wrapper"> +<div class="sidebox"> +<p>Anda juga bisa menghentikan secara eksplisit sebuah tampilan dalam layout Anda agar tidak menyimpan statusnya dengan mengatur atribut +{@link android.R.attr#saveEnabled android:saveEnabled} ke {@code "false"} atau dengan memanggil +metode {@link android.view.View#setSaveEnabled setSaveEnabled()}. Biasanya, Anda tidak boleh +menonaktifkannya, namun Anda boleh melakukannya jika ingin memulihkan status UI aktivitas secara berbeda.</p> +</div> +</div> + +<p>Walaupun implementasi default {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()} menyimpan informasi yang berguna tentang +UI aktivitas, Anda mungkin masih perlu mengesampingkannya untuk menyimpan informasi tambahan. +Misalnya, Anda mungkin perlu menyimpan nilai-nilai anggota yang berubah selama masa pakai aktivitas (yang +mungkin berkorelasi dengan nilai-nilai yang dipulihkan dalam UI, namun anggota-anggota yang menyimpan nilai-nilai UI itu tidak +dipulihkan, secara default).</p> + +<p>Karena implementasi default {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()} membantu menyimpan status UI, jika +Anda mengesampingkan metode ini untuk menyimpan informasi tambahan status, Anda harus selalu memanggil +implementasi superkelas {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()} +sebelum melakukan pekerjaan apa pun. Demikian pula, Anda juga harus memanggil implementasi superkelas {@link +android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} jika Anda mengesampingkannya, sehingga +implementasi default bisa memulihkan status tampilan.</p> + +<p class="note"><strong>Catatan:</strong> Karena {@link android.app.Activity#onSaveInstanceState +onSaveInstanceState()} tidak dijamin +akan dipanggil, Anda harus menggunakannya hanya untuk mencatat status aktivitas sementara (transient) (status +UI)—Anda tidak boleh menggunakannya untuk menyimpan data persisten. Sebagai gantinya, Anda harus menggunakan {@link +android.app.Activity#onPause onPause()} untuk menyimpan data persisten (misalnya data yang harus disimpan +ke database) saat pengguna meninggalkan aktivitas.</p> + +<p>Salah satu cara yang baik untuk menguji kemampuan aplikasi dalam memulihkan statusnya adalah cukup dengan memutar +perangkat sehingga orientasi layarnya berubah. Bila orientasi layar berubah, sistem +akan memusnahkan dan membuat kembali aktivitas untuk menerapkan sumber daya alternatif yang mungkin tersedia +untuk konfigurasi layar baru. Karena alasan ini saja, sangat penting bahwa aktivitas Anda +memulihkan statusnya secara lengkap saat dibuat kembali, karena pengguna memutar layar secara rutin saat +menggunakan aplikasi.</p> + + +<h3 id="ConfigurationChanges">Menangani perubahan konfigurasi</h3> + +<p>Sebagian konfigurasi perangkat bisa berubah saat runtime (misalnya orientasi layar, ketersediaan keyboard +, dan bahasa). Bila terjadi perubahan demikian, Android akan membuat kembali aktivitas yang berjalan +(sistem akan memanggil {@link android.app.Activity#onDestroy}, kemudian segera memanggil {@link +android.app.Activity#onCreate onCreate()}). Perilaku ini +didesain untuk membantu aplikasi Anda menyesuaikan diri dengan konfigurasi baru dengan cara memuat ulang +aplikasi Anda secara otomatis dengan sumber daya alternatif yang telah Anda sediakan (misalnya layout yang berbeda untuk +layar orientasi dan ukuran yang berbeda).</p> + +<p>Jika Anda mendesain aktivitas dengan benar untuk menangani restart karena perubahan orientasi layar dan +memulihkan status aktivitas seperti yang dijelaskan di atas, aplikasi Anda akan lebih tahan terhadap +kejadian tidak terduga lainnya dalam daur hidup aktivitas.</p> + +<p>Cara terbaik menangani restart tersebut adalah + menyimpan dan memulihkan status aktivitas Anda dengan menggunakan {@link + android.app.Activity#onSaveInstanceState onSaveInstanceState()} dan {@link +android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} (atau {@link +android.app.Activity#onCreate onCreate()}), seperti yang dibahas di bagian sebelumnya.</p> + +<p>Untuk informasi selengkapnya tentang konfigurasi perubahan yang terjadi saat program berjalan dan cara menanganinya +, bacalah panduan untuk <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani +Perubahan Runtime</a>.</p> + + + +<h3 id="CoordinatingActivities">Mengoordinasikan aktivitas</h3> + + <p>Bila suatu aktivitas memulai aktivitas lain, keduanya akan mengalami transisi daur hidup. Aktivitas pertama +akan berhenti sementara dan berhenti sama sekali (walau tidak akan berhenti jika masih terlihat di latar belakang), saat +aktivitas lain dibuat. Jika aktivitas-aktivitas ini berbagi data yang disimpan ke disk atau di tempat lain, Anda perlu +memahami bahwa aktivitas pertama tidak dihentikan sepenuhnya sebelum aktivitas kedua dibuat. +Sebagai gantinya, proses akan memulai aktivitas kedua secara tumpang tindih dengan proses penghentian +aktivitas pertama.</p> + +<p>Urutan callback daur hidup didefinisikan dengan baik, khususnya bila kedua aktivitas berada dalam +proses yang sama dan salah satunya memulai yang lain. Berikut ini adalah urutan operasi yang terjadi bila Aktivitas +A memulai Aktivitas B: </p> + +<ol> +<li>Metode {@link android.app.Activity#onPause onPause()} Aktivitas A berjalan.</li> + +<li>Metode-metode {@link android.app.Activity#onCreate onCreate()}, {@link +android.app.Activity#onStart onStart()}, dan {@link android.app.Activity#onResume onResume()} +Aktivitas B berjalan secara berurutan. (Aktivitas B sekarang mendapatkan fokus pengguna.)</li> + +<li>Kemudian, jika Aktivitas A tidak lagi terlihat di layar, metode {@link +android.app.Activity#onStop onStop()}-nya akan dijalankan.</li> +</ol> + + <p>Urutan callback daur hidup yang bisa diramalkan ini memungkinkan Anda mengelola transisi +informasi dari satu aktivitas ke aktivitas lainnya. Misalnya, jika Anda harus menulis ke database saat +aktivitas pertama berhenti agar aktivitas berikutnya bisa membacanya, maka Anda harus menulis ke +database selama {@link android.app.Activity#onPause onPause()} sebagai ganti selama {@link +android.app.Activity#onStop onStop()}.</p> + +<!-- +<h2>Beginner's Path</h2> + +<p>For more information about how Android maintains a history of activities and +enables user multitasking, continue with the <b><a +href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back +Stack</a></b> document.</p> +--> diff --git a/docs/html-intl/intl/id/guide/components/bound-services.jd b/docs/html-intl/intl/id/guide/components/bound-services.jd new file mode 100644 index 000000000000..6e5e65a167e8 --- /dev/null +++ b/docs/html-intl/intl/id/guide/components/bound-services.jd @@ -0,0 +1,658 @@ +page.title=Layanan Terikat +parent.title=Layanan +parent.link=services.html +@jd:body + + +<div id="qv-wrapper"> +<ol id="qv"> +<h2>Dalam dokumen ini</h2> +<ol> + <li><a href="#Basics">Dasar-Dasar</a></li> + <li><a href="#Creating">Membuat Layanan Terikat</a> + <ol> + <li><a href="#Binder">Memperluas kelas Binder</a></li> + <li><a href="#Messenger">Menggunakan Messenger</a></li> + </ol> + </li> + <li><a href="#Binding">Mengikat ke Layanan</a></li> + <li><a href="#Lifecycle">Mengelola Daur Hidup Layanan Terikat</a></li> +</ol> + +<h2>Kelas-kelas utama</h2> +<ol> + <li>{@link android.app.Service}</li> + <li>{@link android.content.ServiceConnection}</li> + <li>{@link android.os.IBinder}</li> +</ol> + +<h2>Contoh</h2> +<ol> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code + RemoteService}</a></li> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code + LocalService}</a></li> +</ol> + +<h2>Lihat juga</h2> +<ol> + <li><a href="{@docRoot}guide/components/services.html">Layanan</a></li> +</ol> +</div> + + +<p>Layanan terikat adalah server di antarmuka klien-server. Layanan terikat memungkinkan komponen-komponen +(seperti aktivitas) untuk diikat ke layanan, mengirim permintaan, menerima respons, dan bahkan melakukan +komunikasi antarproses (IPC). Layanan terikat biasanya hidup hanya saat melayani +komponen aplikasi lain dan tidak berjalan di latar belakang terus-menerus.</p> + +<p>Dokumen ini menampilkan cara membuat layanan terikat, termasuk cara mengikat +ke layanan dari komponen aplikasi lain. Akan tetapi, Anda juga harus mengacu dokumen <a href="{@docRoot}guide/components/services.html">Layanan</a> untuk +informasi tambahan tentang layanan secara umum, seperti cara menyampaikan pemberitahuan dari layanan, mengatur +layanan agar berjalan di latar depan, dan lain-lain.</p> + + +<h2 id="Basics">Dasar-Dasar</h2> + +<p>Layanan terikat adalah implementasi kelas {@link android.app.Service} yang memungkinkan +aplikasi lain diikat padanya dan berinteraksi dengannya. Untuk menyediakan pengikatan bagi sebuah +layanan, Anda harus mengimplementasikan metode callback {@link android.app.Service#onBind onBind()}. Metode ini +menghasilkan objek {@link android.os.IBinder} yang mendefinisikan antarmuka pemprograman yang +bisa digunakan klien untuk berinteraksi dengan layanan.</p> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h3>Mengikat ke Layanan yang Sudah Dimulai</h3> + +<p>Seperti dibahas dalam dokumen <a href="{@docRoot}guide/components/services.html">Layanan</a> +, Anda bisa membuat layanan yang dimulai sekaligus diikat. Yakni, layanan bisa +dimulai dengan memanggil {@link android.content.Context#startService startService()}, yang memungkinkan +layanan berjalan terus-menerus, dan juga membolehkan klien untuk mengikat ke layanan dengan memanggil {@link +android.content.Context#bindService bindService()}. + <p>Jika Anda mengizinkan layanan dimulai dan diikat, lalu ketika layanan telah +dimulai, sistem <em>tidak</em> menghapus layanan ketika semua klien melepas ikatan. Sebagai gantinya, Anda harus +menghentikan layanan secara eksplisit, dengan memanggil {@link android.app.Service#stopSelf stopSelf()} atau {@link +android.content.Context#stopService stopService()}.</p> + +<p>Walaupun Anda biasanya harus mengimplementasikan {@link android.app.Service#onBind onBind()} +<em>atau</em> {@link android.app.Service#onStartCommand onStartCommand()}, kadang-kadang perlu +mengimplementasikan keduanya. Misalnya, sebuah pemutar musik bisa merasakan manfaatnya karena layanannya boleh berjalan +terus-menerus dan juga menyediakan pengikatan. Dengan cara ini, sebuah aktivitas bisa memulai layanan untuk memutar beberapa +lagu dan musik terus dimainkan sekalipun pengguna meninggalkan aplikasi. Lalu, bila pengguna +kembali ke aplikasi, aktivitas bisa mengikat ke layanan untuk mendapatkan kembali kontrol atas pemutaran.</p> + +<p>Pastikan membaca bagian tentang <a href="#Lifecycle">Mengelola Daur Hidup Layanan +Terikat</a>, untuk informasi selengkapnya tentang daur hidup layanan saat menambahkan pengikatan ke +layanan yang sudah dimulai.</p> +</div> +</div> + +<p>Klien bisa mengikat ke layanan dengan memanggil {@link android.content.Context#bindService +bindService()}. Bila itu dilakukan, klien harus menyediakan implementasi {@link +android.content.ServiceConnection}, yang memantau koneksi dengan layanan. Metode {@link +android.content.Context#bindService bindService()} kembali dengan serta-merta tanpa sebuah nilai, namun +bila sistem Android membuat koneksi antara klien +dan layanan, sistem akan memanggil {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} pada {@link +android.content.ServiceConnection} untuk mengirim {@link android.os.IBinder} yang +bisa digunakan klien untuk berkomunikasi dengan layanan.</p> + +<p>Beberapa klien bisa terhubung ke layanan dengan serentak. Akan tetapi, sistem akan memanggil metode +{@link android.app.Service#onBind onBind()} layanan Anda untuk mengambil {@link android.os.IBinder} hanya +bila klien pertama mengikat. Sistem lalu memberikan {@link android.os.IBinder} yang sama ke setiap +klien tambahan yang mengikat, tanpa memanggil {@link android.app.Service#onBind onBind()} lagi.</p> + +<p>Bila klien terakhir melepas ikatan dari layanan, sistem akan menghapus layanan (kecuali jika +layanan juga dimulai oleh {@link android.content.Context#startService startService()}).</p> + +<p>Bila Anda mengimplementasikan layanan terikat, yang terpenting adalah mendefinisikan antarmuka +yang dihasilkan metode callback {@link android.app.Service#onBind onBind()} Anda. Ada sedikit +cara mendefinisikan antarmuka {@link android.os.IBinder} layanan Anda dan bagian berikut +akan membahas masing-masing teknik.</p> + + + +<h2 id="Creating">Membuat Layanan Terikat</h2> + +<p>Saat membuat layanan yang menyediakan pengikatan, Anda harus menyediakan {@link android.os.IBinder} +yang menyediakan antarmuka pemrograman yang bisa digunakan klien untuk berinteraksi dengan layanan. Ada +tiga cara untuk mendefinisikan antarmuka:</p> + +<dl> + <dt><a href="#Binder">Memperluas kelas Binder</a></dt> + <dd>Jika layanan Anda bersifat privat untuk aplikasi Anda sendiri dan berjalan dalam proses yang sama dengan klien +(biasanya), Anda harus membuat antarmuka dengan memperluas kelas {@link android.os.Binder} +dan menghasilkan instance dari +{@link android.app.Service#onBind onBind()}. Klien akan menerima {@link android.os.Binder} dan +bisa menggunakannya untuk mengakses langsung metode publik yang tersedia dalam implementasi {@link android.os.Binder} +atau bahkan {@link android.app.Service}. + <p>Inilah teknik yang lebih disukai bila layanan Anda sekadar pekerja latar belakang untuk aplikasi Anda +sendiri. Satu-satunya alasan tidak membuat antarmuka dengan cara ini adalah karena +layanan Anda akan digunakan oleh aplikasi lain atau pada proses-proses terpisah.</dd> + + <dt><a href="#Messenger">Menggunakan Messenger</a></dt> + <dd>Jika antarmuka Anda perlu bekerja lintas proses, Anda bisa membuat +antarmuka untuk layanan dengan {@link android.os.Messenger}. Dengan cara ini, layanan +mendefinisikan {@link android.os.Handler} yang akan merespons aneka tipe objek {@link +android.os.Message}. {@link android.os.Handler} +ini adalah dasar bagi {@link android.os.Messenger} yang nanti bisa berbagi {@link android.os.IBinder} +dengan klien, sehingga memungkinkan klien mengirim perintah ke layanan dengan menggunakan objek {@link +android.os.Message}. Selain itu, klien bisa mendefinisikan sendiri {@link android.os.Messenger} +sehingga layanan bisa mengirim balik pesan. + <p>Inilah cara termudah melakukan komunikasi antarproses (IPC), karena {@link +android.os.Messenger} akan mengantre semua permintaan ke dalam satu thread sehingga Anda tidak perlu mendesain +layanan agar thread-safe.</p> + </dd> + + <dt>Menggunakan AIDL</dt> + <dd>AIDL (Android Interface Definition Language) melakukan semua pekerjaan untuk mengurai objek menjadi +primitif yang bisa dipahami dan diarahkan oleh sistem operasi ke berbagai proses untuk melakukan +IPC. Teknik sebelumnya, dengan menggunakan {@link android.os.Messenger}, sebenarnya berdasarkan AIDL sebagai +struktur yang mendasarinya. Seperti disebutkan di atas, {@link android.os.Messenger} membuat antrean +semua permintaan klien dalam satu thread, sehingga layanan akan menerima permintaan satu per satu. Akan tetapi, +jika ingin layanan Anda menangani beberapa permintaan sekaligus, Anda bisa menggunakan AIDL +secara langsung. Dalam hal ini, layanan Anda harus mampu multi-thread dan dibuat thread-safe. + <p>Untuk menggunakan AIDL secara langsung, Anda harus +membuat file {@code .aidl} yang mendefinisikan antarmuka pemrograman. Alat Android SDK menggunakan +file ini untuk menghasilkan kelas abstrak yang mengimplementasikan antarmuka dan menangani IPC, yang nanti +bisa Anda perluas dalam layanan.</p> + </dd> +</dl> + + <p class="note"><strong>Catatan:</strong> Umumnya aplikasi <strong>tidak boleh</strong> menggunakan AIDL untuk +membuat layanan terikat, karena hal itu mungkin memerlukan kemampuan multi-thread dan +bisa mengakibatkan implementasi yang lebih rumit. Dengan demikian, AIDL tidak cocok untuk sebagian besar aplikasi +dan dokumen ini tidak membahas cara menggunakannya untuk layanan Anda. Jika Anda yakin perlu +menggunakan AIDL secara langsung, lihat dokumen <a href="{@docRoot}guide/components/aidl.html">AIDL</a> +.</p> + + + + +<h3 id="Binder">Memperluas kelas Binder</h3> + +<p>Jika layanan Anda hanya digunakan oleh aplikasi lokal dan tidak perlu bekerja lintas proses, +maka Anda bisa mengimplementasikan kelas {@link android.os.Binder} Anda sendiri yang memberi klien Anda +akses langsung ke metode publik dalam layanan.</p> + +<p class="note"><strong>Catatan:</strong> Hal ini hanya berhasil jika klien dan layanan berada dalam +aplikasi dan proses yang sama, suatu kondisi yang paling umum. Misalnya, cara ini sangat cocok untuk sebuah aplikasi musik +yang perlu mengikat aktivitas ke layanannya sendiri, yakni memutar musik di +latar belakang.</p> + +<p>Berikut cara menyiapkannya:</p> +<ol> + <li>Dalam layanan Anda, buat sebuah instance {@link android.os.Binder} yang: + <ul> + <li>berisi metode publik yang bisa dipanggil klien</li> + <li>menghasilkan instance {@link android.app.Service} saat ini, yang memiliki metode publik yang +bisa dipanggil klien</li> + <li>atau, menghasilkan instance kelas lain yang host-nya di layanan dengan metode publik yang +bisa dipanggil klien</li> + </ul> + <li>Hasilkan instance {@link android.os.Binder} ini dari metode callback {@link +android.app.Service#onBind onBind()}.</li> + <li>Di klien, terima {@link android.os.Binder} dari metode callback {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} dan +buat panggilan ke layanan terikat dengan menggunakan metode yang disediakan.</li> +</ol> + +<p class="note"><strong>Catatan:</strong> Alasan layanan dan klien harus berada dalam aplikasi yang sama +adalah agar klien bisa mengkonversi objek yang dihasilkan dan memanggil API-nya dengan benar. Layanan +dan klien juga harus berada dalam proses yang sama, karena teknik ini tidak melakukan +pengarahan (marshalling) apa pun untuk lintas proses.</p> + +<p>Misalnya, berikut ini adalah layanan yang memberi klien akses ke metode-metode dalam layanan melalui +implementasi {@link android.os.Binder}:</p> + +<pre> +public class LocalService extends Service { + // Binder given to clients + private final IBinder mBinder = new LocalBinder(); + // Random number generator + private final Random mGenerator = new Random(); + + /** + * Class used for the client Binder. Because we know this service always + * runs in the same process as its clients, we don't need to deal with IPC. + */ + public class LocalBinder extends Binder { + LocalService getService() { + // Return this instance of LocalService so clients can call public methods + return LocalService.this; + } + } + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + /** method for clients */ + public int getRandomNumber() { + return mGenerator.nextInt(100); + } +} +</pre> + +<p>{@code LocalBinder} menyediakan {@code getService()} metode bagi klien untuk mengambil +instance {@code LocalService} saat ini. Cara ini memungkinkan klien memanggil metode publik dalam +layanan. Misalnya, klien bisa memanggil {@code getRandomNumber()} dari layanan.</p> + +<p>Berikut ini adalah aktivitas yang mengikat ke {@code LocalService} dan memanggil {@code getRandomNumber()} +bila tombol diklik:</p> + +<pre> +public class BindingActivity extends Activity { + LocalService mService; + boolean mBound = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + } + + @Override + protected void onStart() { + super.onStart(); + // Bind to LocalService + Intent intent = new Intent(this, LocalService.class); + bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } + + @Override + protected void onStop() { + super.onStop(); + // Unbind from the service + if (mBound) { + unbindService(mConnection); + mBound = false; + } + } + + /** Called when a button is clicked (the button in the layout file attaches to + * this method with the android:onClick attribute) */ + public void onButtonClick(View v) { + if (mBound) { + // Call a method from the LocalService. + // However, if this call were something that might hang, then this request should + // occur in a separate thread to avoid slowing down the activity performance. + int num = mService.getRandomNumber(); + Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); + } + } + + /** Defines callbacks for service binding, passed to bindService() */ + private ServiceConnection mConnection = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName className, + IBinder service) { + // We've bound to LocalService, cast the IBinder and get LocalService instance + LocalBinder binder = (LocalBinder) service; + mService = binder.getService(); + mBound = true; + } + + @Override + public void onServiceDisconnected(ComponentName arg0) { + mBound = false; + } + }; +} +</pre> + +<p>Contoh di atas menampilkan cara klien mengikat ke layanan dengan menggunakan implementasi +{@link android.content.ServiceConnection} dan callback {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()}. Bagian +berikut menyediakan informasi selengkapnya tentang proses pengikatan ke layanan.</p> + +<p class="note"><strong>Catatan:</strong> Contoh di atas tidak secara eksplisit melepas ikatan dari layanan, +namun semua klien harus melepas ikatan pada waktu yang tepat (seperti saat aktivitas sedang jeda).</p> + +<p>Untuk contoh kode selengkapnya, lihat kelas <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code +LocalService.java}</a> dan kelas <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">{@code +LocalServiceActivities.java}</a> dalam <a href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p> + + + + + +<h3 id="Messenger">Menggunakan Messenger</h3> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h4>Dibandingkan dengan AIDL</h4> + <p>Bila Anda perlu melakukan IPC, menggunakan {@link android.os.Messenger} untuk antarmuka +lebih sederhana daripada mengimplementasikannya dengan AIDL, karena {@link android.os.Messenger} mengantre +semua panggilan ke layanan, sementara antarmuka AIDL murni mengirim permintaan serentak ke +layanan, yang nanti harus menangani multi-threading.</p> + <p>Untuk sebagian besar aplikasi, layanan tidak perlu melakukan multi-threading, jadi dengan menggunakan {@link +android.os.Messenger} memungkinkan layanan menangani panggilan satu per satu. Jika +layanan harus multi-thread, Anda harus menggunakan <a href="{@docRoot}guide/components/aidl.html">AIDL</a> untuk mendefinisikan antarmuka.</p> +</div> +</div> + +<p>Jika layanan perlu berkomunikasi dengan proses jauh, Anda bisa menggunakan +{@link android.os.Messenger} untuk menyediakan antarmuka bagi layanan Anda. Teknik ini memungkinkan +Anda melakukan komunikasi antarproses (IPC) tanpa harus menggunakan AIDL.</p> + +<p>Berikut ini rangkuman cara menggunakan {@link android.os.Messenger}:</p> + +<ul> + <li>Layanan mengimplementasikan {@link android.os.Handler} yang menerima callback untuk tiap +panggilan dari klien.</li> + <li>{@link android.os.Handler} digunakan untuk membuat objek {@link android.os.Messenger} +(yang merupakan acuan ke {@link android.os.Handler}).</li> + <li>{@link android.os.Messenger} membuat {@link android.os.IBinder} yang +dikembalikan layanan ke klien dari {@link android.app.Service#onBind onBind()}.</li> + <li>Klien menggunakan {@link android.os.IBinder} untuk membuat instance {@link android.os.Messenger} +(yang mengacu {@link android.os.Handler} layanan), yang digunakan klien untuk mengirim +objek {@link android.os.Message} ke layanan.</li> + <li>Layanan menerima setiap {@link android.os.Message} dalam {@link +android.os.Handler}—secara spesifik, dalam metode {@link android.os.Handler#handleMessage +handleMessage()}.</li> +</ul> + + +<p>Dengan cara ini, tidak ada "metode" untuk dipanggil klien pada layanan. Sebagai gantinya, +klien mengirim "pesan" (objek-objek {@link android.os.Message}) yang diterima layanan dalam +{@link android.os.Handler}-nya.</p> + +<p>Berikut ini contoh layanan sederhana yang menggunakan antarmuka {@link android.os.Messenger}:</p> + +<pre> +public class MessengerService extends Service { + /** Command to the service to display a message */ + static final int MSG_SAY_HELLO = 1; + + /** + * Handler of incoming messages from clients. + */ + class IncomingHandler extends Handler { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_SAY_HELLO: + Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show(); + break; + default: + super.handleMessage(msg); + } + } + } + + /** + * Target we publish for clients to send messages to IncomingHandler. + */ + final Messenger mMessenger = new Messenger(new IncomingHandler()); + + /** + * When binding to the service, we return an interface to our messenger + * for sending messages to the service. + */ + @Override + public IBinder onBind(Intent intent) { + Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); + return mMessenger.getBinder(); + } +} +</pre> + +<p>Perhatikan bahwa metode {@link android.os.Handler#handleMessage handleMessage()} dalam +{@link android.os.Handler} adalah tempat layanan menerima {@link android.os.Message} +yang masuk dan memutuskan aksi yang harus dilakukan, berdasarkan anggota {@link android.os.Message#what}.</p> + +<p>Klien tinggal membuat {@link android.os.Messenger} berdasarkan {@link +android.os.IBinder} yang dihasilkan layanan dan mengirim pesan menggunakan {@link +android.os.Messenger#send send()}. Misalnya, berikut ini adalah aktivitas sederhana yang mengikat ke +layanan dan mengirim pesan {@code MSG_SAY_HELLO} ke layanan:</p> + +<pre> +public class ActivityMessenger extends Activity { + /** Messenger for communicating with the service. */ + Messenger mService = null; + + /** Flag indicating whether we have called bind on the service. */ + boolean mBound; + + /** + * Class for interacting with the main interface of the service. + */ + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + // This is called when the connection with the service has been + // established, giving us the object we can use to + // interact with the service. We are communicating with the + // service using a Messenger, so here we get a client-side + // representation of that from the raw IBinder object. + mService = new Messenger(service); + mBound = true; + } + + public void onServiceDisconnected(ComponentName className) { + // This is called when the connection with the service has been + // unexpectedly disconnected -- that is, its process crashed. + mService = null; + mBound = false; + } + }; + + public void sayHello(View v) { + if (!mBound) return; + // Create and send a message to the service, using a supported 'what' value + Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); + try { + mService.send(msg); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + } + + @Override + protected void onStart() { + super.onStart(); + // Bind to the service + bindService(new Intent(this, MessengerService.class), mConnection, + Context.BIND_AUTO_CREATE); + } + + @Override + protected void onStop() { + super.onStop(); + // Unbind from the service + if (mBound) { + unbindService(mConnection); + mBound = false; + } + } +} +</pre> + +<p>Perhatikan bahwa contoh ini tidak menampilkan cara layanan merespons klien. Jika ingin +layanan merespons, Anda juga perlu membuat {@link android.os.Messenger} di klien. Lalu +saat menerima callback {@link android.content.ServiceConnection#onServiceConnected +onServiceConnected()}, klien akan mengirim {@link android.os.Message} ke layanan yang berisi +{@link android.os.Messenger} klien dalam parameter {@link android.os.Message#replyTo} +metode {@link android.os.Messenger#send send()}.</p> + +<p>Anda bisa melihat contoh cara menyediakan pertukaran pesan dua arah dalam contoh <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code +MessengerService.java}</a> (layanan) dan <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code +MessengerServiceActivities.java}</a> (klien).</p> + + + + + +<h2 id="Binding">Mengikat ke Layanan</h2> + +<p>Komponen-komponen aplikasi (klien) bisa mengikat ke layanan dengan memanggil +{@link android.content.Context#bindService bindService()}. Sistem Android +lalu memanggil metode {@link android.app.Service#onBind +onBind()} layanan, yang menghasilkan {@link android.os.IBinder} untuk berinteraksi dengan layanan.</p> + +<p>Pengikatan ini bersifat asinkron. {@link android.content.Context#bindService +bindService()} segera kembali dan <em>tidak</em> mengembalikan {@link android.os.IBinder} ke +klien. Untuk menerima {@link android.os.IBinder}, klien harus membuat instance {@link +android.content.ServiceConnection} dan meneruskannya ke {@link android.content.Context#bindService +bindService()}. {@link android.content.ServiceConnection} berisi metode callback yang +dipanggil sistem untuk mengirim {@link android.os.IBinder}.</p> + +<p class="note"><strong>Catatan:</strong> Hanya aktivitas, layanan, dan penyedia konten yang bisa mengikat +ke layanan yang—Anda <strong>tidak bisa</strong> ikat ke layanan dari penerima siaran.</p> + +<p>Jadi, untuk mengikat ke layanan dari klien, Anda harus: </p> +<ol> + <li>Mengimplementasikan {@link android.content.ServiceConnection}. + <p>Implementasi Anda harus mengesampingkan dua metode callback:</p> + <dl> + <dt>{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}</dt> + <dd>Sistem memanggil ini untuk mengirim {@link android.os.IBinder} yang dihasilkan oleh +metode {@link android.app.Service#onBind onBind()} layanan.</dd> + <dt>{@link android.content.ServiceConnection#onServiceDisconnected +onServiceDisconnected()}</dt> + <dd>Sistem Android memanggil ini bila koneksi ke layanan putus +tanpa terduga, seperti ketika layanan mengalami crash atau dimatikan. Ini <em>tidak</em> dipanggil ketika +klien melepas ikatan.</dd> + </dl> + </li> + <li>Panggil {@link +android.content.Context#bindService bindService()}, dengan meneruskan implementasi {@link +android.content.ServiceConnection}. </li> + <li>Bila sistem memanggil metode callback {@link android.content.ServiceConnection#onServiceConnected +onServiceConnected()}, Anda bisa mulai membuat panggilan ke layanan, dengan menggunakan +metode yang didefinisikan oleh antarmuka.</li> + <li>Untuk memutus koneksi dari layanan, panggil {@link +android.content.Context#unbindService unbindService()}. + <p>Bila telah dimusnahkan (destroyed), klien Anda akan melepas ikatan dari layanan, namun Anda harus selalu melepas ikatan +bila sudah selesai berinteraksi dengan layanan atau bila aktivitas Anda sedang jeda sehingga layanan bisa +dimatikan saat tidak sedang digunakan. (Waktu yang tepat untuk mengikat dan melepas ikatan dibahas +selengkapnya di bawah ini.)</p> + </li> +</ol> + +<p>Misalnya, cuplikan berikut menghubungkan klien ke layanan yang dibuat di atas dengan +<a href="#Binder">memperluas kelas Binder</a>, sehingga tinggal mengkonversi +{@link android.os.IBinder} yang dihasilkan ke kelas {@code LocalService} dan meminta instance {@code +LocalService}:</p> + +<pre> +LocalService mService; +private ServiceConnection mConnection = new ServiceConnection() { + // Called when the connection with the service is established + public void onServiceConnected(ComponentName className, IBinder service) { + // Because we have bound to an explicit + // service that is running in our own process, we can + // cast its IBinder to a concrete class and directly access it. + LocalBinder binder = (LocalBinder) service; + mService = binder.getService(); + mBound = true; + } + + // Called when the connection with the service disconnects unexpectedly + public void onServiceDisconnected(ComponentName className) { + Log.e(TAG, "onServiceDisconnected"); + mBound = false; + } +}; +</pre> + +<p>Dengan {@link android.content.ServiceConnection} ini, klien bisa mengikat ke layanan dengan meneruskannya +ke {@link android.content.Context#bindService bindService()}. Misalnya:</p> + +<pre> +Intent intent = new Intent(this, LocalService.class); +bindService(intent, mConnection, Context.BIND_AUTO_CREATE); +</pre> + +<ul> + <li>Parameter pertama {@link android.content.Context#bindService bindService()} adalah sebuah +{@link android.content.Intent} yang secara eksplisit menyebutkan layanan yang akan diikat (walaupun intent +boleh implisit).</li> +<li>Parameter kedua adalah objek {@link android.content.ServiceConnection}.</li> +<li>Parameter ketiga adalah tanda (flag) yang menunjukkan opsi pengikatan. Tanda ini biasanya harus {@link +android.content.Context#BIND_AUTO_CREATE} agar dapat membuat layanan jika belum hidup. +Nilai-nilai lain yang memungkinkan adalah {@link android.content.Context#BIND_DEBUG_UNBIND} +dan {@link android.content.Context#BIND_NOT_FOREGROUND}, atau {@code 0} untuk tidak satu pun.</li> +</ul> + + +<h3>Catatan tambahan</h3> + +<p>Berikut ini beberapa catatan penting tentang mengikat ke layanan:</p> +<ul> + <li>Anda harus selalu menjebak eksepsi {@link android.os.DeadObjectException}, yang dilontarkan +bila koneksi terputus. Inilah satu-satunya eksepsi yang dilontarkan oleh metode jauh.</li> + <li>Objek adalah acuan yang dihitung lintas proses. </li> + <li>Anda biasanya harus memasangkan pengikatan dan pelepasan ikatan selama +memasangkan momen membuat dan menghapus daur hidup klien. Misalnya: + <ul> + <li>Jika Anda hanya perlu berinteraksi dengan layanan saat aktivitas terlihat, Anda +harus mengikat selama {@link android.app.Activity#onStart onStart()} dan melepas ikatan selama {@link +android.app.Activity#onStop onStop()}.</li> + <li>Jika Anda ingin aktivitas menerima tanggapan bahkan saat dihentikan di +latar belakang, Anda bisa mengikat selama {@link android.app.Activity#onCreate onCreate()} dan melepas ikatan +selama {@link android.app.Activity#onDestroy onDestroy()}. Berhati-hatilah karena hal ini menyiratkan aktivitas +Anda perlu menggunakan layanan selama dijalankan (sekalipun di latar belakang), jadi jika +layanan berada dalam proses lain, Anda meningkatkan bobot proses dan semakin besar +kemungkinan sistem akan mematikannya.</li> + </ul> + <p class="note"><strong>Catatan:</strong> Anda biasanya <strong>tidak</strong> boleh mengikat dan melepas ikatan +selama {@link android.app.Activity#onResume onResume()} aktivitas Anda dan {@link +android.app.Activity#onPause onPause()}, karena callback ini terjadi pada setiap transisi daur hidup +dan Anda harus menjaga pemrosesan yang terjadi pada transisi ini tetap minim. Juga, jika +banyak aktivitas dalam aplikasi Anda mengikat ke layanan yang sama dan ada transisi antara +dua aktivitas, layanan bisa dimusnahkan dan dibuat lagi sambil aktivitas saat ini melepas ikatan +(selama jeda) sebelum aktivitas berikutnya mengikat (selama lanjutkan). (Transisi aktivitas ini untuk cara +aktivitas mengoordinasikan daur hidupnya dijelaskan dalam dokumen <a href="{@docRoot}guide/components/activities.html#CoordinatingActivities">Aktivitas</a> +.)</p> +</ul> + +<p>Untuk contoh kode selengkapnya, yang menampilkan cara mengikat ke layanan, lihat kelas <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code +RemoteService.java}</a> dalam <a href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p> + + + + + +<h2 id="Lifecycle">Mengelola Daur Hidup Layanan Terikat</h2> + +<p>Bila layanan dilepas ikatannya dari semua klien, sistem Android akan menghapusnya (kecuali jika layanan juga +dimulai dengan {@link android.app.Service#onStartCommand onStartCommand()}). Dengan demikian, Anda tidak harus +mengelola daur hidup layanan jika layanan itu murni sebuah layanan +terikat—yang dikelola sistem Android untuk Anda berdasarkan apakah layanan terikat ke klien atau tidak.</p> + +<p>Akan tetapi, Jika Anda memilih untuk mengimplementasikan metode callback {@link android.app.Service#onStartCommand +onStartCommand()}, maka Anda harus menghentikan layanan secara eksplisit, karena layanan +sekarang dianggap telah <em>dimulai</em>. Dalam hal ini, layanan akan berjalan hingga layanan +menghentikan dirinya sendiri dengan {@link android.app.Service#stopSelf()} atau panggilan komponen lain {@link +android.content.Context#stopService stopService()}, terlepas dari apakah layanan terikat ke +klien atau tidak.</p> + +<p>Selain itu, jika layanan Anda telah dimulai dan menerima pengikatan, maka saat sistem memanggil +metode {@link android.app.Service#onUnbind onUnbind()}, Anda bisa memilih untuk mengembalikan +{@code true} jika ingin menerima panggilan ke {@link android.app.Service#onRebind +onRebind()} bila nanti klien mengikat ke layanan (sebagai ganti menerima panggilan ke {@link +android.app.Service#onBind onBind()}). {@link android.app.Service#onRebind +onRebind()} akan menghasilkan void, namun klien tetap menerima {@link android.os.IBinder} dalam callback +{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}. +Di bawah ini adalah gambar 1 yang mengilustrasikan logika untuk jenis daur hidup ini.</p> + + +<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" /> +<p class="img-caption"><strong>Gambar 1.</strong> Daur hidup untuk layanan yang dimulai +dan juga memungkinkan pengikatan.</p> + + +<p>Untuk informasi selengkapnya tentang daur hidup layanan yang telah dimulai, lihat dokumen <a href="{@docRoot}guide/components/services.html#Lifecycle">Layanan</a>.</p> + + + + diff --git a/docs/html-intl/intl/id/guide/components/fragments.jd b/docs/html-intl/intl/id/guide/components/fragments.jd new file mode 100644 index 000000000000..9f7199cd8a0b --- /dev/null +++ b/docs/html-intl/intl/id/guide/components/fragments.jd @@ -0,0 +1,812 @@ +page.title=Fragmen +parent.title=Aktivitas +parent.link=activities.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + <h2>Dalam dokumen ini</h2> + <ol> + <li><a href="#Design">Filosofi Desain</a></li> + <li><a href="#Creating">Membuat Fragmen</a> + <ol> + <li><a href="#UI">Menambahkan antarmuka pengguna</a></li> + <li><a href="#Adding">Menambahkan fragmen ke aktivitas</a></li> + </ol> + </li> + <li><a href="#Managing">Mengelola Fragmen</a></li> + <li><a href="#Transactions">Melakukan Transaksi Fragmen</a></li> + <li><a href="#CommunicatingWithActivity">Berkomunikasi dengan Aktivitas</a> + <ol> + <li><a href="#EventCallbacks">Membuat callback kejadian pada aktivitas</a></li> + <li><a href="#ActionBar">Menambahkan item ke Action-Bar</a></li> + </ol> + </li> + <li><a href="#Lifecycle">Menangani Daur Hidup Fragmen</a> + <ol> + <li><a href="#CoordinatingWithActivity">Mengoordinasi dengan daur hidup aktivitas</a></li> + </ol> + </li> + <li><a href="#Example">Contoh</a></li> + </ol> + + <h2>Kelas-kelas utama</h2> + <ol> + <li>{@link android.app.Fragment}</li> + <li>{@link android.app.FragmentManager}</li> + <li>{@link android.app.FragmentTransaction}</li> + </ol> + + <h2>Lihat juga</h2> + <ol> + <li><a href="{@docRoot}training/basics/fragments/index.html">Membangun UI Dinamis dengan Fragmen</a></li> + <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Mendukung Tablet +dan Handset</a></li> + </ol> +</div> +</div> + +<p>{@link android.app.Fragment} mewakili perilaku atau bagian dari antarmuka pengguna dalam +{@link android.app.Activity}. Anda bisa mengombinasikan beberapa fragmen dalam satu aktivitas untuk membangun UI +multipanel dan menggunakan kembali sebuah fragmen dalam beberapa aktivitas. Anda bisa menganggap fragmen sebagai bagian +modular dari aktivitas, yang memiliki daur hidup sendiri, menerima kejadian input sendiri, dan +yang bisa Anda tambahkan atau hapus saat aktivitas berjalan (semacam "sub aktivitas" yang +bisa digunakan kembali dalam aktivitas berbeda).</p> + +<p>Fragmen harus selalu tertanam dalam aktivitas dan daur hidup fragmen secara langsung +dipengaruhi oleh daur hidup aktivitas host-nya. Misalnya, saat aktivitas dihentikan sementara, +semua fragmen di dalamnya juga dihentikan sementara, dan bila aktivitas dimusnahkan, semua fragmen juga demikian. Akan tetapi, saat +aktivitas berjalan (dalam <a href="{@docRoot}guide/components/activities.html#Lifecycle">status daur hidup</a> <em>dilanjutkan</em>, Anda bisa +memanipulasi setiap fragmen secara terpisah, seperti menambah atau menghapusnya. Saat melakukan transaksi +fragmen, Anda juga bisa menambahkannya ke back-stack yang dikelola oleh aktivitas +—setiap entri back-stack merupakan record transaksi fragmen yang +terjadi. Dengan back-stack pengguna dapat membalikkan transaksi fragmen (mengarah mundur), +dengan menekan tombol <em>Back</em>.</p> + +<p>Bila Anda menambahkan fragmen sebagai bagian dari layout aktivitas, fragmen itu berada dalam {@link +android.view.ViewGroup} di hierarki tampilan aktivitas tersebut dan fragmen mendefinisikan +layout +tampilannya sendiri. Anda bisa menyisipkan fragmen ke dalam layout aktivitas dengan mendeklarasikan fragmen dalam file layout aktivitas +, sebagai elemen {@code <fragment>}, atau dari kode aplikasi dengan menambahkannya ke + {@link android.view.ViewGroup} yang ada. Akan tetapi, fragmen tidak harus menjadi bagian dari +layout aktivitas; Anda juga bisa menggunakan fragmen tanpa UI-nya sendiri sebagai pekerja tak terlihat untuk +aktivitas tersebut.</p> + +<p>Dokumen ini menjelaskan cara membangun aplikasi menggunakan fragmen, termasuk +cara fragmen mempertahankan statusnya bila ditambahkan ke back-stack aktivitas, berbagi +kejadian dengan aktivitas, dan fragmen lain dalam aktivitas, berkontribusi pada action-bar +aktivitas, dan lainnya.</p> + + +<h2 id="Design">Filosofi Desain</h2> + +<p>Android memperkenalkan fragmen di Android 3.0 (API level 11), terutama untuk mendukung desain UI yang lebih +dinamis dan fleksibel pada layar besar, seperti tablet. Karena +layar tablet jauh lebih besar daripada layar handset, maka lebih banyak ruang untuk mengombinasikan dan +bertukar komponen UI. Fragmen memungkinkan desain seperti itu tanpa perlu mengelola perubahan +kompleks pada hierarki tampilan. Dengan membagi layout aktivitas menjadi beberapa fragmen, Anda bisa +mengubah penampilan aktivitas saat runtime dan mempertahankan perubahan itu di back-stack +yang dikelola oleh aktivitas.</p> + +<p>Misalnya, aplikasi berita bisa menggunakan satu fragmen untuk menampilkan daftar artikel di +sebelah kiri dan fragmen lainnya untuk menampilkan artikel di sebelah kanan—kedua fragmen ini muncul di satu +aktivitas, berdampingan, dan masing-masing fragmen memiliki serangkaian metode callback daur hidup dan menangani kejadian input +penggunanya sendiri. Sehingga, sebagai ganti menggunakan satu aktivitas untuk memilih +artikel dan aktivitas lainnya untuk membaca artikel, pengguna bisa memilih artikel dan membaca semuanya dalam +aktivitas yang sama, sebagaimana diilustrasikan dalam layout tablet pada gambar 1.</p> + +<p>Anda harus mendesain masing-masing fragmen sebagai komponen aktivitas modular dan bisa digunakan kembali. Yakni, karena +setiap fragmen mendefinisikan layoutnya dan perilakunya dengan callback daur hidupnya sendiri, Anda bisa memasukkan +satu fragmen dalam banyak aktivitas, sehingga Anda harus mendesainnya untuk digunakan kembali dan mencegah +memanipulasi satu fragmen dari fragmen lain secara langsung. Ini terutama penting karena dengan +fragmen modular Anda bisa mengubah kombinasi fragmen untuk ukuran layar berbeda. Saat mendesain aplikasi +untuk mendukung tablet maupun handset, Anda bisa menggunakan kembali fragmen dalam +konfigurasi layout berbeda untuk mengoptimalkan pengalaman pengguna berdasarkan ruang layar yang tersedia. Misalnya +, pada handset, fragmen mungkin perlu dipisahkan untuk menyediakan UI panel tunggal +bila lebih dari satu yang tidak cocok dalam aktivitas yang sama.</p> + +<img src="{@docRoot}images/fundamentals/fragments.png" alt="" /> +<p class="img-caption"><strong>Gambar 1.</strong> Contoh cara dua modul UI yang didefinisikan oleh + fragmen bisa digabungkan ke dalam satu aktivitas untuk desain tablet, namun dipisahkan untuk +desain handset.</p> + +<p>Misalnya—untuk melanjutkan contoh aplikasi berita— aplikasi bisa menanamkan +dua fragmen dalam <em>Aktivitas A</em>, saat berjalan pada perangkat berukuran tablet. Akan tetapi, pada +layar berukuran handset, ruang untuk kedua fragmen tidak cukup, sehingga <em>Aktivitas A</em> hanya +menyertakan fragmen untuk daftar artikel, dan saat pengguna memilih artikel, +<em>Aktivitas B</em> akan dimulai, termasuk fragmen kedua untuk membaca artikel. Sehingga, aplikasi mendukung +tablet dan handset dengan menggunakan kembali fragmen dalam kombinasi berbeda, seperti diilustrasikan dalam +gambar 1.</p> + +<p>Untuk informasi selengkapnya tentang mendesain aplikasi menggunakan kombinasi fragmen berbeda +untuk konfigurasi layar berbeda, lihat panduan untuk <a href="{@docRoot}guide/practices/tablets-and-handsets.html">Mendukung Tablet dan Handset</a>.</p> + + + +<h2 id="Creating">Membuat Fragmen</h2> + +<div class="figure" style="width:327px"> +<img src="{@docRoot}images/fragment_lifecycle.png" alt="" /> +<p class="img-caption"><strong>Gambar 2.</strong> Daur hidup fragmen (saat + aktivitasnya berjalan).</p> +</div> + +<p>Untuk membuat fragmen, Anda harus membuat subkelas {@link android.app.Fragment} (atau +subkelasnya yang ada). Kelas {@link android.app.Fragment} memiliki kode yang mirip seperti +{@link android.app.Activity}. Kelas ini memiliki metode callback yang serupa dengan aktivitas, seperti + {@link android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onStart onStart()}, +{@link android.app.Fragment#onPause onPause()}, dan {@link android.app.Fragment#onStop onStop()}. Sebenarnya +, jika Anda mengkonversi aplikasi Android saat ini untuk menggunakan fragmen, Anda mungkin cukup memindahkan +kode dari metode callback aktivitas ke masing-masing metode callback +fragmen.</p> + +<p>Biasanya, Anda harus mengimplementasikan setidaknya metode daur hidup berikut ini:</p> + +<dl> + <dt>{@link android.app.Fragment#onCreate onCreate()}</dt> + <dd>Sistem akan memanggilnya saat membuat fragmen. Dalam implementasi, Anda harus +menginisialisasi komponen penting dari fragmen yang ingin dipertahankan saat fragmen +dihentikan sementara atau dihentikan, kemudian dilanjutkan.</dd> + <dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt> + <dd>Sistem akan memanggilnya saat fragmen menggambar antarmuka penggunanya +untuk yang pertama kali. Untuk menggambar UI fragmen, Anda harus mengembalikan {@link android.view.View} dari metode +ini yang menjadi akar layout fragmen. Hasil yang dikembalikan bisa berupa null jika +fragmen tidak menyediakan UI.</dd> + <dt>{@link android.app.Activity#onPause onPause()}</dt> + <dd>Sistem akan memanggil metode ini sebagai indikasi pertama bahwa pengguna sedang meninggalkan +fragmen Anda (walau itu tidak selalu berarti fragmen sedang dimusnahkan). Inilah biasanya tempat Anda +harus mengikat setiap perubahan yang harus dipertahankan selepas sesi pengguna saat ini (karena +pengguna mungkin tidak kembali).</dd> +</dl> + +<p>Kebanyakan aplikasi harus mengimplementasikan setidaknya tiga metode ini untuk setiap fragmen, namun ada +beberapa metode callback lain yang juga harus Anda gunakan untuk menangani berbagai tahap +daur hidup fragmen. Semua metode callback daur hidup akan dibahas secara lebih detail, di bagian +tentang <a href="#Lifecycle">Menangani Daur Hidup Fragmen</a>.</p> + + +<p>Ada juga beberapa subkelas yang mungkin ingin diperpanjang, sebagai ganti kelas basis {@link +android.app.Fragment}:</p> + +<dl> + <dt>{@link android.app.DialogFragment}</dt> + <dd>Menampilkan dialog mengambang. Penggunaan kelas ini untuk membuat dialog merupakan alternatif yang baik dari +penggunaan metode helper dialog di kelas {@link android.app.Activity}, karena Anda bisa +menyatukan dialog fragmen ke dalam back-stack fragmen yang dikelola oleh aktivitas, +sehingga pengguna bisa kembali ke fragmen yang ditinggalkan.</dd> + + <dt>{@link android.app.ListFragment}</dt> + <dd>Menampilkan daftar item yang dikelola oleh adaptor (seperti {@link +android.widget.SimpleCursorAdapter}), serupa dengan {@link android.app.ListActivity}. Menampilkan +beberapa metode pengelolaan daftar tampilan seperti callback {@link +android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} untuk +menangani kejadian klik.</dd> + + <dt>{@link android.preference.PreferenceFragment}</dt> + <dd>Menampilkan hierarki objek {@link android.preference.Preference} sebagai daftar, serupa dengan +{@link android.preference.PreferenceActivity}. Hal ini berguna saat membuat aktivitas +"pengaturan" untuk aplikasi Anda.</dd> +</dl> + + +<h3 id="UI">Menambahkan antarmuka pengguna</h3> + +<p>Fragmen biasanya digunakan sebagai bagian dari antarmuka pengguna aktivitas dan menyumbangkan +layoutnya sendiri ke aktivitas.</p> + +<p>Untuk menyediakan layout fragmen, Anda harus mengimplementasikan metode callback {@link +android.app.Fragment#onCreateView onCreateView()}, yang dipanggil sistem Android +bila tiba saatnya fragmen menggambar layoutnya. Implementasi Anda atas metode ini harus mengembalikan +{@link android.view.View} yang menjadi akar layout fragmen.</p> + +<p class="note"><strong>Catatan:</strong> Jika fragmen adalah subkelas {@link +android.app.ListFragment}, implementasi default akan mengembalikan {@link android.widget.ListView} dari +{@link android.app.Fragment#onCreateView onCreateView()}, sehingga Anda tidak perlu mengimplementasikannya.</p> + +<p>Untuk mengembalikan layout dari {@link +android.app.Fragment#onCreateView onCreateView()}, Anda bisa memekarkannya dari <a href="{@docRoot}guide/topics/resources/layout-resource.html">sumber daya layout</a> yang didefinisikan di XML. Untuk +membantu melakukannya, {@link android.app.Fragment#onCreateView onCreateView()} menyediakan objek +{@link android.view.LayoutInflater}.</p> + +<p>Misalnya, ini adalah subkelas {@link android.app.Fragment} yang memuat layout dari file +{@code example_fragment.xml}:</p> + +<pre> +public static class ExampleFragment extends Fragment { + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.example_fragment, container, false); + } +} +</pre> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h3>Membuat layout</h3> + <p>Dalam contoh di atas, {@code R.layout.example_fragment} merupakan acuan ke sumber daya layout +bernama {@code example_fragment.xml} yang tersimpan dalam sumber daya aplikasi. Untuk informasi tentang cara +membuat layout di XML, lihat dokumentasi +<a href="{@docRoot}guide/topics/ui/index.html">Antarmuka Pengguna</a>.</p> +</div> +</div> + +<p>Parameter {@code container} yang diteruskan ke {@link android.app.Fragment#onCreateView +onCreateView()} adalah induk {@link android.view.ViewGroup} (dari layout aktivitas) tempat +layout fragmen +akan disisipkan. Parameter {@code savedInstanceState} adalah {@link android.os.Bundle} yang +menyediakan data tentang instance fragmen sebelumnya, jika fragmen dilanjutkan +(status pemulihan dibahas selengkapnya di bagian tentang <a href="#Lifecycle">Menangani +Daur Hidup Fragmen</a>).</p> + +<p>Metode {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} membutuhkan +tiga argumen:</p> +<ul> + <li>ID sumber daya layout yang ingin dimekarkan.</li> + <li>{@link android.view.ViewGroup} akan menjadi induk dari layout yang dimekarkan. {@code +container} perlu diteruskan agar sistem menerapkan parameter layout ke tampilan akar layout +yang dimekarkan, yang ditetapkan dalam tampilan induk yang akan dituju.</li> + <li>Boolean yang menunjukkan apakah layout akan dimekarkan harus ditempelkan pada {@link +android.view.ViewGroup} (parameter kedua) selama pemekaran. (Dalam hal ini, ini +salah karena sistem sudah memasukkan layout yang dimekarkan ke dalam {@code +container}—meneruskan benar akan membuat tampilan grup yang berlebihan dalam layout akhir.)</li> +</ul> + +<p>Anda kini telah melihat cara membuat fragmen yang menyediakan layout. Berikutnya, Anda perlu menambahkan +fragmen ke aktivitas.</p> + + + +<h3 id="Adding">Menambahkan fragmen ke aktivitas</h3> + +<p>Biasanya, fragmen berkontribusi pada sebagian UI ke aktivitas host, yang ditanamkan sebagai +bagian dari hierarki tampilan keseluruhan aktivitas. Ada dua cara untuk menambahkan fragmen ke layout +aktivitas:</p> + +<ul> + <li><b>Deklarasikan fragmen dalam file layout aktivitas.</b> +<p>Dalam hal ini, Anda bisa +menetapkan properti layout fragmen seakan-akan sebuah tampilan. Misalnya, berikut ini adalah file +layout untuk aktivitas dengan dua fragmen:</p> +<pre> +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <fragment android:name="com.example.news.ArticleListFragment" + android:id="@+id/list" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent" /> + <fragment android:name="com.example.news.ArticleReaderFragment" + android:id="@+id/viewer" + android:layout_weight="2" + android:layout_width="0dp" + android:layout_height="match_parent" /> +</LinearLayout> +</pre> + <p>Atribut {@code android:name} dalam {@code <fragment>} menetapkan kelas {@link +android.app.Fragment} untuk dibuat instance-nya dalam layout.</p> + +<p>Saat sistem membuat layout aktivitas, sistem membuat instance setiap fragmen sebagaimana yang ditetapkan dalam layout +dan memanggil metode {@link android.app.Fragment#onCreateView onCreateView()} masing-masing, +untuk mengambil setiap fragmen. Sistem akan menyisipkan {@link android.view.View} yang dikembalikan langsung oleh fragmen, + menggantikan elemen {@code <fragment>}.</p> + +<div class="note"> + <p><strong>Catatan:</strong> Setiap fragmen memerlukan identifier +unik yang bisa digunakan sistem untuk memulihkan fragmen jika aktivitas dimulai kembali (dan identifier yang bisa digunakan menangkap +fragmen untuk melakukan transaksi, seperti menghapusnya). Ada tiga cara untuk memberikan +ID bagi fragmen:</p> + <ul> + <li>Memberikan atribut {@code android:id} bersama ID unik.</li> + <li>Memberikan atribut {@code android:tag} bersama string unik.</li> + <li>Jika Anda tidak memberikan dua hal tersebut, sistem akan menggunakan ID +tampilan kontainer.</li> + </ul> +</div> + </li> + + <li><b>Atau, secara programatis tambahkan fragmen ke {@link android.view.ViewGroup} yang ada.</b> +<p>Kapan saja saat aktivitas berjalan, Anda bisa menambahkan fragmen ke layout aktivitas. Anda +cukup menetapkan {@link +android.view.ViewGroup} di tempat memasukkan fragmen.</p> + <p>Untuk membuat transaksi fragmen dalam aktivitas (seperti menambah, menghapus, atau mengganti +fragmen), Anda harus menggunakan API dari {@link android.app.FragmentTransaction}. Anda bisa mengambil instance + {@link android.app.FragmentTransaction} dari {@link android.app.Activity} seperti ini:</p> + +<pre> +FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()} +FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()}; +</pre> + +<p>Selanjutnya Anda bisa menambahkan fragmen menggunakan metode {@link +android.app.FragmentTransaction#add(int,Fragment) add()}, dengan menetapkan fragmen yang akan ditambahkan dan +tampilan tempat menyisipkannya. Misalnya:</p> + +<pre> +ExampleFragment fragment = new ExampleFragment(); +fragmentTransaction.add(R.id.fragment_container, fragment); +fragmentTransaction.commit(); +</pre> + + <p>Argumen pertama yang diteruskan ke {@link android.app.FragmentTransaction#add(int,Fragment) add()} + adalah {@link android.view.ViewGroup} tempat fragmen harus dimasukkan, yang ditetapkan oleh +ID sumber daya, dan parameter kedua merupakan fragmen yang akan ditambahkan.</p> + <p>Setelah membuat perubahan dengan +{@link android.app.FragmentTransaction}, Anda harus + memanggil {@link android.app.FragmentTransaction#commit} untuk menerapkan perubahan.</p> + </li> +</ul> + + +<h4 id="AddingWithoutUI">Menambahkan fragmen tanpa UI</h4> + +<p>Contoh di atas menampilkan cara menambahkan fragmen ke aktivitas untuk menyediakan UI. Akan tetapi, +Anda juga bisa menggunakan fragmen untuk menyediakan perilaku latar belakang bagi aktivitas tanpa menampilkan UI +tambahan.</p> + +<p>Untuk menambahkan fragmen tanpa UI, tambahkan fragmen dari aktivitas menggunakan {@link +android.app.FragmentTransaction#add(Fragment,String)} (dengan menyediakan string unik "tag" untuk fragmen +, bukan ID tampilan). Ini akan menambahkan fragmen, namun, karena tidak dikaitkan dengan tampilan +dalam layout aktivitas, ini tidak akan menerima panggilan ke {@link +android.app.Fragment#onCreateView onCreateView()}. Jadi Anda tidak perlu mengimplementasikan metode itu.</p> + +<p>Menyediakan tag string untuk fragmen tidak hanya untuk fragmen non-UI—Anda juga bisa +menyediakan tag string untuk fragmen yang memiliki UI—namun jika fragmen tidak memiliki UI +, maka tag string adalah satu-satunya cara untuk mengidentifikasinya. Jika Anda ingin mendapatkan fragmen dari +aktivitas nantinya, Anda perlu menggunakan {@link android.app.FragmentManager#findFragmentByTag +findFragmentByTag()}.</p> + +<p>Untuk contoh aktivitas yang menggunakan fragmen sebagai pekerja latar belakang, tanpa UI, lihat sampel {@code +FragmentRetainInstance.java}, yang disertakan dalam sampel SDK (tersedia melalui +Android SDK Manager) dan terletak di sistem Anda sebagai +<code><sdk_root>/APIDemos/app/src/main/java/com/example/android/apis/app/FragmentRetainInstance.java</code>.</p> + + + +<h2 id="Managing">Mengelola Fragmen</h2> + +<p>Untuk mengelola fragmen dalam aktivitas, Anda perlu menggunakan {@link android.app.FragmentManager}. Untuk +mendapatkannya, panggil {@link android.app.Activity#getFragmentManager()} dari aktivitas Anda.</p> + +<p>Beberapa hal yang dapat Anda lakukan dengan {@link android.app.FragmentManager} antara lain:</p> + +<ul> + <li>Dapatkan fragmen yang ada di aktivitas dengan {@link +android.app.FragmentManager#findFragmentById findFragmentById()} (untuk fragmen yang menyediakan UI dalam +layout aktivitas) atau {@link android.app.FragmentManager#findFragmentByTag +findFragmentByTag()} (untuk fragmen yang menyediakan atau tidak menyediakan UI).</li> + <li>Tarik fragmen dari back-stack, dengan {@link +android.app.FragmentManager#popBackStack()} (mensimulasikan perintah <em>Back</em> oleh pengguna).</li> + <li>Daftarkan listener untuk perubahan pada back-stack, dengan {@link +android.app.FragmentManager#addOnBackStackChangedListener addOnBackStackChangedListener()}.</li> +</ul> + +<p>Untuk informasi selengkapnya tentang metode ini dan hal lainnya, lihat dokumentasi kelas {@link +android.app.FragmentManager}.</p> + +<p>Seperti yang ditunjukkan di bagian sebelumnya, Anda juga bisa menggunakan {@link android.app.FragmentManager} +untuk membuka {@link android.app.FragmentTransaction}, sehingga Anda bisa melakukan transaksi, seperti +menambah dan menghapus fragmen.</p> + + +<h2 id="Transactions">Melakukan Transaksi Fragmen</h2> + +<p>Fitur menarik terkait penggunaan fragmen di aktivitas adalah kemampuan menambah, menghapus, mengganti, +dan melakukan tindakan lain dengannya, sebagai respons atas interaksi pengguna. Setiap set perubahan +yang Anda lakukan untuk aktivitas disebut transaksi dan Anda bisa melakukan transaksi menggunakan API di {@link +android.app.FragmentTransaction}. Anda juga bisa menyimpan setiap transaksi ke back-stack yang dikelola +aktivitas, sehingga pengguna bisa mengarah mundur melalui perubahan fragmen (mirip mengarah +mundur melalui aktivitas).</p> + +<p>Anda bisa mengambil instance {@link android.app.FragmentTransaction} dari {@link +android.app.FragmentManager} seperti ini:</p> + +<pre> +FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()}; +FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()}; +</pre> + +<p>Setiap transaksi merupakan serangkaian perubahan yang ingin dilakukan pada waktu yang sama. Anda bisa +mengatur semua perubahan yang ingin dilakukan untuk transaksi mana saja menggunakan metode seperti {@link +android.app.FragmentTransaction#add add()}, {@link android.app.FragmentTransaction#remove remove()}, +dan {@link android.app.FragmentTransaction#replace replace()}. Kemudian, untuk menerapkan transaksi +pada aktivitas, Anda harus memanggil {@link android.app.FragmentTransaction#commit()}.</p> +</dl> + +<p>Akan tetapi, sebelum memanggil {@link +android.app.FragmentTransaction#commit()}, Anda mungkin perlu memanggil {@link +android.app.FragmentTransaction#addToBackStack addToBackStack()}, untuk menambahkan transaksi +ke back-stack dari transaksi fragmen. Back-stack ini dikelola oleh aktivitas dan memungkinkan +pengguna kembali ke status fragmen sebelumnya, dengan menekan tombol <em>Back</em>.</p> + +<p>Misalnya, berikut ini cara mengganti satu fragmen dengan yang fragmen yang lain, dan mempertahankan +status sebelumnya di back-stack:</p> + +<pre> +// Create new fragment and transaction +Fragment newFragment = new ExampleFragment(); +FragmentTransaction transaction = getFragmentManager().beginTransaction(); + +// Replace whatever is in the fragment_container view with this fragment, +// and add the transaction to the back stack +transaction.replace(R.id.fragment_container, newFragment); +transaction.addToBackStack(null); + +// Commit the transaction +transaction.commit(); +</pre> + +<p>Dalam contoh ini, {@code newFragment} menggantikan fragmen apa saja (jika ada) yang saat ini berada dalam +kontainer layout yang diidentifikasi oleh ID {@code R.id.fragment_container}. Dengan memanggil @link +android.app.FragmentTransaction#addToBackStack addToBackStack()}, transaksi yang diganti +disimpan ke back-stack sehingga pengguna bisa membalikkan transaksi dan mengembalikan fragmen +sebelumnya dengan menekan tombol <em>Back</em>.</p> + +<p>Jika Anda menambahkan beberapa perubahan pada transaksi (seperti {@link +android.app.FragmentTransaction#add add()} atau {@link android.app.FragmentTransaction#remove +remove()}) dan panggil {@link +android.app.FragmentTransaction#addToBackStack addToBackStack()}, maka semua perubahan akan diterapkan +sebelum Anda memanggil {@link android.app.FragmentTransaction#commit commit()} akan ditambahkan ke +back-stack sebagai satu transaksi dan tombol <em>Back</em> akan membalikannya semua.</p> + +<p>Urutan menambahkan perubahan pada {@link android.app.FragmentTransaction} tidak berpengaruh, +kecuali:</p> +<ul> + <li>Anda harus memanggil {@link android.app.FragmentTransaction#commit()} paling akhir</li> + <li>Jika Anda menambahkan beberapa fragmen ke kontainer yang sama, maka +urutan penambahannya akan menentukan urutan munculnya dalam hierarki tampilan</li> +</ul> + +<p>Jika Anda tidak memanggil {@link android.app.FragmentTransaction#addToBackStack(String) +addToBackStack()} saat melakukan transaksi yang menghapus fragmen, maka fragmen itu +akan dimusnahkan bila transaksi diikat dan pengguna tidak bisa mengarah kembali ke sana. Sedangkan, jika +Anda memanggil {@link android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} saat +menghapus fragmen, maka fragmen itu akan <em>dihentikan</em> dan akan dilanjutkan jika pengguna mengarah +kembali.</p> + +<p class="note"><strong>Tip:</strong> Untuk setiap transaksi fragmen, Anda bisa menerapkan animasi +transisi, dengan memanggil {@link android.app.FragmentTransaction#setTransition setTransition()} sebelum +mengikatnya.</p> + +<p>Memanggil {@link android.app.FragmentTransaction#commit()} tidak akan langsung menjalankan +transaksi. Namun sebuah jadwal akan dibuat untuk dijalankan pada thread UI aktivitas (thread "utama") +begitu thread bisa melakukannya. Akan tetapi, jika perlu Anda bisa memanggil {@link +android.app.FragmentManager#executePendingTransactions()} dari thread UI untuk segera +mengeksekusi transaksi yang diserahkan oleh {@link android.app.FragmentTransaction#commit()}. Hal itu +biasanya tidak perlu kecuali jika transaksi merupakan dependensi bagi pekerjaan dalam thread lain.</p> + +<p class="caution"><strong>Perhatian:</strong> Anda bisa mengikat transaksi menggunakan {@link +android.app.FragmentTransaction#commit commit()} hanya sebelum aktivitas <a href="{@docRoot}guide/components/activities.html#SavingActivityState">menyimpan +statusnya</a> (saat pengguna meninggalkan aktivitas). Jika Anda mencoba mengikatnya setelah itu, +eksepsi akan dilontarkan. Ini karena status setelah pengikatan bisa hilang jika aktivitas +perlu dipulihkan. Untuk situasi yang memperbolehkan Anda meniadakan pengikatan (commit), gunakan {@link +android.app.FragmentTransaction#commitAllowingStateLoss()}.</p> + + + + +<h2 id="CommunicatingWithActivity">Berkomunikasi dengan Aktivitas</h2> + +<p>Meskipun {@link android.app.Fragment} diimplementasikan sebagai objek yang tidak bergantung pada +{@link android.app.Activity} dan bisa digunakan dalam banyak aktivitas, instance tertentu +dari fragmen secara langsung terkait dengan aktivitas yang dimuatnya.</p> + +<p>Khususnya, fragmen bisa mengakses instance {@link android.app.Activity} dengan {@link +android.app.Fragment#getActivity()} dan dengan mudah melakukan tugas-tugas seperti mencari tampilan dalam + layout aktivitas:</p> + +<pre> +View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Activity#findViewById findViewById}(R.id.list); +</pre> + +<p>Demikian pula, aktivitas Anda bisa memanggil metode di fragmen dengan meminta acuan ke +{@link android.app.Fragment} dari {@link android.app.FragmentManager}, menggunakan {@link +android.app.FragmentManager#findFragmentById findFragmentById()} atau {@link +android.app.FragmentManager#findFragmentByTag findFragmentByTag()}. Misalnya:</p> + +<pre> +ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment); +</pre> + + +<h3 id="EventCallbacks">Membuat callback kejadian pada aktivitas</h3> + +<p>Dalam beberapa kasus, Anda mungkin perlu fragmen untuk berbagi kejadian dengan aktivitas. Cara yang baik untuk melakukannya +adalah mendefinisikan antarmuka callback di dalam fragmen dan mengharuskan aktivitas host +mengimplementasikannya. Saat aktivitas menerima callback melalui antarmuka, aktivitas akan bisa berbagi informasi itu +dengan fragmen lain dalam layout jika perlu.</p> + +<p>Misalnya, jika sebuah aplikasi berita memiliki dua fragmen dalam aktivitas—satu untuk menampilkan daftar +artikel (fragmen A) dan satu lagi untuk menampilkan artikel (fragmen B)—maka fragmen A harus +memberi tahu aktivitas bila item daftar dipilih sehingga aktivitas bisa memberi tahu fragmen B untuk menampilkan artikel. Dalam +hal ini, antarmuka {@code OnArticleSelectedListener} dideklarasikan di dalam fragmen A:</p> + +<pre> +public static class FragmentA extends ListFragment { + ... + // Container Activity must implement this interface + public interface OnArticleSelectedListener { + public void onArticleSelected(Uri articleUri); + } + ... +} +</pre> + +<p>Selanjutnya aktivitas yang menjadi host fragmen akan mengimplementasikan antarmuka {@code OnArticleSelectedListener} + dan +mengesampingkan {@code onArticleSelected()} untuk memberi tahu fragmen B mengenai kejadian dari fragmen A. Untuk memastikan +bahwa aktivitas host mengimplementasikan antarmuka ini, metode callback fragmen A {@link +android.app.Fragment#onAttach onAttach()} (yang dipanggil sistem saat menambahkan +fragmen ke aktivitas) membuat instance {@code OnArticleSelectedListener} dengan +membuat {@link android.app.Activity} yang diteruskan ke {@link android.app.Fragment#onAttach +onAttach()}:</p> + +<pre> +public static class FragmentA extends ListFragment { + OnArticleSelectedListener mListener; + ... + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + mListener = (OnArticleSelectedListener) activity; + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener"); + } + } + ... +} +</pre> + +<p>Jika aktivitas belum mengimplementasikan antarmuka, maka fragmen akan melontarkan +{@link java.lang.ClassCastException}. +Jika berhasil, anggota {@code mListener} yang menyimpan acuan ke implementasi aktivitas +{@code OnArticleSelectedListener}, sehingga fragmen A bisa berbagi kejadian dengan aktivitas, dengan memanggil metode +yang didefinisikan oleh antarmuka {@code OnArticleSelectedListener}. Misalnya, jika fragmen A adalah +ekstensi dari {@link android.app.ListFragment}, maka setiap kali +pengguna mengklik item daftar, sistem akan memanggil {@link android.app.ListFragment#onListItemClick +onListItemClick()} di fragmen, yang selanjutnya memanggil {@code onArticleSelected()} untuk berbagi +kejadian dengan aktivitas:</p> + +<pre> +public static class FragmentA extends ListFragment { + OnArticleSelectedListener mListener; + ... + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + // Append the clicked item's row ID with the content provider Uri + Uri noteUri = ContentUris.{@link android.content.ContentUris#withAppendedId withAppendedId}(ArticleColumns.CONTENT_URI, id); + // Send the event and Uri to the host activity + mListener.onArticleSelected(noteUri); + } + ... +} +</pre> + +<p>Parameter {@code id} yang diteruskan ke {@link +android.app.ListFragment#onListItemClick onListItemClick()} merupakan ID baris dari item yang diklik, +yang digunakan aktivitas (atau fragmen lain) untuk mengambil artikel dari {@link +android.content.ContentProvider} aplikasi.</p> + +<p><!--To see a complete implementation of this kind of callback interface, see the <a +href="{@docRoot}resources/samples/NotePad/index.html">NotePad sample</a>. -->Informasi selengkapnya tentang +menggunakan penyedia konten tersedia dalam dokumen <a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p> + + + +<h3 id="ActionBar">Menambahkan item ke Action-Bar</h3> + +<p>Fragmen Anda bisa menyumbangkan item menu ke <a href="{@docRoot}guide/topics/ui/menus.html#options-menu">Menu Opsi</a> aktivitas (dan, konsekuensinya, <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>) dengan mengimplementasikan +{@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}. Agar +metode ini bisa menerima panggilan, Anda harus memanggil {@link +android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()} selama {@link +android.app.Fragment#onCreate(Bundle) onCreate()}, untuk menunjukkan bahwa fragmen +ingin menambahkan item ke Menu Opsi (jika tidak, fragmen tidak akan menerima panggilan ke +{@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu()}).</p> + +<p>Setiap item yang selanjutnya Anda tambahkan ke Menu Opsi dari fragmen akan ditambahkan ke item menu +yang ada. Fragmen juga menerima callback ke {@link +android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} bila item menu +dipilih.</p> + +<p>Anda juga bisa mendaftarkan tampilan dalam layout fragmen untuk menyediakan menu konteks dengan memanggil {@link +android.app.Fragment#registerForContextMenu(View) registerForContextMenu()}. Bila pengguna +membuka menu konteks, fragmen akan menerima panggilan ke {@link +android.app.Fragment#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo) +onCreateContextMenu()}. Bila pengguna memilih item, fragmen akan menerima panggilan ke @link +android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}.</p> + +<p class="note"><strong>Catatan:</strong> Walaupun fragmen menerima callback pada item yang dipilih +untuk setiap item menu yang ditambahkannya, aktivitaslah yang pertama kali menerima masing-masing callback saat pengguna +memilih item menu. Jika implementasi aktivitas dari callback bila-item-dipilih, +tidak menangani item yang dipilih, maka kejadian akan diteruskan ke callback fragmen. Ini berlaku +untuk Menu Opsi dan menu konteks.</p> + +<p>Untuk informasi selengkapnya tentang menu, lihat panduan pengembang <a href="{@docRoot}guide/topics/ui/menus.html">Menu</a> dan <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>.</p> + + + + +<h2 id="Lifecycle">Menangani Daur Hidup Fragmen</h2> + +<div class="figure" style="width:350px"> +<img src="{@docRoot}images/activity_fragment_lifecycle.png" alt="" /> +<p class="img-caption"><strong>Gambar 3.</strong> Efek daur hidup aktivitas pada daur hidup +fragmen.</p> +</div> + +<p>Mengelola daur hidup fragmen mirip sekali dengan mengelola daur hidup aktivitas. Seperti +aktivitas, fragmen bisa berada dalam tiga status:</p> + +<dl> + <dt><i>Dilanjutkan</i></dt> + <dd>Fragmen terlihat dalam aktivitas yang berjalan.</dd> + + <dt><i>Dihentikan sementara</i></dt> + <dd>Aktivitas lain berada di latar depan dan memiliki fokus, namun aktivitas tempat fragmen berada +masih terlihat (aktivitas latar depan sebagian terlihat atau tidak menutupi +seluruh layar).</dd> + + <dt><i>Dihentikan</i></dt> + <dd>Fragmen tidak terlihat. Aktivitas host telah dihentikan atau +fragmen telah dihapus dari aktivitas namun ditambahkan ke back-stack. Fragmen yang dihentikan +masih hidup (semua status dan informasi anggota masih disimpan oleh sistem). Akan tetapi, fragmen +tidak terlihat lagi oleh pengguna dan akan dimatikan jika aktivitas dimatikan.</dd> +</dl> + +<p>Seperti halnya aktivitas, Anda bisa mempertahankan status fragmen menggunakan {@link +android.os.Bundle}, jika proses aktivitas dimatikan dan Anda harus memulihkan status +fragmen bila aktivitas dibuat kembali. Anda bisa menyimpan status selama callback {@link +android.app.Fragment#onSaveInstanceState onSaveInstanceState()} fragmen dan memulihkannya selama +{@link android.app.Fragment#onCreate onCreate()}, {@link +android.app.Fragment#onCreateView onCreateView()}, atau {@link +android.app.Fragment#onActivityCreated onActivityCreated()}. Untuk informasi selengkapnya tentang menyimpan +status, lihat dokumen <a href="{@docRoot}guide/components/activities.html#SavingActivityState">Aktivitas</a> +.</p> + +<p>Perbedaan paling signifikan dalam daur hidup antara aktivitas dan fragmen ada +pada cara penyimpanannya dalam back-stack masing-masing. Aktivitas ditempatkan ke back-stack aktivitas +yang dikelola oleh sistem saat dihentikan, secara default (sehingga pengguna bisa mengarah kembali +ke aktivitas dengan tombol <em>Back</em>, seperti yang dibahas dalam <a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tugas dan Back-Stack</a>). +Akan tetapi, fragmen yang ditempatkan ke back-stack dikelola oleh aktivitas host hanya saat +Anda secara eksplisit meminta agar instance disimpan dengan memanggil {@link +android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} selama transaksi yang +menghapus fragmen.</p> + +<p>Jika tidak, pengelolaan daur hidup fragmen mirip sekali dengan mengelola daur hidup +aktivitas. Jadi, praktik yang sama untuk <a href="{@docRoot}guide/components/activities.html#Lifecycle">mengelola daur hidup +aktivitas</a> juga berlaku untuk fragmen. Namun yang perlu juga Anda pahami adalah bagaimana hidup +aktivitas memengaruhi hidup fragmen.</p> + +<p class="caution"><strong>Perhatian:</strong> Jika Anda memerlukan objek {@link android.content.Context} + dalam {@link android.app.Fragment}, Anda bisa memanggil {@link android.app.Fragment#getActivity()}. +Akan tetapi, berhati-hatilah memanggil {@link android.app.Fragment#getActivity()} hanya bila fragmen +terkait dengan aktivitas. Bila fragmen belum terkait, atau terlepas selama akhir daur +hidupnya, {@link android.app.Fragment#getActivity()} akan kembali nol.</p> + + +<h3 id="CoordinatingWithActivity">Mengoordinasi dengan daur hidup aktivitas</h3> + +<p>Daur hidup aktivitas tempat fragmen berada akan memengaruhi langsung siklus hidup +fragmen sedemikian rupa sehingga setiap callback daur hidup aktivitas menghasilkan callback yang sama untuk masing-masing +fragmen. Misalnya, bila aktivitas menerima {@link android.app.Activity#onPause}, masing-masing +fragmen dalam aktivitas akan menerima {@link android.app.Fragment#onPause}.</p> + +<p>Namun fragmen memiliki beberapa callback daur hidup ekstra, yang menangani interaksi +unik dengan aktivitas untuk melakukan tindakan seperti membangun dan memusnahkan UI fragmen. Metode callback +tambahan ini adalah:</p> + +<dl> + <dt>{@link android.app.Fragment#onAttach onAttach()}</dt> + <dd>Dipanggil bila fragmen telah dikaitkan dengan aktivitas ({@link +android.app.Activity} diteruskan di sini).</dd> + <dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt> + <dd>Dipanggil untuk membuat hierarki tampilan yang dikaitkan dengan fragmen.</dd> + <dt>{@link android.app.Fragment#onActivityCreated onActivityCreated()}</dt> + <dd>Dipanggil bila metode {@link android.app.Activity#onCreate +onCreate()} aktivitas telah dikembalikan.</dd> + <dt>{@link android.app.Fragment#onDestroyView onDestroyView()}</dt> + <dd>Dipanggil bila hierarki tampilan yang terkait dengan fragmen dihapus.</dd> + <dt>{@link android.app.Fragment#onDetach onDetach()}</dt> + <dd>Dipanggil bila fragmen diputuskan dari aktivitas.</dd> +</dl> + +<p>Aliran daur hidup fragmen, karena dipengaruhi oleh aktivitas host-nya, diilustrasikan oleh +gambar 3. Dalam gambar ini, Anda bisa melihat bagaimana setiap status aktivitas menentukan +metode callback mana yang mungkin diterima fragmen. Misalnya, saat aktivitas menerima call back {@link +android.app.Activity#onCreate onCreate()}, fragmen dalam aktivitas akan menerima tidak lebih +dari callback {@link android.app.Fragment#onActivityCreated onActivityCreated()}.</p> + +<p>Setelah status aktivitas diteruskan kembali, Anda bisa bebas menambah dan menghapus fragmen untuk +aktivitas tersebut. Sehingga, hanya saat aktivitas berada dalam status dilanjutkan, daur hidup fragmen bisa +berubah secara independen.</p> + +<p>Akan tetapi, saat aktivitas meninggalkan status dilanjutkan, fragmen akan kembali didorong +melalui daur hidupnya oleh aktivitas.</p> + + + + +<h2 id="Example">Contoh</h2> + +<p>Untuk merangkum semua yang telah dibahas dalam dokumen ini, berikut ini contoh aktivitas +yang menggunakan dua fragmen untuk membuat layout dua panel. Aktivitas di bawah ini menyertakan satu fragmen untuk +menampilkan daftar putar Shakespeare dan fragmen lainnya menampilkan rangkuman pemutaran bila dipilih dari +daftar. Aktivitas ini juga menunjukkan cara menyediakan konfigurasi fragmen berbeda, +berdasarkan konfigurasi layar.</p> + +<p class="note"><strong>Catatan:</strong> Kode sumber lengkap untuk aktivitas ini tersedia di +<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.html">{@code +FragmentLayout.java}</a>.</p> + +<p>Aktivitas utama akan menerapkan layout seperti biasa, selama {@link +android.app.Activity#onCreate onCreate()}:</p> + +{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java main} + +<p>Layout yang diterapkan adalah {@code fragment_layout.xml}:</p> + +{@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout} + +<p>Dengan layout ini, sistem akan membuat instance {@code TitlesFragment} (yang mencantumkan +judul) segera setelah aktivitas memuat layout, sementara {@link android.widget.FrameLayout} + (lokasi penempatan fragmen untuk menampilkan rangkuman pemutaran) menempati ruang di sisi kanan +layar, namun pada awalnya masih kosong. Seperti yang akan Anda lihat di bawah ini, sampai pengguna memilih item +dari daftar maka fragmen baru akan ditempatkan ke dalam {@link android.widget.FrameLayout}.</p> + +<p>Akan tetapi, tidak semua konfigurasi layar cukup lebar untuk menampilkan +daftar putar dan rangkuman secara berdampingan. Sehingga, layout di atas hanya digunakan untuk konfigurasi +layar mendatar, dengan menyimpannya di {@code res/layout-land/fragment_layout.xml}.</p> + +<p>Sehingga, bila layar berada dalam orientasi tegak, sistem akan menerapkan layout berikut, yang +tersimpan di {@code res/layout/fragment_layout.xml}:</p> + +{@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout} + +<p>Layout ini hanya menyertakan {@code TitlesFragment}. Ini artinya saat perangkat berada dalam +orientasi tegak, hanya judul daftar putar yang terlihat. Jadi, saat pengguna mengklik item +daftar dalam konfigurasi ini, aplikasi akan memulai aktivitas baru untuk menampilkan rangkuman, +sebagai ganti pemuatan fragmen kedua.</p> + +<p>Berikutnya, Anda bisa melihat bagaimana hal ini dilakukan dalam kelas fragmen. Pertama adalah {@code +TitlesFragment}, yang menampilkan judul daftar putar Shakespeare. Fragmen ini membuat ekstensi {@link +android.app.ListFragment} dan mengandalkannya itu untuk menangani sebagian besar pekerjaan tampilan daftar.</p> + +<p>Saat Anda memeriksa kode ini, perhatikan bahwa ada dua kemungkinan perilaku saat pengguna mengklik +item daftar: bergantung pada layout mana yang aktif, bisa membuat dan menampilkan fragmen +baru untuk menampilkan detail dalam aktivitas yang sama (menambahkan fragmen ke {@link +android.widget.FrameLayout}), atau memulai aktivitas baru (tempat fragmen ditampilkan).</p> + +{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java titles} + +<p>Fragmen kedua, {@code DetailsFragment} menampilkan rangkuman pemutaran untuk item yang dipilih dari +daftar dari {@code TitlesFragment}:</p> + +{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details} + +<p>Ingatlah dari kelas {@code TitlesFragment}, bahwa, jika pengguna mengklik item daftar dan +layout saat ini <em>tidak</em> menyertakan tampilan {@code R.id.details} (yaitu tempat +{@code DetailsFragment} berada), maka aplikasi memulai aktivitas {@code DetailsActivity} +untuk menampilkan konten item.</p> + +<p>Berikut ini adalah {@code DetailsActivity}, yang hanya menanamkan {@code DetailsFragment} untuk menampilkan rangkuman pemutaran +yang dipilih saat layar dalam orientasi tegak:</p> + +{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java +details_activity} + +<p>Perhatikan bahwa aktivitas ini selesai sendiri jika konfigurasi mendatar, sehingga aktivitas utama +bisa mengambil alih dan menampilkan {@code DetailsFragment} bersama {@code TitlesFragment}. +Ini bisa terjadi jika pengguna memulai {@code DetailsActivity} saat dalam orientasi tegak, namun kemudian +memutarnya menjadi mendatar (yang akan memulai lagi aktivitas saat ini).</p> + + +<p>Untuk contoh lainnya mengenai penggunaan fragmen (dan file sumber lengkap untuk contoh ini), +lihat aplikasi contoh Demo API yang tersedia di <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#Fragment"> +ApiDemos</a> (bisa diunduh dari <a href="{@docRoot}resources/samples/get.html">Komponen contoh SDK</a>).</p> + + diff --git a/docs/html-intl/intl/id/guide/components/fundamentals.jd b/docs/html-intl/intl/id/guide/components/fundamentals.jd new file mode 100644 index 000000000000..2c925e98edb0 --- /dev/null +++ b/docs/html-intl/intl/id/guide/components/fundamentals.jd @@ -0,0 +1,480 @@ +page.title=Dasar-Dasar Aplikasi +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + +<h2>Dalam dokumen ini</h2> +<ol> +<li><a href="#Components">Komponen Aplikasi</a> + <ol> + <li><a href="#ActivatingComponents">Mengaktifkan komponen</a></li> + </ol> +</li> +<li><a href="#Manifest">File Manifes</a> + <ol> + <li><a href="#DeclaringComponents">Mendeklarasikan komponen</a></li> + <li><a href="#DeclaringRequirements">Mendeklarasikan kebutuhan aplikasi</a></li> + </ol> +</li> +<li><a href="#Resources">Sumber Daya Aplikasi</a></li> +</ol> +</div> +</div> + +<p>Aplikasi Android ditulis dalam bahasa pemrograman Java. Android SDK Tools mengkompilasi +kode Anda—bersama data dan file sumber daya —ke dalam APK: <i>Paket Android</i>, +yaitu file arsip berekstensi {@code .apk}. Satu file APK berisi semua konten +aplikasi Android dan merupakan file yang digunakan perangkat berbasis Android untuk menginstal aplikasi.</p> + +<p>Setelah diinstal di perangkat, setiap aplikasi Android tinggal di sandbox keamanannya sendiri: </p> + +<ul> + <li>Sistem operasi Android merupakan sistem Linux multi-pengguna yang di dalamnya setiap +aplikasi adalah pengguna berbeda.</li> + +<li>Secara default, sistem menetapkan ID pengguna Linux unik kepada setiap aplikasi (ID ini hanya + digunakan oleh sistem dan tidak diketahui aplikasi). Sistem menetapkan izin +bagi semua file dalam aplikasi sehingga hanya ID pengguna yang diizinkan yang bisa mengaksesnya. </li> + +<li>Setiap proses memiliki mesin virtual (VM) sendiri, sehingga kode aplikasi yang berjalan secara terisolasi dari +aplikasi lainnya.</li> + +<li>Secara default, setiap aplikasi berjalan dalam proses Linux-nya sendiri. Android memulai proses +bila ada komponen aplikasi yang perlu dijalankan, kemudian mematikan proses bila tidak lagi diperlukan +atau bila sistem harus memulihkan memori untuk digunakan aplikasi lain.</li> +</ul> + +<p>Dengan cara ini, sistem Android mengimplementasikan <em>prinsip privilese minim</em>. Ini berarti, +secara default aplikasi hanya memiliki akses ke komponen yang diperlukannya untuk melakukan pekerjaannya dan +tidak lebih dari itu. Hal ini menghasilkan lingkungan yang sangat aman sehingga aplikasi tidak bisa mengakses bagian +sistem bila tidak diberi izin.</p> + +<p>Akan tetapi, ada beberapa cara bagi aplikasi untuk berbagi data dengan aplikasi lain dan bagi aplikasi +untuk mengakses layanan sistem:</p> + +<ul> + <li>Dua aplikasi bisa diatur untuk menggunakan ID pengguna Linux yang sama, +dalam hal ini keduanya bisa saling mengakses file masing-masing. Untuk menghemat sumber daya sistem, aplikasi dengan ID +pengguna yang sama juga bisa diatur agar berjalan dalam proses Linux yang sama dan menggunakan VM yang sama ( +aplikasi juga harus ditandatangani dengan sertifikat yang sama).</li> + <li>Aplikasi bisa meminta izin akses ke data perangkat seperti kontak +pengguna, pesan SMS, penyimpanan lepas-pasang (kartu SD), kamera, Bluetooth, dan lainnya. Semua +izin aplikasi harus diberikan oleh pengguna saat menginstal.</li> +</ul> + +<p>Hal tersebut mencakup dasar-dasar tentang cara aplikasi Android berada di dalam sistem. Bagian dokumen +selanjutnya memperkenalkan Anda pada:</p> +<ul> + <li>Komponen kerangka kerja inti yang mendefinisikan aplikasi.</li> + <li>File manifes tempat Anda mendeklarasikan komponen dan fitur yang diperlukan perangkat +untuk aplikasi.</li> + <li>Sumber daya yang terpisah dari kode aplikasi dan memungkinkan +aplikasi mengoptimalkan perilakunya untuk beragam konfigurasi perangkat.</li> +</ul> + + + +<h2 id="Components">Komponen Aplikasi</h2> + +<p>Komponen aplikasi adalah blok pembangun penting dari aplikasi Android. +Setiap komponen merupakan titik berbeda yang digunakan sistem untuk memasuki aplikasi. Tidak semua komponen +merupakan titik masuk sebenarnya bagi pengguna dan sebagian saling bergantung, namun masing-masing komponen tersedia +sebagai kesatuan sendiri dan memainkan peran tertentu—masing-masing merupakan +blok pembangun unik yang mendefinisikan perilaku aplikasi secara keseluruhan.</p> + +<p>Ada empat macam tipe komponen aplikasi. Setiap tipe memiliki kegunaan tersendiri +dan daur hidupnya sendiri yang mendefinisikan cara komponen dibuat dan dimusnahkan.</p> + +<p>Berikut ini empat tipe komponen aplikasi:</p> + +<dl> + +<dt><b>Aktivitas</b></dt> + +<dd>Sebuah <i>aktivitas</i> mewakili satu layar dengan antarmuka pengguna. Misalnya, +aplikasi email mungkin memiliki satu aktivitas yang menampilkan daftar email +baru, aktivitas lain untuk menulis email, dan aktivitas satunya lagi untuk membaca email. Walaupun +semua aktivitas bekerja sama untuk membentuk pengalaman pengguna yang kohesif dalam aplikasi email, +masing-masing tidak saling bergantung. Karenanya, aplikasi berbeda bisa memulai +salah satu aktivitas ini (jika aplikasi email mengizinkannya). Misalnya, aplikasi kamera bisa memulai +aktivitas dalam aplikasi email yang membuat email baru agar pengguna bisa berbagi gambar. + +<p>Aktivitas diimplementasikan sebagai subkelas {@link android.app.Activity} dan Anda bisa mengetahui selengkapnya +tentang hal ini dalam panduan pengembang <a href="{@docRoot}guide/components/activities.html">Aktivitas</a> +.</p> +</dd> + + +<dt><b>Layanan</b></dt> + +<dd>Sebuah <i>layanan</i> adalah komponen yang berjalan di latar belakang untuk melakukan +operasi yang berjalan lama atau untuk melakukan pekerjaan bagi proses jarak jauh. Layanan +tidak menyediakan antarmuka pengguna. Misalnya, sebuah layanan bisa memutar musik di latar belakang sementara +pengguna berada dalam aplikasi lain, atau layanan bisa menarik data lewat jaringan tanpa +memblokir interaksi pengguna dengan aktivitas. Komponen lain, seperti aktivitas, bisa memulai +layanan dan membiarkannya berjalan atau mengikat layanan untuk berinteraksi dengannya. + +<p>Layanan diimplementasikan sebagai subkelas {@link android.app.Service} dan Anda bisa mengetahui selengkapnya +tentang hal ini dalam panduan +pengembang <a href="{@docRoot}guide/components/services.html">Layanan</a>.</p> +</dd> + + +<dt><b>Penyedia konten</b></dt> + +<dd>Sebuah <i>penyedia konten</i> mengelola seperangkat data-bersama aplikasi. Anda bisa menyimpan data +dalam sistem file, database SQLite, di web, atau lokasi penyimpanan permanen lainnya +yang bisa diakses aplikasi. Melalui penyedia konten, aplikasi lain bisa melakukan query atau bahkan +memodifikasi data (jika penyedia konten mengizinkannya). Misalnya, sistem Android menyediakan penyedia +konten yang mengelola informasi kontak pengguna. Karenanya, setiap aplikasi +dengan izin yang sesuai bisa melakukan query mengenai bagian dari penyedia konten (seperti {@link +android.provider.ContactsContract.Data}) untuk membaca dan menulis informasi tentang orang tertentu. + +<p>Penyedia konten juga berguna untuk membaca dan menulis data privat ke aplikasi Anda +dan tidak dibagikan. Misalnya, aplikasi contoh <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> menggunakan +penyedia konten untuk menyimpan catatan.</p> + +<p>Penyedia konten diimplementasikan sebagai subkelas {@link android.content.ContentProvider} +dan harus mengimplementasikan seperangkat standar API yang memungkinkan aplikasi +lain melakukan transaksi. Untuk informasi selengkapnya, lihat panduan pengembang +<a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p> +</dd> + + +<dt><b>Penerima siaran</b></dt> + +<dd>Sebuah <i>penerima siaran</i> adalah komponen yang merespons pengumuman siaran dalam lingkup +sistem. Banyak siaran yang berasal dari sistem—misalnya, siaran yang mengumumkan bahwa +layar telah dimatikan, baterai lemah, atau gambar telah direkam. +Aplikasi juga bisa memulai siaran—misalnya untuk menginformasikan ke +aplikasi lain bahwa sebagian data telah diunduh ke perangkat dan bisa digunakan aplikasi lain tersebut. Walaupun penerima +siaran tidak menampilkan antarmuka pengguna, penerima bisa <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">membuat pemberitahuan baris status</a> +untuk memberi tahu pengguna kapan kejadian siaran dilakukan. Meskipun penerima siaran umumnya cuma menjadi +"gerbang" untuk komponen lain dan dimaksudkan untuk melakukan pekerjaan dalam jumlah sangat minim. Misalnya +, penerima siaran bisa menjalankan layanan untuk melakukan beberapa pekerjaan berdasarkan kejadian. + +<p>Penerima siaran diimplementasikan sebagai subkelas {@link android.content.BroadcastReceiver} +dan setiap siaran dikirim sebagai objek {@link android.content.Intent}. Untuk informasi selengkapnya, +lihat kelas {@link android.content.BroadcastReceiver}.</p> +</dd> + +</dl> + + + +<p>Aspek unik dari desain sistem Android adalah aplikasi mana pun bisa memulai +komponen aplikasi lain. Misalnya, jika Anda menginginkan pengguna mengambil +foto dengan kamera perangkat, bisa saja aplikasi lain yang melakukannya dan aplikasi +Anda bisa menggunakannya, sebagai ganti mengembangkan aktivitas sendiri untuk mengambil foto. Anda tidak +harus menyatukan atau bahkan menautkan ke kode dari aplikasi kamera. +Sebagai gantinya, Anda tinggal memulai aktivitas di aplikasi kamera yang akan mengambil +foto. Bila selesai, foto akan dikembalikan ke aplikasi sehingga Anda bisa menggunakannya. Bagi pengguna, +kamera seakan menjadi bagian dari aplikasi Anda.</p> + +<p>Saat sistem memulai komponen, sistem akan memulai proses untuk aplikasi itu (jika +belum berjalan) dan membuat instance kelas yang diperlukan untuk komponen. Misalnya, jika aplikasi Anda +memulai aktivitas dalam aplikasi kamera yang mengambil foto, aktivitas itu akan +berjalan dalam proses yang dimiliki oleh aplikasi kamera, bukan dalam proses aplikasi Anda. +Karenanya, tidak seperti aplikasi di sebagian besar sistem lain, aplikasi Android tidak memiliki titik +masuk tunggal (misalnya tidak ada fungsi {@code main()}).</p> + +<p>Karena sistem menjalankan setiap aplikasi dalam proses terpisah dengan izin file yang +membatasi akses ke aplikasi lain, aplikasi Anda tidak bisa langsung mengaktifkan komponen dari aplikasi lain. Akan tetapi, sistem +Android bisa melakukannya. Jadi, untuk mengaktifkan +komponen dalam aplikasi lain, Anda harus mengirim pesan ke sistem yang menetapkan <em>intent</em> Anda untuk memulai +komponen tertentu. Selanjutnya sistem akan mengaktifkan komponen untuk Anda.</p> + + +<h3 id="ActivatingComponents">Mengaktifkan Komponen</h3> + +<p>Tiga dari empat tipe komponen—aktivitas, layanan, dan +penerima siaran—diaktifkan oleh pesan asinkron yang disebut <em>intent</em>. +Intent saling mengikat setiap komponen saat runtime (Anda bisa menganggapnya +sebagai pembawa pesan yang meminta tindakan dari komponen lain), baik komponen itu milik aplikasi Anda +atau milik aplikasi lain.</p> + +<p>Intent dibuat dengan objek {@link android.content.Intent}, yang mendefinisikan pesan untuk +mengaktifkan komponen tertentu atau komponen <em>tipe</em> komponen tertentu—masing-masing intent +bisa eksplisit atau implisit.</p> + +<p>Untuk aktivitas dan layanan, intent mendefinisikan tindakan yang akan dilakukan (misalnya, untuk "melihat" atau +"mengirim" sesuatu) dan mungkin menetapkan URI data untuk ditindaklanjuti (salah satu hal yang mungkin perlu diketahui +oleh komponen yang akan dimulai). Misalnya, intent mungkin menyampaikan permintaan suatu +aktivitas untuk menampilkan gambar atau membuka halaman web. Dalam beberapa kasus, Anda bisa memulai +aktivitas untuk menerima hasil, dalam hal ini, aktivitas juga akan mengembalikan hasil +dalam {@link android.content.Intent} (misalnya Anda bisa mengeluarkan intent agar +pengguna bisa memilih kontak pribadi dan memintanya dikembalikan kepada Anda—intent yang dikembalikan menyertakan URI yang +menunjuk ke kontak yang dipilih).</p> + +<p>Untuk penerima siaran, intent hanya mendefinisikan +pengumuman yang sedang disiarkan (misalnya, siaran untuk menunjukkan baterai perangkat hampir habis +hanya menyertakan string tindakan yang menunjukkan "baterai hampir habis").</p> + +<p>Tipe komponen lainnya dan penyedia konten, tidak diaktifkan oleh intent. Melainkan +diaktifkan saat ditargetkan oleh permintaan dari {@link android.content.ContentResolver}. Resolver +konten menangani semua transaksi langsung dengan penyedia konten sehingga komponen yang melakukan +transaksi dengan penyedia tidak perlu dan sebagai gantinya memanggil metode pada objek {@link +android.content.ContentResolver}. Ini membuat lapisan abstraksi antara penyedia +konten dan komponen yang meminta informasi (demi keamanan).</p> + +<p>Ada beberapa metode terpisah untuk mengaktifkan masing-masing tipe komponen:</p> +<ul> + <li>Anda bisa memulai aktivitas (atau memberinya pekerjaan baru) dengan +meneruskan {@link android.content.Intent} ke {@link android.content.Context#startActivity +startActivity()} atau {@link android.app.Activity#startActivityForResult startActivityForResult()} +(bila Anda ingin aktivitas mengembalikan hasil).</li> + <li>Anda bisa memulai layanan (atau memberikan instruksi baru ke layanan yang sedang berlangsung) dengan +meneruskan {@link android.content.Intent} ke {@link android.content.Context#startService +startService()}. Atau Anda bisa mengikat ke layanan dengan meneruskan {@link android.content.Intent} ke +{@link android.content.Context#bindService bindService()}.</li> + <li>Anda bisa memulai siaran dengan meneruskan {@link android.content.Intent} ke metode seperti +{@link android.content.Context#sendBroadcast(Intent) sendBroadcast()}, {@link +android.content.Context#sendOrderedBroadcast(Intent, String) sendOrderedBroadcast()}, atau {@link +android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</li> + <li>Anda bisa melakukan query ke penyedia konten dengan memanggil {@link +android.content.ContentProvider#query query()} pada {@link android.content.ContentResolver}.</li> +</ul> + +<p>Untuk informasi selengkapnya tentang menggunakan intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter + Intent</a>. Informasi selengkapnya tentang mengaktifkan komponen +tertentu juga tersedia dalam dokumen berikut: <a href="{@docRoot}guide/components/activities.html">Aktivitas</a>, <a href="{@docRoot}guide/components/services.html">Layanan</a>, {@link +android.content.BroadcastReceiver} dan <a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p> + + +<h2 id="Manifest">File Manifes</h2> + +<p>Sebelum sistem Android bisa memulai komponen aplikasi, sistem harus mengetahui +keberadaan komponen dengan membaca file {@code AndroidManifest.xml} aplikasi (file +"manifes"). Aplikasi Anda harus mendeklarasikan semua komponennya dalam file ini, yang harus menjadi akar +dari direktori proyek aplikasi.</p> + +<p>Manifes melakukan banyak hal selain mendeklarasikan komponen aplikasi, +seperti:</p> +<ul> + <li>Mengidentifikasi izin pengguna yang diperlukan aplikasi, seperti akses Internet atau +akses-baca ke kontak pengguna.</li> + <li>Mendeklarasikan <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a> + minimum yang diperlukan aplikasi, berdasarkan API yang digunakan aplikasi.</li> + <li>Mendeklarasikan fitur perangkat keras dan perangkat lunak yang diperlukan aplikasi, seperti kamera, +layanan Bluetooth, atau layar multisentuh.</li> + <li>Pustaka API aplikasi perlu ditautkan (selain +API kerangka kerja Android), seperti pustaka +<a href="http://code.google.com/android/add-ons/google-apis/maps-overview.html">Google Maps.</a></li> + <li>Dan lainnya</li> +</ul> + + +<h3 id="DeclaringComponents">Mendeklarasikan komponen</h3> + +<p>Tugas utama manifes adalah menginformasikan komponen aplikasi pada sistem. Misalnya, +file manifes bisa mendeklarasikan aktivitas sebagai berikut: </p> + +<pre> +<?xml version="1.0" encoding="utf-8"?> +<manifest ... > + <application android:icon="@drawable/app_icon.png" ... > + <activity android:name="com.example.project.ExampleActivity" + android:label="@string/example_label" ... > + </activity> + ... + </application> +</manifest></pre> + +<p>Dalam elemen <code><a +href="{@docRoot}guide/topics/manifest/application-element.html"><application></a></code> +, atribut {@code android:icon} menunjuk ke sumber daya untuk ikon yang mengidentifikasi +aplikasi.</p> + +<p>Dalam elemen <code><a +href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>, +atribut {@code android:name} menetapkan nama kelas yang sepenuhnya memenuhi syarat subkelas {@link +android.app.Activity} dan atribut {@code android:label} menetapkan string yang akan +digunakan sebagai label yang terlihat oleh pengguna untuk aktivitas tersebut.</p> + +<p>Anda harus mendeklarasikan semua komponen aplikasi dengan cara ini:</p> +<ul> + <li>Elemen <code><a +href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> untuk +aktivitas</li> + <li>Elemen <code><a +href="{@docRoot}guide/topics/manifest/service-element.html"><service></a></code> untuk +layanan</li> + <li>Elemen <code><a +href="{@docRoot}guide/topics/manifest/receiver-element.html"><receiver></a></code> untuk +penerima siaran</li> + <li>Elemen <code><a +href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a></code> untuk +penyedia konten</li> +</ul> + +<p>Aktivitas, layanan, dan penyedia konten yang Anda sertakan dalam kode sumber, namun tidak +dideklarasikan dalam manifes, tidak akan terlihat pada sistem dan, akibatnya, tidak pernah bisa berjalan. Akan tetapi, +penerima siaran +bisa dideklarasikan dalam manifes atau dibuat secara dinamis dalam kode (sebagai objek +{@link android.content.BroadcastReceiver}) dan didaftarkan pada sistem dengan memanggil +{@link android.content.Context#registerReceiver registerReceiver()}.</p> + +<p>Untuk informasi selengkapnya tentang cara menstrukturkan file manifes untuk aplikasi Anda, +lihat dokumentasi <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">File AndroidManifest.xml</a>. </p> + + + +<h3 id="DeclaringComponentCapabilities">Mendeklarasikan kemampuan komponen</h3> + +<p>Seperti telah dibahas di atas, dalam <a href="#ActivatingComponents">Mengaktifkan Komponen</a>, Anda bisa menggunakan +{@link android.content.Intent} untuk memulai aktivitas, layanan, dan penerima siaran. Anda bisa +melakukannya dengan menamai komponen sasaran secara eksplisit (menggunakan nama kelas komponen) dalam intent. Akan tetapi, +kemampuan intent sebenarnya ada pada konsep <em>intent implisit</em>. Intent implisit +cuma menjelaskan tipe tindakan yang akan dilakukan (dan, secara opsional, data tempat Anda ingin +melakukan tindakan) dan memungkinkan sistem untuk menemukan komponen pada perangkat yang bisa melakukan +tindakan tersebut dan memulainya. Jika ada banyak komponen yang bisa melakukan tindakan yang dijelaskan oleh intent, +maka pengguna bisa memilih komponen yang akan digunakan.</p> + +<p>Cara sistem mengidentifikasi komponen yang bisa merespons intent adalah dengan membandingkan +intent yang diterima dengan <i>filter intent</i> yang disediakan dalam file manifes aplikasi lainnya pada +perangkat.</p> + +<p>Bila mendeklarasikan aktivitas dalam manifes aplikasi, secara opsional Anda bisa menyertakan +filter intent yang mendeklarasikan kemampuan aktivitas agar bisa merespons intent dari +aplikasi lain. Anda bisa mendeklarasikan filter intent untuk komponen dengan +menambahkan elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code +<intent-filter>}</a> sebagai anak elemen deklarasi komponen.</p> + +<p>Misalnya, jika Anda telah membangun aplikasi email dengan aktivitas untuk menulis email baru, Anda bisa +mendeklarasikan filter intent untuk merespons intent "kirim" (untuk mengirim email baru) seperti ini:</p> +<pre> +<manifest ... > + ... + <application ... > + <activity android:name="com.example.project.ComposeEmailActivity"> + <intent-filter> + <action android:name="android.intent.action.SEND" /> + <data android:type="*/*" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + </activity> + </application> +</manifest> +</pre> + +<p>Kemudian, jika aplikasi lain membuat intent dengan tindakan {@link +android.content.Intent#ACTION_SEND} dan meneruskannya ke {@link android.app.Activity#startActivity +startActivity()}, sistem bisa memulai aktivitas Anda agar pengguna bisa menulis draf dan mengirim +email.</p> + +<p>Untuk informasi selengkapnya tentang membuat filter intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>. +</p> + + + +<h3 id="DeclaringRequirements">Mendeklarasikan kebutuhan aplikasi</h3> + +<p>Ada berbagai macam perangkat yang didukung oleh Android dan tidak +semuanya menyediakan fitur dan kemampuan yang sama. Agar aplikasi Anda tidak dihapus pada perangkat yang tidak memiliki +fitur yang diperlukan aplikasi, Anda harus jelas mendefinisikan profil mengenai +tipe perangkat yang didukung aplikasi dengan mendeklarasikan kebutuhan perangkat dan perangkat lunak dalam file +manifes. Kebanyakan deklarasi ini hanya bersifat informasi dan sistem tidak +membacanya, namun layanan eksternal seperti Google Play akan membacanya untuk menyediakan +penyaringan bagi pengguna saat mereka mencari aplikasi dari perangkat.</p> + +<p>Misalnya, jika aplikasi memerlukan kamera dan menggunakan API yang disediakan dalam Android 2.1 (<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a> 7) +, Anda harus mendeklarasikannya sebagai kebutuhan dalam file manifes seperti ini:</p> + +<pre> +<manifest ... > + <uses-feature android:name="android.hardware.camera.any" + android:required="true" /> + <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" /> + ... +</manifest> +</pre> + +<p>Sekarang, perangkat yang <em>tidak</em> memiliki kamera dan menggunakan +Android versi <em>lebih rendah</em> dari 2.1 tidak bisa menginstal aplikasi Anda dari Google Play.</p> + +<p>Akan tetapi, bisa juga mendeklarasikan bahwa aplikasi Anda menggunakan kamera, namun tidak +<em>mengharuskannya</em>. Dalam hal itu, aplikasi Anda harus mengatur atribut <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#required">{@code required}</a> + ke {@code "false"} dan memeriksa saat runtime apakah +perangkat memiliki kamera dan menonaktifkan setiap fitur kamera yang sesuai.</p> + +<p>Informasi selengkapnya tentang cara mengelola kompatibilitas aplikasi dengan +perangkat yang berbeda disediakan dalam dokumen +<a href="{@docRoot}guide/practices/compatibility.html">Kompatibilitas Perangkat</a>.</p> + + + +<h2 id="Resources">Sumber Daya Aplikasi</h2> + +<p>Aplikasi Android tidak hanya terdiri dari kode—Aplikasi memerlukan sumber daya yang +terpisah dari kode sumber, seperti gambar, file audio, dan apa saja yang berkaitan dengan +presentasi visual dari aplikasi. Misalnya, Anda harus mendefinisikan animasi, menu, gaya, warna, +dan layout antarmuka pengguna aktivitas dengan file XML. Penggunaan sumber daya aplikasi +mempermudah pembaruan berbagai karakteristik aplikasi Anda tanpa memodifikasi kode dan—dengan menyediakan +seperangkat sumber daya alternatif—memungkinkan Anda mengoptimalkan aplikasi untuk berbagai konfigurasi +perangkat berbeda (seperti bahasa dan ukuran layar yang berbeda).</p> + +<p>Untuk setiap sumber daya yang Anda sertakan dalam proyek Android, alat bawaan SDK akan mendefinisikan ID integer +unik, yang bisa Anda gunakan untuk mengacu sumber daya dari kode aplikasi atau dari sumber daya lainnya yang +didefinisikan dalam XML. Misalnya, jika aplikasi berisi file gambar bernama {@code +logo.png} (disimpan dalam direktori {@code res/drawable/}), alat SDK akan menghasilkan ID sumber daya +bernama {@code R.drawable.logo}, yang bisa Anda gunakan untuk mengacu gambar dan memasukkannya dalam +antarmuka pengguna.</p> + +<p>Salah satu aspek paling penting dari penyediaan sumber daya yang terpisah dari +kode sumber adalah kemampuan Anda menyediakan sumber daya alternatif untuk konfigurasi perangkat +yang berbeda. Misalnya, dengan mendefinisikan string UI dalam XML, Anda bisa menerjemahkan string ke dalam +bahasa lain dan menyimpan string itu dalam file terpisah. Kemudian, berdasarkan <em>qualifier</em> +bahasa yang ditambahkan ke nama direktori sumber daya (seperti {@code res/values-fr/} untuk nilai +string Prancis) dan pengaturan bahasa pengguna, sistem Android akan menerapkan string bahasa yang sesuai +untuk UI Anda.</p> + +<p>Android mendukung banyak <em>qualifier</em> berbeda untuk sumber daya alternatif Anda. Qualifier +adalah string pendek yang Anda sertakan dalam nama direktori sumber +daya untuk mendefinisikan konfigurasi perangkat yang harus digunakan sumber daya tersebut. Contoh lainnya, +Anda harus sering membuat layout berbeda untuk aktivitas, bergantung pada +orientasi layar dan ukuran perangkat. Misalnya, saat layar perangkat dalam orientasi +tegak, Anda mungkin ingin layout tombolnya vertikal, tetapi saat layar dalam orientasi +mendatar, tombolnya harus sejajar horizontal. Untuk mengubah layout +sesuai orientasi, Anda bisa mendefinisikan dua layout berbeda dan menerapkan qualifier yang +tepat untuk setiap nama direktori layout. Kemudian, sistem secara otomatis menerapkan +layout yang tepat sesuai dengan orientasi perangkat saat ini.</p> + +<p>Untuk informasi selengkapnya tentang berbagai jenis sumber daya yang bisa disertakan dalam aplikasi dan cara +membuat sumber daya alternatif untuk konfigurasi perangkat berbeda, bacalah <a href="{@docRoot}guide/topics/resources/providing-resources.html">Menyediakan Sumber Daya</a>.</p> + + + +<div class="next-docs"> +<div class="col-6"> + <h2 class="norule">Teruskan membaca tentang:</h2> + <dl> + <dt><a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a> + </dt> + <dd>Informasi tentang cara menggunakan API {@link android.content.Intent} untuk + mengaktifkan komponen aplikasi, seperti aktivitas dan layanan, dan cara menyediakan komponen aplikasi + untuk digunakan oleh aplikasi lain.</dd> + <dt><a href="{@docRoot}guide/components/activities.html">Aktivitas</a></dt> + <dd>Informasi tentang cara membuat instance kelas {@link android.app.Activity}, +yang menyediakan layar tersendiri dalam aplikasi bersama antarmuka pengguna.</dd> + <dt><a href="{@docRoot}guide/topics/resources/providing-resources.html">Menyediakan Sumber Daya</a></dt> + <dd>Informasi tentang cara aplikasi Android disusun untuk memisahkan sumber daya aplikasi dari +kode aplikasi, termasuk cara Anda bisa menyediakan sumber daya alternatif untuk +konfigurasi perangkat tertentu. + </dd> + </dl> +</div> +<div class="col-6"> + <h2 class="norule">Anda juga mungkin tertarik dengan:</h2> + <dl> + <dt><a href="{@docRoot}guide/practices/compatibility.html">Kompatibilitas Perangkat</a></dt> + <dd>Informasi tentang cara kerja Android pada berbagai tipe perangkat dan +pengenalan mengenai cara mengoptimalkan aplikasi untuk setiap perangkat atau membatasi ketersediaan aplikasi Anda untuk +perangkat berbeda.</dd> + <dt><a href="{@docRoot}guide/topics/security/permissions.html">Izin Sistem</a></dt> + <dd>Informasi tentang cara Android membatasi akses aplikasi pada API tertentu dengan sistem izin +yang mengharuskan persetujuan pengguna agar aplikasi dapat menggunakan API tersebut.</dd> + </dl> +</div> +</div> + diff --git a/docs/html-intl/intl/id/guide/components/index.jd b/docs/html-intl/intl/id/guide/components/index.jd new file mode 100644 index 000000000000..de40b22d875e --- /dev/null +++ b/docs/html-intl/intl/id/guide/components/index.jd @@ -0,0 +1,57 @@ +page.title=Komponen Aplikasi +page.landing=true +page.landing.intro=Kerangka kerja aplikasi Android memungkinkan Anda membuat aplikasi yang kaya dan inovatif menggunakan seperangkat komponen yang dapat digunakan kembali. Bagian ini menjelaskan cara membangun komponen yang mendefinisikan blok pembangun aplikasi Anda dan cara menghubungkannya bersama menggunakan intent. +page.metaDescription=Kerangka kerja aplikasi Android memungkinkan Anda membuat aplikasi yang kaya dan inovatif menggunakan seperangkat komponen yang dapat digunakan kembali. Bagian ini menjelaskan cara membangun komponen yang mendefinisikan blok pembangun aplikasi Anda dan cara menghubungkannya bersama menggunakan intent. +page.landing.image=images/develop/app_components.png +page.image=images/develop/app_components.png + +@jd:body + +<div class="landing-docs"> + + <div class="col-6"> + <h3>Artikel Blog</h3> + + <a href="http://android-developers.blogspot.com/2012/05/using-dialogfragments.html"> + <h4>Menggunakan DialogFragments</h4> + <p>Dalam posting ini, saya akan menunjukkan cara menggunakan DialogFragments dengan pustaka dukungan v4 (untuk kompatibilitas mundur pada perangkat sebelum Honeycomb) untuk menunjukkan dialog edit sederhana dan mengembalikan hasil ke Aktivitas pemanggil menggunakan antarmuka.</p> + </a> + + <a href="http://android-developers.blogspot.com/2011/03/fragments-for-all.html"> + <h4>Fragmen Untuk Semua</h4> + <p>Hari ini kami telah merilis pustaka statis yang memperlihatkan API Fragment yang sama (serta LoaderManager baru dan beberapa kelas lain) agar aplikasi yang kompatibel dengan Android 1.6 atau yang lebih baru bisa menggunakan fragmen untuk membuat antarmuka pengguna yang kompatibel dengan tablet. </p> + </a> + + <a href="http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html"> + <h4>Multithreading untuk Kinerja</h4> + <p>Praktik yang baik dalam membuat aplikasi yang responsif adalah memastikan thread UI utama Anda +melakukan pekerjaan minimum. Setiap tugas yang berpotensi lama dan dapat membuat aplikasi mogok harus +ditangani di thread berbeda.</p> + </a> + </div> + + <div class="col-6"> + <h3>Pelatihan</h3> + + <a href="http://developer.android.com/training/basics/activity-lifecycle/index.html"> + <h4>Mengelola Daur Hidup Aktivitas</h4> + <p>Bagian ini menjelaskan pentingnya metode callback daur hidup yang diterima setiap instance Aktivitas +dan cara menggunakannya sehingga aktivitas Anda melakukan yang diharapkan pengguna dan tidak menghabiskan sumber daya sistem +saat aktivitas tidak membutuhkannya.</p> + </a> + + <a href="http://developer.android.com/training/basics/fragments/index.html"> + <h4>Membangun UI Dinamis dengan Fragmen</h4> + <p>Bagian ini menunjukkan kepada Anda cara membuat pengalaman pengguna yang dinamis dengan fragmen dan mengoptimalkan +pengalaman pengguna aplikasi Anda dengan berbagai ukuran layar, sekaligus terus mendukung +perangkat yang menjalankan versi sebelumnya, sesudah versi Android 1.6.</p> + </a> + + <a href="http://developer.android.com/training/sharing/index.html"> + <h4>Berbagi Konten</h4> + <p>Bagian ini membahas beberapa cara umum untuk mengirim dan menerima konten antar +aplikasi menggunakan API Intent dan objek ActionProvider.</p> + </a> + </div> + +</div> diff --git a/docs/html-intl/intl/id/guide/components/intents-filters.jd b/docs/html-intl/intl/id/guide/components/intents-filters.jd new file mode 100644 index 000000000000..8e89b5db81c7 --- /dev/null +++ b/docs/html-intl/intl/id/guide/components/intents-filters.jd @@ -0,0 +1,899 @@ +page.title=Intent dan Filter Intent +page.tags="IntentFilter" +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + +<h2>Dalam dokumen ini</h2> +<ol> + <li><a href="#Types">Tipe Intent</a></li> + <li><a href="#Building">Membangun Intent</a> + <ol> + <li><a href="#ExampleExplicit">Contoh intent eksplisit</a></li> + <li><a href="#ExampleSend">Contoh intent implisit</a></li> + <li><a href="#ForceChooser">Memaksakan pemilih aplikasi</a></li> + </ol> + </li> + <li><a href="#Receiving">Menerima Intent Implisit</a> + <ol> + <li><a href="#ExampleFilters">Contoh filter</a></li> + </ol> + </li> + <li><a href="#PendingIntent">Menggunakan Intent Tertunda</a></li> + <li><a href="#Resolution">Resolusi Intent</a> + <ol> + <li><a href="#ActionTest">Pengujian tindakan</a></li> + <li><a href="#CategoryTest">Pengujian kategori</a></li> + <li><a href="#DataTest">Pengujian data</a></li> + <li><a href="#imatch">Pencocokan intent</a></li> + </ol> + </li> +</ol> + +<h2>Lihat juga</h2> +<ol> +<li><a href="{@docRoot}training/basics/intents/index.html">Berinteraksi dengan Aplikasi Lain</a></li> +<li><a href="{@docRoot}training/sharing/index.html">Berbagi Konten</a></li> +</ol> + +</div> +</div> + + + + +<p>{@link android.content.Intent} merupakan objek pertukaran pesan yang bisa Anda gunakan untuk meminta tindakan +dari <a href="{@docRoot}guide/components/fundamentals.html#Components">komponen aplikasi</a> lain. +Walaupun intent memudahkan komunikasi antarkomponen dalam beberapa cara, ada tiga +kasus-penggunaan dasar:</p> + +<ul> +<li><b>Untuk memulai aktivitas:</b> +<p>{@link android.app.Activity} menyatakan satu layar dalam aplikasi. Anda bisa memulai instance +baru {@link android.app.Activity} dengan meneruskan {@link android.content.Intent} +ke {@link android.content.Context#startActivity startActivity()}. {@link android.content.Intent} +menjelaskan aktivitas yang akan dimulai dan membawa data yang diperlukan.</p> + +<p>Jika Anda ingin menerima hasil dari aktivitas bila selesai, +panggil {@link android.app.Activity#startActivityForResult +startActivityForResult()}. Aktivitas Anda menerima hasil +sebagai objek {@link android.content.Intent} terpisah dalam callback {@link +android.app.Activity#onActivityResult onActivityResult()} aktivitas Anda. +Untuk informasi selengkapnya, lihat panduan <a href="{@docRoot}guide/components/activities.html">Aktivitas</a>.</p></li> + +<li><b>Untuk memulai layanan:</b> +<p>{@link android.app.Service} adalah komponen yang melakukan operasi di latar belakang +tanpa antarmuka pengguna. Anda bisa memulai layanan untuk melakukan operasi satu-kali +(misalnya mengunduh file) dengan meneruskan {@link android.content.Intent} +ke {@link android.content.Context#startService startService()}. {@link android.content.Intent} +menjelaskan layanan yang akan dimulai dan membawa data yang diperlukan.</p> + +<p>Jika layanan didesain dengan antarmuka pengguna klien-server, Anda bisa mengikat ke layanan +dari komponen lain dengan meneruskan {@link android.content.Intent} ke {@link +android.content.Context#bindService bindService()}</code>. Untuk informasi selengkapnya, lihat panduan <a href="{@docRoot}guide/components/services.html">Layanan</a>.</p></li> + +<li><b>Untuk mengirim siaran:</b> +<p>Siaran adalah pesan yang bisa diterima aplikasi apa saja. Sistem menyampaikan beragam siaran +untuk kejadian sistem, misalnya saat sistem booting atau saat perangkat mulai mengisi daya. +Anda bisa mengirim siaran ke aplikasi lain dengan meneruskan {@link android.content.Intent} +ke {@link android.content.Context#sendBroadcast(Intent) sendBroadcast()}, +{@link android.content.Context#sendOrderedBroadcast(Intent, String) +sendOrderedBroadcast()}, atau {@link +android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</p> +</li> +</ul> + + + + +<h2 id="Types">Tipe Intent</h2> + +<p>Ada dua tipe intent:</p> + +<ul> +<li><b>Intent eksplisit</b> menetapkan komponen untuk memulai dengan nama ( +nama kelas yang sepenuhnya memenuhi syarat). Anda biasanya akan menggunakan intent eksplisit untuk memulai sebuah komponen +dalam aplikasi sendiri, karena Anda mengetahui nama kelas dari aktivitas atau layanan yang ingin dimulai. +Misalnya, mulai aktivitas baru sebagai respons terhadap tindakan pengguna atau mulai layanan untuk mengunduh +file di latar belakang.</li> + +<li><b>Intent implisit</b> tidak menetapkan komponen tertentu, melainkan mendeklarasikan tindakan umum +yang dilakukan, yang memungkinkan komponen aplikasi lain untuk menanganinya. Misalnya, jika Anda ingin +menampilkan sebuah lokasi di peta pada pengguna, Anda bisa menggunakan intent implisit untuk meminta aplikasi lain +yang mampu untuk menunjukkan lokasi yang telah ditetapkan di peta tersebut.</li> +</ul> + +<p>Saat Anda membuat intent eksplisit untuk memulai aktivitas atau layanan, sistem akan segera +memulai komponen aplikasi yang telah ditetapkan dalam objek {@link android.content.Intent}.</p> + +<div class="figure" style="width:446px"> +<img src="{@docRoot}images/components/intent-filters@2x.png" width="446" alt="" /> +<p class="img-caption"><strong>Gambar 1.</strong> Ilustrasi yang menggambarkan cara intent implisit +disampaikan melalui sistem untuk memulai aktivitas lain: <b>[1]</b> <em>Aktivitas A</em> membuat sebuah +{@link android.content.Intent} dengan keterangan tindakan dan meneruskannya ke {@link +android.content.Context#startActivity startActivity()}. <b>[2]</b> Sistem Android akan mencari semua +aplikasi untuk filter intent yang cocok dengan intent tersebut. Bila cocok, <b>[3]</b> sistem akan +memulai aktivitas mencocokkan (<em>Aktivitas B</em>) dengan memanggil metode {@link +android.app.Activity#onCreate onCreate()} dan meneruskannya ke {@link android.content.Intent}. +</p> +</div> + +<p>Bila Anda membuat intent implisit, sistem Android akan menemukan komponen yang sesuai untuk memulai +dengan membandingkan konten intent dengan <em>filter intent</em> yang dideklarasikan dalam <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">file manifes</a> aplikasi lain di +perangkat. Jika intent cocok dengan filter intent, sistem akan memulai komponen tersebut dan mengiriminya +objek {@link android.content.Intent}. Jika banyak filter intent yang kompatibel, sistem +menampilkan dialog sehingga pengguna bisa memilih aplikasi yang akan digunakan.</p> + +<p>Filter intent adalah ekspresi dalam file manifes aplikasi yang +menetapkan tipe intent yang akan diterima +komponen. Misalnya, dengan mendeklarasikan intent filter untuk aktivitas, +Anda akan memungkinkan aplikasi lain untuk langsung memulai aktivitas Anda dengan intent tertentu. +Demikian pula, jika Anda <em>tidak</em> mendeklarasikan filter intent untuk suatu aktivitas, maka aktivitas tersebut hanya bisa dimulai +dengan intent eksplisit.</p> + +<p class="caution"><strong>Perhatian:</strong> Untuk memastikan aplikasi Anda aman, selalu gunakan intent +eksplisit saat memulai {@link android.app.Service} dan jangan +mendeklarasikan filter intent untuk layanan. Menggunakan intent implisit untuk memulai layanan akan menimbulkan +bahaya keamanan karena Anda tidak bisa memastikan layanan apa yang akan merespons intent, +dan pengguna tidak bisa melihat layanan mana yang dimulai. Mulai dari Android 5.0 (API level 21), sistem +melontarkan eksepsi jika Anda memanggil {@link android.content.Context#bindService bindService()} +dengan intent implisit.</p> + + + + + +<h2 id="Building">Membangun Intent</h2> + +<p>Objek {@link android.content.Intent} membawa informasi yang digunakan sistem Android +untuk menentukan komponen mana yang akan dimulai (misalnya nama persis dari suatu komponen atau kategori +komponen yang seharusnya menerima intent), ditambah informasi yang digunakan komponen penerima untuk +melakukan tindakan dengan benar (misalnya tindakan yang harus dilakukan dan data yang harus diolah).</p> + + +<p>Informasi utama yang dimuat dalam {@link android.content.Intent} adalah sebagai berikut:</p> + +<dl> + +<dt><b>Nama komponen</b></dt> +<dd>Nama komponen yang akan dimulai. + +<p>Ini opsional, namun merupakan bagian informasi penting yang membuat intent +menjadi <b>eksplisit</b>, yaitu intent harus dikirim hanya ke komponen aplikasi +yang didefinisikan oleh nama komponen. Tanpa nama komponen, intent menjadi <b>implisit</b> dan +sistem akan memutuskan komponen mana yang harus menerima intent berdasarkan informasi intent lain +(misalnya tindakan, data, dan kategori—yang dijelaskan di bawah ini). Jadi jika Anda ingin memulai komponen +tertentu dalam aplikasi, Anda harus menetapkan nama komponen tersebut.</p> + +<p class="note"><strong>Catatan:</strong> Saat memulai {@link android.app.Service}, Anda harus +<strong>selalu menetapkan nama komponen</strong>. Jika tidak, maka Anda tidak bisa memastikan layanan apa +yang akan merespons intent tersebut, dan pengguna tidak bisa melihat layanan mana yang dimulai.</p> + +<p>Bidang {@link android.content.Intent} ini adalah objek +{@link android.content.ComponentName}, yang bisa Anda tetapkan menggunakan +nama kelas yang sepenuhnya memenuhi syarat dari komponen target, termasuk nama paket aplikasi. Misalnya, +{@code com.example.ExampleActivity}. Anda bisa mengatur nama komponen dengan {@link +android.content.Intent#setComponent setComponent()}, {@link android.content.Intent#setClass +setClass()}, {@link android.content.Intent#setClassName(String, String) setClassName()}, atau dengan konstruktor +{@link android.content.Intent}.</p> + +</dd> + +<p><dt><b>Tindakan</b></dt> +<dd>String yang menetapkan tindakan generik untuk dilakukan (misalnya <em>lihat</em> atau <em>pilih</em>). + +<p>Dalam hal intent siaran, ini adalah tindakan yang terjadi dan dilaporkan. +Tindakan ini sangat menentukan bagaimana keseluruhan intent disusun—terutama +apa yang dimuat dalam data dan ekstra. + +<p>Anda bisa menetapkan tindakan sendiri yang akan digunakan oleh intent dalam aplikasi Anda (atau digunakan oleh aplikasi +lain untuk memanggil komponen dalam aplikasi Anda), namun Anda harus menggunakan konstanta tindakan +yang didefinisikan oleh kelas {@link android.content.Intent} atau kelas kerangka kerja lain. Berikut ini adalah beberapa +tindakan umum untuk memulai sebuah aktivitas:</p> + +<dl> +<dt>{@link android.content.Intent#ACTION_VIEW}</dt> + <dd>Gunakan tindakan ini dalam intent dengan {@link + android.content.Context#startActivity startActivity()} saat Anda memiliki beberapa informasi yang + bisa ditampilkan aktivitas kepada pengguna, misalnya foto yang bisa dilihat dalam aplikasi galeri, atau alamat + yang bisa dilihat dalam aplikasi peta.</dd> + +<dt>{@link android.content.Intent#ACTION_SEND}</dt> + <dd>Juga dikenal dengan intent "berbagi", Anda harus menggunakannya dalam intent dengan {@link + android.content.Context#startActivity startActivity()} bila Anda memiliki data yang bisa digunakan pengguna untuk + berbagi melalui aplikasi lain, misalnya aplikasi email atau aplikasi jaringan sosial.</dd> +</dl> + +<p>Lihat referensi kelas {@link android.content.Intent} untuk konstanta +selengkapnya yang mendefinisikan tindakan generik. Tindakan lain yang didefinisikan +di tempat lain dalam kerangka kerja Android, misalnya dalam {@link android.provider.Settings} untuk tindakan +yang membuka layar tertentu dalam aplikasi Settings di sistem.</p> + +<p>Anda bisa menetapkan tindakan untuk sebuah intent dengan {@link android.content.Intent#setAction +setAction()} atau dengan konstruktor {@link android.content.Intent}.</p> + +<p>Jika mendefinisikan tindakan Anda sendiri, pastikan untuk memasukkan nama paket aplikasi Anda +sebagai awalan. Misalnya:</p> +<pre>static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";</pre> +</dd> + +<dt><b>Data</b></dt> +<dd>URI (objek {@link android.net.Uri}) yang mengacu data untuk diolah dan/atau +tipe MIME dari data tersebut. Tipe data yang disediakan umumnya didikte oleh tindakan intent. +Misalnya, jika tindakan merupakan {@link android.content.Intent#ACTION_EDIT}, data harus berisi +URI dari dokumen untuk diedit. + +<p>Saat membuat intent, +seringkali tipe data (tipe MIME-nya) selain URI perlu ditetapkan. +Misalnya, aktivitas yang mampu menampilkan gambar mungkin tidak mampu +memutar file audio, walaupun format URI mungkin serupa. +Jadi menetapkan tipe MIME data Anda akan membantu sistem +Android menemukan komponen terbaik untuk diterima intent. +Akan tetapi, tipe MIME seringkali bisa diambil dari URI—terutama saat datanya merupakan URI +{@code content:}, yang menunjukkan data tersebut berada di perangkat dan dikontrol oleh +{@link android.content.ContentProvider}, yang membuat data tipe MIME terlihat di sistem.</p> + +<p>Untuk mengatur data URI saja, panggil {@link android.content.Intent#setData setData()}. +Untuk mengatur tipe MIME saja, panggil {@link android.content.Intent#setType setType()}. Jika perlu, Anda +bisa mengatur keduanya secara eksplisit dengan {@link +android.content.Intent#setDataAndType setDataAndType()}.</p> + +<p class="caution"><strong>Perhatian:</strong> Jika ingin mengatur tipe URI dan MIME, +<strong>jangan</strong> panggil {@link android.content.Intent#setData setData()} dan +{@link android.content.Intent#setType setType()} karena mereka saling menghapuskan nilai satu sama lain. +Selalu gunakan {@link android.content.Intent#setDataAndType setDataAndType()} untuk mengatur +tipe URI maupun MIME.</p> +</dd> + +<p><dt><b>Kategori</b></dt> +<dd>String yang berisi informasi tambahan tentang jenis komponen +yang harus menangani intent. Keterangan kategori dalam jumlah berapa pun bisa +dimasukkan dalam intent, namun sebagian besar intent tidak memerlukan kategori. +Berikut ini adalah beberapa kategori umum: + +<dl> +<dt>{@link android.content.Intent#CATEGORY_BROWSABLE}</dt> + <dd>Aktivitas target memungkinkannya dimulai oleh browser web untuk menampilkan data +yang diacu oleh tautan—misalnya gambar atau pesan e-mail. + </dd> +<dt>{@link android.content.Intent#CATEGORY_LAUNCHER}</dt> + <dd>Aktivitas tersebut adalah aktivitas awal dari sebuah tugas dan dicantumkan dalam + launcher aplikasi sistem. + </dd> +</dl> + +<p>Lihat keterangan kelas {@link android.content.Intent} untuk mengetahui daftar lengkap +kategori.</p> + +<p>Anda bisa menetapkan kategori dengan {@link android.content.Intent#addCategory addCategory()}.</p> +</dd> +</dl> + + +<p>Properti yang tercantum di atas (nama komponen, tindakan, data, dan kategori) menyatakan +karakteristik yang mendefinisikan intent. Dengan membaca properti ini, sistem Android +mampu memutuskan komponen aplikasi yang harus dimulainya.</p> + +<p>Akan tetapi, intent bisa membawa informasi tambahan yang tidak memengaruhi +cara intent ditetapkan pada komponen aplikasi. Intent juga bisa menyediakan:</p> + +<dl> +<dt><b>Ekstra</b></dt> +<dd>Pasangan nilai-kunci yang membawa informasi yang diperlukan untuk menghasilkan tindakan yang diminta. +Seperti halnya beberapa tindakan menggunakan jenis tertentu URI data, beberapa tindakan juga menggunakan ekstra tertentu. + +<p>Anda bisa menambahkan data ekstra dengan beragam metode {@link android.content.Intent#putExtra putExtra()}, +masing-masing menerima dua parameter: nama kunci dan nilainya. +Anda juga bisa membuat objek {@link android.os.Bundle} dengan semua data ekstra, kemudian memasukkan +{@link android.os.Bundle} dalam {@link android.content.Intent} dengan {@link +android.content.Intent#putExtras putExtras()}.</p> + +<p>Misalnya, saat membuat intent yang akan dikirimkan bersama email +{@link android.content.Intent#ACTION_SEND}, Anda bisa menetapkan penerima "kepada" dengan kunci +{@link android.content.Intent#EXTRA_EMAIL}, dan menetapkan "subjek" dengan kunci +{@link android.content.Intent#EXTRA_SUBJECT}.</p> + +<p>Kelas {@link android.content.Intent} menetapkan beberapa konstanta {@code EXTRA_*} +untuk tipe data standar. Jika Anda ingin mendeklarasikan kunci ekstra sendiri (untuk intent yang +diterima aplikasi Anda), pastikan untuk memasukkan nama paket aplikasi +sebagai awalan. Misalnya:</p> +<pre>static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";</pre> +</dd> + +<dt><b>Flag</b></dt> +<dd>Flag didefinisikan dalam kelas {@link android.content.Intent} yang berfungsi sebagai metadata untuk +intent. Flag menginstruksikan cara meluncurkan aktivitas (misalnya, +<a href="{@docRoot}guide/components/tasks-and-back-stack.html">tugas</a> mana yang harus dimiliki suatu aktivitas +) dan cara memperlakukannya setelah diluncurkan (misalnya, apakah aktivitas tersebut masuk ke dalam daftar aktivitas +terbaru) pada sistem Android. + +<p>Untuk informasi selengkapnya, lihat metode {@link android.content.Intent#setFlags setFlags()} .</p> +</dd> + +</dl> + + + + +<h3 id="ExampleExplicit">Contoh intent eksplisit</h3> + +<p>Intent eksplisit adalah intent yang Anda gunakan untuk meluncurkan komponen aplikasi tertentu, seperti +aktivitas tertentu atau layanan dalam aplikasi Anda. Untuk membuat intent eksplisit, definisikan +nama komponen untuk objek {@link android.content.Intent} —semua +properti intent lain bersifat opsional.</p> + +<p>Misalnya, jika Anda ingin membangun layanan dalam aplikasi Anda, bernama {@code DownloadService}, +yang didesain untuk mengunduh file dari web, Anda bisa memulainya dengan kode berikut ini:</p> + +<pre> +// Executed in an Activity, so 'this' is the {@link android.content.Context} +// The fileUrl is a string URL, such as "http://www.example.com/image.png" +Intent downloadIntent = new Intent(this, DownloadService.class); +downloadIntent.setData({@link android.net.Uri#parse Uri.parse}(fileUrl)); +startService(downloadIntent); +</pre> + +<p>Konstruktor {@link android.content.Intent#Intent(Context,Class)} + menyediakan {@link android.content.Context} aplikasi dan +objek {@link java.lang.Class} pada komponen. Dengan demikian, +intent ini memulai secara eksplisit kelas {@code DownloadService} dalam aplikasi.</p> + +<p>Untuk informasi selengkapnya tentang membangun dan memulai layanan, lihat panduan +<a href="{@docRoot}guide/components/services.html">Layanan</a>.</p> + + + + +<h3 id="ExampleSend">Contoh intent implisit</h3> + +<p>Intent implisit menetapkan tindakan yang bisa memanggil aplikasi pada perangkat yang mampu +melakukan tindakan. Menggunakan intent implisit berguna bila aplikasi Anda tidak bisa melakukan +tindakan, namun aplikasi lain mungkin bisa melakukannya dan Anda ingin pengguna untuk memilih aplikasi mana yang ingin digunakan.</p> + +<p>Misalnya, jika memiliki konten yang Anda ingin agar pengguna berbagi konten itu dengan orang lain, buatlah intent +dengan tindakan {@link android.content.Intent#ACTION_SEND} +dan tambahkan ekstra yang menetapkan konten yang akan dibagikan. Bila Anda memanggil +{@link android.content.Context#startActivity startActivity()} dengan intent tersebut, pengguna bisa +memilih aplikasi yang akan digunakan untuk berbagi konten.</p> + +<p class="caution"><strong>Perhatian:</strong> Ada kemungkinan pengguna tidak memiliki <em>suatu</em> +aplikasi yang menangani intent implisit yang Anda kirimkan ke {@link android.content.Context#startActivity +startActivity()}. Jika itu terjadi, panggilan akan gagal dan aplikasi Anda akan crash. Untuk memeriksa +apakah aktivitas bisa menerima intent, panggil {@link android.content.Intent#resolveActivity +resolveActivity()} pada objek {@link android.content.Intent} Anda. Jika hasilnya bukan nol, +berarti setidaknya ada satu aplikasi yang bisa menangani intent tersebut dan aman untuk memanggil +{@link android.content.Context#startActivity startActivity()}. Jika hasilnya nol, +Anda tidak boleh menggunakan intent tersebut dan, jika memungkinkan, Anda harus menonaktifkan fitur yang mengeluarkan +intent tersebut.</p> + + +<pre> +// Create the text message with a string +Intent sendIntent = new Intent(); +sendIntent.setAction(Intent.ACTION_SEND); +sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage); +sendIntent.setType("text/plain"); + +// Verify that the intent will resolve to an activity +if (sendIntent.resolveActivity(getPackageManager()) != null) { + startActivity(sendIntent); +} +</pre> + +<p class="note"><strong>Catatan:</strong> Dalam hal ini, URI tidak digunakan, namun tipe data intent +dideklarasikan untuk menetapkan konten yang dibawa oleh ekstra.</p> + + +<p>Saat {@link android.content.Context#startActivity startActivity()} dipanggil, sistem akan +memeriksa semua aplikasi yang terinstal untuk menentukan aplikasi mana yang bisa menangani intent jenis ini ( +intent dengan tindakan {@link android.content.Intent#ACTION_SEND} dan yang membawa data +"teks/polos"). Jika hanya ada satu aplikasi yang bisa menanganinya, aplikasi tersebut akan langsung terbuka dan diberi +intent tersebut. Jika banyak aktivitas menerima intent, sistem akan +menampilkan dialog sehingga pengguna bisa memilih aplikasi mana yang digunakan.</p> + + +<div class="figure" style="width:200px"> + <img src="{@docRoot}images/training/basics/intent-chooser.png" alt=""> + <p class="img-caption"><strong>Gambar 2.</strong> Dialog pemilih.</p> +</div> + +<h3 id="ForceChooser">Memaksakan pemilih aplikasi</h3> + +<p>Bila ada lebih dari satu aplikasi yang merespons intent implisit Anda, +pengguna bisa memilih aplikasi mana yang digunakan dan membuat aplikasi tersebut pilihan default untuk +tindakan tersebut. Ini sangat membantu saat melakukan tindakan di mana pengguna +mungkin ingin menggunakan aplikasi yang sama untuk seterusnya, seperti saat membuka halaman web (pengguna +biasanya memilih hanya satu browser web).</p> + +<p>Akan tetapi, jika ada banyak aplikasi yang bisa merespons intent tersebut dan pengguna mungkin ingin menggunakan aplikasi +yang berbeda untuk setiap kalinya, Anda harus menampilkan dialog pemilih secara eksplisit. Dialog pemilih akan meminta +pengguna memilih aplikasi yang akan digunakan untuk tindakan tertentu setiap kali (pengguna tidak bisa memilih aplikasi default untuk +tindakan tersebut). Misalnya, saat aplikasi Anda melakukan "berbagi" dengan tindakan {@link +android.content.Intent#ACTION_SEND}, pengguna mungkin ingin berbagi menggunakan aplikasi berbeda sesuai +dengan situasi mereka saat itu, jadi Anda harus selalu menggunakan dialog pemilih, seperti yang ditampilkan dalam gambar 2.</p> + + + + +<p>Untuk menampilkan pemilih, buatlah {@link android.content.Intent} menggunakan {@link +android.content.Intent#createChooser createChooser()} dan teruskan ke {@link +android.app.Activity#startActivity startActivity()}. Misalnya:</p> + +<pre> +Intent sendIntent = new Intent(Intent.ACTION_SEND); +... + +// Always use string resources for UI text. +// This says something like "Share this photo with" +String title = getResources().getString(R.string.chooser_title); +// Create intent to show the chooser dialog +Intent chooser = Intent.createChooser(sendIntent, title); + +// Verify the original intent will resolve to at least one activity +if (sendIntent.resolveActivity(getPackageManager()) != null) { + startActivity(chooser); +} +</pre> + +<p>Ini menampilkan dialog dengan daftar aplikasi yang merespons intent yang diteruskan ke metode {@link +android.content.Intent#createChooser createChooser()} dan menggunakan teks yang disediakan sebagai +judul dialog.</p> + + + + + + + + + +<h2 id="Receiving">Menerima Intent Implisit</h2> + +<p>Untuk mengiklankan intent implisit yang bisa diterima aplikasi Anda, deklarasikan satu atau beberapa filter intent untuk +tiap komponen aplikasi dengan elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code <intent-filter>}</a> +dalam <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">file manifes</a> Anda. +Tiap filter intent menetapkan tipe intent yang diterimanya berdasarkan tindakan intent, +data, dan kategori. Sistem akan mengirim intent implisit ke komponen aplikasi Anda hanya jika +intent tersebut bisa diteruskan melalui salah satu filter intent.</p> + +<p class="note"><strong>Catatan:</strong> Intent eksplisit selalu dikirimkan ke targetnya, +apa pun filter intent yang dideklarasikan komponen.</p> + +<p>Komponen aplikasi harus mendeklarasikan filter terpisah untuk setiap pekerjaan unik yang bisa dilakukannya. +Misalnya, satu aktivitas dalam aplikasi galeri gambar bisa memiliki dua filter: satu filter +untuk melihat gambar, dan filter lainnya untuk mengedit gambar. Bila aktivitas dimulai, +aktivitas akan memeriksa {@link android.content.Intent} dan menentukan cara berperilaku berdasarkan informasi +dalam {@link android.content.Intent} (misalnya menampilkan kontrol editor atau tidak).</p> + +<p>Tiap filter intent didefinisikan oleh elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code <intent-filter>}</a> +dalam file manifes aplikasi, yang tersarang dalam komponen aplikasi terkait (seperti +elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> +). Di dalam <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code <intent-filter>}</a>, +Anda bisa menetapkan tipe intent yang akan diterima dengan menggunakan salah satu atau beberapa +dari tiga elemen ini:</p> + +<dl> +<dt><a href="{@docRoot}guide/topics/manifest/action-element.html">{@code <action>}</a></dt> + <dd>Mendeklarasikan tindakan intent yang diterima, dalam atribut {@code name}. Nilai + haruslah nilai string literal dari tindakan, bukan konstanta kelas.</dd> +<dt><a href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a></dt> + <dd>Mendeklarasikan tipe data yang diterima, menggunakan salah satu atau beberapa atribut yang menetapkan beragam + aspek URI data (<code>scheme</code>, <code>host</code>, <code>port</code>, + <code>path</code>, dll.) dan tipe MIME.</dd> +<dt><a href="{@docRoot}guide/topics/manifest/category-element.html">{@code <category>}</a></dt> + <dd>Mendeklarasikan kategori intent yang diterima, dalam atribut {@code name}. Nilai + haruslah nilai string literal dari tindakan, bukan konstanta kelas. + + <p class="note"><strong>Catatan:</strong> Untuk menerima intent implisit, Anda + <strong>harus menyertakan</strong> kategori +{@link android.content.Intent#CATEGORY_DEFAULT} dalam filter intent. Metode + {@link android.app.Activity#startActivity startActivity()}dan + {@link android.app.Activity#startActivityForResult startActivityForResult()} memperlakukan semua intent + seolah-olah mendeklarasikan kategori {@link android.content.Intent#CATEGORY_DEFAULT}. + Jika tidak mendeklarasikan kategori ini dalam filter intent Anda, tidak ada intent implisit yang ditetapkan untuk + aktivitas Anda.</p> + </dd> +</dl> + +<p>Misalnya, ini adalah deklarasi aktivitas dengan filter intent yang diterima intent +{@link android.content.Intent#ACTION_SEND} bila tipe data berupa teks:</p> + +<pre> +<activity android:name="ShareActivity"> + <intent-filter> + <action android:name="android.intent.action.SEND"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="text/plain"/> + </intent-filter> +</activity> +</pre> + +<p>Anda bisa membuat filter yang menyertakan lebih dari satu instance +<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code <action>}</a>, +<a href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a>, atau +<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code <category>}</a>. +Jika Anda melakukannya, Anda hanya perlu memastikan bahwa komponen bisa menangani semua kombinasi +elemen filter tersebut.</p> + +<p>Bila ingin menangani beragam jenis intent, namun hanya dalam kombinasi +tindakan, data, dan tipe kategori tertentu, maka Anda harus membuat banyak filter intent.</p> + + +<div class="sidebox-wrapper"> +<div class="sidebox"> +<h2>Membatasi akses ke komponen</h2> +<p>Menggunakan filter intent bukanlah cara yang aman untuk mencegah aplikasi lain memulai +komponen Anda. Walaupun filter intent membatasi komponen agar hanya merespons +jenis intent implisit tertentu, aplikasi lain bisa saja memulai komponen aplikasi Anda +dengan menggunakan intent eksplisit jika pengembangnya menentukan nama komponen Anda. +Jika perlu <em>hanya aplikasi Anda sendiri</em> yang mampu memulai salah satu komponen, +atur atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#exported">{@code +exported}</a> ke {@code "false"} untuk komponen itu. +</p> +</div> +</div> + +<p>Intent implisit diuji terhadap filter dengan membandingkan intent dengan masing-masing +dari ketiga elemen. Agar dikirim ke komponen, intent harus lolos ketiga pengujian tersebut. +Jika intent gagal dalam salah satu pengujian, sistem Android tidak akan mengirim intent ke +komponen. Akan tetapi, karena sebuah komponen dapat memiliki beberapa filter intent, intent yang tidak +lolos melalui salah satu filter komponen mungkin akan lolos di filter lain. +Informasi selengkapnya tentang cara sistem menetapkan intent disediakan dalam bagian di bawah ini +tentang <a href="#Resolution">Resolusi Intent</a>.</p> + +<p class="caution"><strong>Perhatian:</strong> Untuk menghindari menjalankan +{@link android.app.Service} aplikasi yang berbeda secara tidak sengaja, selalu gunakan intent eksplisit untuk memulai layanan Anda sendiri dan jangan +deklarasikan filter intent untuk layanan Anda.</p> + +<p class="note"><strong>Catatan:</strong> +Untuk semua aktivitas, Anda harus mendeklarasikan filter intent dalam file manifes. +Akan tetapi, filter untuk penerima siaran bisa didaftarkan secara dinamis dengan memanggil +{@link android.content.Context#registerReceiver(BroadcastReceiver, IntentFilter, String, +Handler) registerReceiver()}. Anda nanti bisa mencabut pendaftaran penerima dengan {@link +android.content.Context#unregisterReceiver unregisterReceiver()}. Dengan begitu aplikasi Anda +bisa mendengarkan siaran tertentu hanya selama periode waktu yang telah ditetapkan saat aplikasi Anda +berjalan.</p> + + + + + + + +<h3 id="ExampleFilters">Contoh filter</h3> + +<p>Untuk lebih memahami beberapa perilaku filter intent, lihatlah cuplikan berikut +dari file manifes aplikasi berbagi di jaringan sosial.</p> + +<pre> +<activity android:name="MainActivity"> + <!-- This activity is the main entry, should appear in app launcher --> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> +</activity> + +<activity android:name="ShareActivity"> + <!-- This activity handles "SEND" actions with text data --> + <intent-filter> + <action android:name="android.intent.action.SEND"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="text/plain"/> + </intent-filter> + <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data --> + <intent-filter> + <action android:name="android.intent.action.SEND"/> + <action android:name="android.intent.action.SEND_MULTIPLE"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="application/vnd.google.panorama360+jpg"/> + <data android:mimeType="image/*"/> + <data android:mimeType="video/*"/> + </intent-filter> +</activity> +</pre> + +<p>Aktivitas pertama, {@code MainActivity}, merupakan titik masuk utama aplikasi—aplikasi yang +terbuka saat pengguna meluncurkan aplikasi dengan ikon launcher:</p> +<ul> + <li>Tindakan {@link android.content.Intent#ACTION_MAIN} + menunjukkan ini adalah titik masuk utama dan tidak mengharapkan data intent apa pun.</li> + <li>Kategori {@link android.content.Intent#CATEGORY_LAUNCHER} menunjukjkan bahwa ikon + aktivitas ini harus ditempatkan dalam launcher aplikasi sistem. Jika elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> + tidak menetapkan ikon dengan{@code icon}, maka sistem akan menggunakan ikon dari elemen +<a href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>.</li> +</ul> +<p>Keduanya harus dipasangkan bersama agar aktivitas muncul dalam launcher aplikasi.</p> + +<p>Aktivitas kedua, {@code ShareActivity}, dimaksudkan untuk memudahkan berbagi teks dan konten +media. Walaupun pengguna mungkin memasuki aktivitas ini dengan mengarah ke aktivitas dari {@code MainActivity}, +pengguna juga bisa memasukkan {@code ShareActivity} secara langsung dari aplikasi lain yang mengeluarkan intent +implisit yang cocok dengan salah satu dari kedua filter intent.</p> + +<p class="note"><strong>Catatan:</strong> Tipe MIME, +<a href="https://developers.google.com/panorama/android/">{@code +application/vnd.google.panorama360+jpg}</a>, merupakan tipe data khusus yang menetapkan +foto panorama, yang bisa Anda tangani dengan API <a href="{@docRoot}reference/com/google/android/gms/panorama/package-summary.html">panorama +Google</a>.</p> + + + + + + + + + + + + + +<h2 id="PendingIntent">Menggunakan Intent Tertunda</h2> + +<p>Objek {@link android.app.PendingIntent} merupakan pembungkus objek {@link +android.content.Intent}. Tujuan utama {@link android.app.PendingIntent} +adalah memberikan izin pada aplikasi asing +untuk menggunakan {@link android.content.Intent} yang termuat seolah-olah dieksekusi dari +proses aplikasi Anda sendiri.</p> + +<p>Kasus penggunaan utama untuk intent tertunda antara lain:</p> +<ul> + <li>Mendeklarasikan intent untuk dieksekusi saat pengguna melakukan tindakan dengan <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan</a> + ({@link android.app.NotificationManager} + sistem Android akan mengeksekusi {@link android.content.Intent}) Anda. + <li>Mendeklarasikan intent untuk dieksekusi saat pengguna melakukan tindakan dengan +<a href="{@docRoot}guide/topics/appwidgets/index.html">App Widget</a> + (aplikasi layar Home mengeksekusi {@link android.content.Intent}). + <li>Mendeklarasikan intent untuk dieksekusi di waktu yang telah ditetapkan di masa mendatang +({@link android.app.AlarmManager} sistem Android akan mengeksekusi {@link android.content.Intent}). +</ul> + +<p>Karena setiap objek {@link android.content.Intent} didesain untuk ditangani oleh tipe +tertentu dari komponen aplikasi (baik {@link android.app.Activity}, {@link android.app.Service}, maupun + {@link android.content.BroadcastReceiver}), jadi {@link android.app.PendingIntent} harus +dibuat dengan pertimbangan yang sama. Saat menggunakan intent tertunda, aplikasi Anda tidak akan +mengeksekusi intent dengan panggilan seperti {@link android.content.Context#startActivity +startActivity()}. Anda harus mendeklarasikan tipe komponen yang dimaksud saat membuat +{@link android.app.PendingIntent} dengan memanggil metode kreator masing-masing:</p> + +<ul> + <li>{@link android.app.PendingIntent#getActivity PendingIntent.getActivity()} untuk + {@link android.content.Intent} yang memulai {@link android.app.Activity}.</li> + <li>{@link android.app.PendingIntent#getService PendingIntent.getService()} untuk + {@link android.content.Intent} yang memulai {@link android.app.Service}.</li> + <li>{@link android.app.PendingIntent#getBroadcast PendingIntent.getBroadcast()} untuk + {@link android.content.Intent} yang memulai {@link android.content.BroadcastReceiver}.</li> +</ul> + +<p>Kecuali jika aplikasi Anda <em>menerima</em> intent tertunda dari aplikasi lain, +metode di atas untuk membuat {@link android.app.PendingIntent} menjadi satu-satunya metode +{@link android.app.PendingIntent} yang mungkin Anda butuhkan.</p> + +<p>Tiap metode mengambil {@link android.content.Context} aplikasi saat itu, +{@link android.content.Intent} yang ingin Anda bungkus, dan satu atau beberapa flag yang menetapkan +cara penggunaan intent (misalnya apakah intent bisa digunakan lebih dari sekali).</p> + +<p>Informasi selengkapnya tentang intent tertunda disediakan pada dokumentasi untuk setiap +kasus penggunaan yang bersangkutan, seperti dalam panduan API <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a> +dan <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a>.</p> + + + + + + + +<h2 id="Resolution">Resolusi Intent</h2> + + +<p>Saat sistem menerima intent implisit yang memulai suatu aktivitas, sistem tersebut akan mencari +aktivitas terbaik untuk intent dengan membandingkan intent dengan filter intent berdasarkan tiga aspek:</p> + +<ul> + <li>Tindakan intent + <li>Data intent (baik URI maupun tipe data) + <li>Kategori intent +</ul> + +<p>Bagian berikut menjelaskan cara pencocokan intent dengan komponen yang sesuai +sehubungan dengan cara pendeklarasian filter intent dalam file manifes aplikasi.</p> + + +<h3 id="ActionTest">Pengujian tindakan</h3> + +<p>Untuk menetapkan tindakan intent yang diterima, filter intent bisa mendeklarasikan nol atau beberapa elemen +<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code +<action>}</a>. Misalnya:</p> + +<pre> +<intent-filter> + <action android:name="android.intent.action.EDIT" /> + <action android:name="android.intent.action.VIEW" /> + ... +</intent-filter> +</pre> + +<p>Untuk melewati filter ini, tindakan yang ditetapkan dalam {@link android.content.Intent} +harus sesuai dengan salah satu tindakan yang tercantum dalam filter.</p> + +<p>Jika filter tidak mencantumkan tindakan apa pun, maka tidak ada intent +yang dicocokkan, jadi semua intent gagal dalam pengujian. Akan tetapi, jika sebuah {@link android.content.Intent} +tidak menetapkan suatu tindakan, maka akan lolos pengujian (asalkan filter +berisi setidaknya satu tindakan).</p> + + + +<h3 id="CategoryTest">Pengujian kategori</h3> + +<p>Untuk menetapkan kategori intent yang diterima, filter intent bisa mendeklarasikan nol atau beberapa elemen +<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code +<category>}</a>. Misalnya:</p> + +<pre> +<intent-filter> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + ... +</intent-filter> +</pre> + +<p>Agar intent bisa lolos pengujian kategori, setiap kategori dalam {@link android.content.Intent} +harus sesuai dengan kategori dalam filter. Kebalikannya tidak diperlukan—filter intent bisa +mendeklarasikan kategori lebih banyak daripada yang ditetapkan dalam {@link android.content.Intent} dan +{@link android.content.Intent} tetap akan lolos. Oleh karena itu, intent tanpa kategori harus +selalu lolos pengujian ini, kategori apa pun yang dideklarasikan dalam filter.</p> + +<p class="note"><strong>Catatan:</strong> +Android secara otomatis menerapkan kategori {@link android.content.Intent#CATEGORY_DEFAULT} +untuk semua intent implisit yang diteruskan ke {@link +android.content.Context#startActivity startActivity()} dan {@link +android.app.Activity#startActivityForResult startActivityForResult()}. +Jadi jika ingin aktivitas Anda menerima intent implisit, aktivitas tersebut harus +menyertakan kategori untuk{@code "android.intent.category.DEFAULT"} dalam filter intent (seperti +yang ditampilkan dalam contoh{@code <intent-filter>} sebelumnya.</p> + + + +<h3 id="DataTest">Pengujian data</h3> + +<p>Untuk menetapkan data intent yang diterima, filter intent bisa mendeklarasikan nol atau beberapa elemen +<a href="{@docRoot}guide/topics/manifest/data-element.html">{@code +<data>}</a>. Misalnya:</p> + +<pre> +<intent-filter> + <data android:mimeType="video/mpeg" android:scheme="http" ... /> + <data android:mimeType="audio/mpeg" android:scheme="http" ... /> + ... +</intent-filter> +</pre> + +<p>Tiap elemen <code><a href="{@docRoot}guide/topics/manifest/data-element.html"><data></a></code> +bisa menetapkan struktur URI dan tipe data (tipe media MIME). Ada atribut +terpisah — {@code scheme}, {@code host}, {@code port}, +dan {@code path} — untuk setiap bagian URI: +</p> + +<p style="margin-left: 2em">{@code <scheme>://<host>:<port>/<path>}</p> + +<p> +Misalnya: +</p> + +<p style="margin-left: 2em">{@code content://com.example.project:200/folder/subfolder/etc}</p> + +<p>Dalam URI ini, skemanya adalah {@code content}, host-nya adalah {@code com.example.project}, +port-nya adalah {@code 200}, dan path-nya adalah {@code folder/subfolder/etc}. +</p> + +<p>Tiap atribut bersifat opsional dalam elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a>, +namun ada dependensi linear:</p> +<ul> + <li>Jika skema tidak ditetapkan, host akan diabaikan.</li> + <li>Jika host tidak ditetapkan, port akan diabaikan.</li> + <li>Jika skema dan host tidak ditetapkan, path akan diabaikan.</li> +</ul> + +<p>Bila URI dalam intent dibandingkan dengan spesifikasi URI dalam filter, +pembandingannya hanya dengan bagian URI yang disertakan dalam filter. Misalnya:</p> +<ul> + <li>Jika sebuah filter menetapkan hanya satu skema, semua URI dengan skema tersebut akan cocok +dengan filter.</li> + <li>Jika sebuah filter menetapkan satu skema dan satu otoritas namun tanpa path, semua URI +dengan skema dan otoritas yang sama akan lolos dari filter, apa pun path-nya.</li> + <li>Jika sebuah filter menetapkan satu skema, otoritas dan path, hanya URI dengan skema, +otoritas, dan path sama yang bisa lolos dari filter.</li> +</ul> + +<p class="note"><strong>Catatan:</strong> Spesifikasi path bisa berisi +wildcard bintang (*) untuk hanya mencocokkan nama path secara parsial.</p> + +<p>Pengujian data membandingkan URI maupun tipe MIME dalam intent dengan URI +dan tipe MIME yang ditetapkan dalam filter. Aturannya adalah sebagai berikut: +</p> + +<ol type="a"> +<li>Intent yang tidak berisi URI maupun tipe MIME hanya akan lolos +pengujian jika filter tersebut tidak menetapkan URI atau tipe MIME apa pun.</li> + +<li>Intent yang berisi URI namun tidak berisi tipe MIME (baik secara eksplisit maupun tidak langsung dari +URI) hanya akan lolos pengujian jika URI-nya cocok dengan format URI filter +dan filternya juga tidak menetapkan tipe MIME.</li> + +<li>Intent yang berisi tipe MIME namun tidak berisi URI hanya akan lolos pengujian +jika filter mencantumkan tipe MIME yang sama dan tidak menetapkan format URI.</li> + +<li>Intent yang berisi URI maupun tipe MIME (baik secara eksplisit maupun tidak langsung dari +URI) hanya akan lolos pengujian bagian tipe MIME jika +tipe tersebut cocok dengan tipe yang dicantumkan dalam filter. Ini akan lolos pengujian bagian URI +jika URI-nya cocok dengan URI dalam filter atau memiliki {@code content:} +atau URI {@code file:} dan filter tidak menetapkan URI. Dengan kata lain, +komponen dianggap mendukung data {@code content:} dan {@code file:} jika +filternya <em>hanya</em> mencantumkan tipe MIME.</p></li> +</ol> + +<p> +Aturan terakhir ini, aturan (d), mencerminkan harapan +bahwa komponen mampu mendapatkan data lokal dari file atau penyedia konten. +Oleh karena itu, filter mereka mencatumkan tipe data saja dan tidak secara eksplisit +harus menamai skema {@code content:} dan {@code file:}. +Ini adalah kasus umum. Elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a> +seperti berikut ini, misalnya, memberi tahu Android bahwa komponen bisa mengambil data gambar dari penyedia +konten dan menampilkannya: +</p> + +<pre> +<intent-filter> + <data android:mimeType="image/*" /> + ... +</intent-filter></pre> + +<p> +Karena sebagian besar data yang tersedia dikeluarkan oleh penyedia konten, filter yang +menetapkan tipe data namun bukan URI mungkin adalah yang paling umum. +</p> + +<p> +Konfigurasi umum yang lain adalah filter dengan skema dan tipe data. Misalnya +, elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a> + seperti berikut ini akan memberi tahu Android bahwa +komponen bisa mengambil data video dari jaringan untuk melakukan tindakan: +</p> + +<pre> +<intent-filter> + <data android:scheme="http" android:type="video/*" /> + ... +</intent-filter></pre> + + + +<h3 id="imatch">Pencocokan intent</h3> + +<p>Intent dicocokkan dengan filter intent selain untuk menemukan komponen +target yang akan diaktifkan, juga untuk menemukan sesuatu tentang rangkaian +komponen pada perangkat. Misalnya, aplikasi Home akan menempatkan launcher aplikasi +dengan mencari semua aktivitas dengan filter intent yang menetapkan tindakan +{@link android.content.Intent#ACTION_MAIN} dan +kategori {@link android.content.Intent#CATEGORY_LAUNCHER}.</p> + +<p>Aplikasi Anda bisa menggunakan pencocokan intent dengan cara serupa. +{@link android.content.pm.PackageManager} memiliki seperangkat metode {@code query...()} +yang mengembalikan semua komponen yang bisa menerima intent tertentu, dan +serangkaian metode{@code resolve...()} serupa yang menentukan komponen +terbaik untuk merespons intent. Misalnya, +{@link android.content.pm.PackageManager#queryIntentActivities +queryIntentActivities()} akan mengembalikan daftar semua aktivitas yang bisa melakukan +intent yang diteruskan sebagai argumen, dan {@link +android.content.pm.PackageManager#queryIntentServices +queryIntentServices()} akan mengembalikan daftar layanan serupa. +Tidak ada metode yang akan mengaktifkan komponen; mereka hanya mencantumkan komponen yang +bisa merespons. Ada metode serupa, +{@link android.content.pm.PackageManager#queryBroadcastReceivers +queryBroadcastReceivers()}, untuk penerima siaran. +</p> + + + + diff --git a/docs/html-intl/intl/id/guide/components/loaders.jd b/docs/html-intl/intl/id/guide/components/loaders.jd new file mode 100644 index 000000000000..88093cc258a4 --- /dev/null +++ b/docs/html-intl/intl/id/guide/components/loaders.jd @@ -0,0 +1,494 @@ +page.title=Aktivitas +parent.title=Loader +parent.link=activities.html +@jd:body +<div id="qv-wrapper"> +<div id="qv"> + <h2>Dalam dokumen ini</h2> + <ol> + <li><a href="#summary">Rangkuman Loader API</a></li> + <li><a href="#app">Menggunakan Loader dalam Aplikasi</a> + <ol> + <li><a href="#requirements"></a></li> + <li><a href="#starting">Memulai Loader</a></li> + <li><a href="#restarting">Me-restart Loader</a></li> + <li><a href="#callback">Menggunakan Callback LoaderManager</a></li> + </ol> + </li> + <li><a href="#example">Contoh</a> + <ol> + <li><a href="#more_examples">Contoh Selengkapnya</a></li> + </ol> + </li> + </ol> + + <h2>Kelas-kelas utama</h2> + <ol> + <li>{@link android.app.LoaderManager}</li> + <li>{@link android.content.Loader}</li> + + </ol> + + <h2>Contoh-contoh terkait</h2> + <ol> + <li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html"> +LoaderCursor</a></li> + <li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> +LoaderThrottle</a></li> + </ol> + </div> +</div> + +<p>Diperkenalkan di Android 3.0, loader memudahkan pemuatan data asinkron +dalam aktivitas atau fragmen. Loader memiliki karakteristik ini:</p> + <ul> + <li>Loader tersedia untuk setiap {@link android.app.Activity} dan {@link +android.app.Fragment}.</li> + <li>Loader menyediakan pemuatan data asinkron.</li> + <li>Loader memantau sumber data mereka dan memberikan hasil baru bila +konten berubah.</li> + <li>Loader secara otomatis menghubungkan kembali ke kursor loader lalu saat +dibuat kembali setelah perubahan konfigurasi. Karena itu, loader tidak perlu melakukan query ulang +datanya.</li> + </ul> + +<h2 id="summary">Rangkuman Loader API</h2> + +<p>Ada beberapa kelas dan antarmuka yang mungkin dilibatkan dalam menggunakan +loader pada aplikasi. Semuanya dirangkum dalam tabel ini:</p> + +<table> + <tr> + <th>Kelas/Antarmuka</th> + <th>Keterangan</th> + </tr> + <tr> + <td>{@link android.app.LoaderManager}</td> + <td>Kelas abstrak yang dikaitkan dengan {@link android.app.Activity} atau +{@link android.app.Fragment} untuk mengelola satu atau beberapa instance {@link +android.content.Loader}. Ini membantu aplikasi mengelola +operasi berjalan lebih lama bersamaan dengan daur hidup {@link android.app.Activity} +atau {@link android.app.Fragment}; penggunaan paling umumnya adalah dengan +{@link android.content.CursorLoader}, akan tetapi aplikasi bebas menulis loader-nya + sendiri untuk memuat tipe data lainnya. + <br /> + <br /> + Hanya ada satu {@link android.app.LoaderManager} per aktivitas atau fragmen. Namun {@link android.app.LoaderManager} bisa memiliki +beberapa loader.</td> + </tr> + <tr> + <td>{@link android.app.LoaderManager.LoaderCallbacks}</td> + <td>Antarmuka callback untuk klien berinteraksi dengan {@link +android.app.LoaderManager}. Misalnya, Anda menggunakan metode callback {@link +android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} +untuk membuat loader baru.</td> + </tr> + <tr> + <td>{@link android.content.Loader}</td> + <td>Kelas abstrak yang melakukan pemuatan data asinkron. Ini +adalah kelas dasar untuk loader. Biasanya Anda akan menggunakan {@link +android.content.CursorLoader}, namun Anda bisa menerapkan subkelas sendiri. Selagi +loader aktif, loader harus memantau sumber datanya dan memberikan hasil +baru bila konten berubah. </td> + </tr> + <tr> + <td>{@link android.content.AsyncTaskLoader}</td> + <td>Loader abstrak yang menyediakan {@link android.os.AsyncTask} untuk melakukan pekerjaan.</td> + </tr> + <tr> + <td>{@link android.content.CursorLoader}</td> + <td>Subkelas {@link android.content.AsyncTaskLoader} yang meng-query +{@link android.content.ContentResolver} dan mengembalikan {@link +android.database.Cursor}. Kelas ini mengimplementasikan protokol {@link +android.content.Loader} dengan cara standar untuk query kursor, +yang dibuat berdasarkan {@link android.content.AsyncTaskLoader} untuk melakukan query kursor +pada thread latar belakang agar tidak memblokir UI aplikasi. Menggunakan loader +ini merupakan cara terbaik untuk memuat data secara asinkron dari {@link +android.content.ContentProvider}, sebagai ganti melakukan query terkelola melalui +fragmen atau API aktivitas.</td> + </tr> +</table> + +<p>Kelas dan antarmuka dalam tabel di atas merupakan komponen +esensial yang akan Anda gunakan untuk mengimplementasikan loader dalam aplikasi Anda. Anda tidak memerlukan semuanya +untuk setiap loader yang dibuat, namun Anda akan selalu memerlukan acuan ke {@link +android.app.LoaderManager} untuk memulai loader dan implementasi +kelas {@link android.content.Loader} seperti {@link +android.content.CursorLoader}. Bagian berikut ini menunjukkan kepada Anda cara menggunakan +kelas dan antarmuka ini dalam aplikasi.</p> + +<h2 id ="app">Menggunakan Loader dalam Aplikasi</h2> +<p>Bagian ini menjelaskan cara menggunakan loader dalam aplikasi Android. Aplikasi +yang menggunakan loader biasanya berisi yang berikut ini:</p> +<ul> + <li>{@link android.app.Activity} atau {@link android.app.Fragment}.</li> + <li>Instance {@link android.app.LoaderManager}.</li> + <li>{@link android.content.CursorLoader} akan memuat data yang didukung oleh {@link +android.content.ContentProvider}. Atau, Anda dapat mengimplementasikan subkelas sendiri + dari {@link android.content.Loader} atau {@link android.content.AsyncTaskLoader} untuk +memuat data dari beberapa sumber lain.</li> + <li>Implementasi untuk {@link android.app.LoaderManager.LoaderCallbacks}. +Di sinilah Anda membuat loader baru dan mengelola acuan bagi loader +yang ada.</li> +<li>Cara menampilkan data loader, seperti {@link +android.widget.SimpleCursorAdapter}.</li> + <li>Sumber data, seperti {@link android.content.ContentProvider}, saat menggunakan +{@link android.content.CursorLoader}.</li> +</ul> +<h3 id="starting">Memulai Loader</h3> + +<p>{@link android.app.LoaderManager} mengelola satu atau beberapa instance {@link +android.content.Loader} dalam {@link android.app.Activity} atau +{@link android.app.Fragment}. Hanya ada satu {@link +android.app.LoaderManager} per aktivitas atau fragmen.</p> + +<p>Anda biasanya +memulai {@link android.content.Loader} dalam metode {@link +android.app.Activity#onCreate onCreate()} aktivitas, atau dalam metode +{@link android.app.Fragment#onActivityCreated onActivityCreated()} fragmen. Anda +melakukannya dengan cara berikut ini:</p> + +<pre>// Prepare the loader. Either re-connect with an existing one, +// or start a new one. +getLoaderManager().initLoader(0, null, this);</pre> + +<p>Metode {@link android.app.LoaderManager#initLoader initLoader()} mengambil +parameter berikut:</p> +<ul> + <li>ID unik yang mengidentifikasi loader. Dalam contoh ini, ID-nya adalah 0.</li> +<li>Argumen opsional untuk dipasok ke loader +pada saat pembuatan (dalam contoh ini <code>null</code>).</li> + +<li>Implementasi {@link android.app.LoaderManager.LoaderCallbacks}, yang +akan dipanggil {@link android.app.LoaderManager} untuk melaporkan kejadian loader. Dalam contoh +ini, kelas lokal mengimplementasikan antarmuka {@link +android.app.LoaderManager.LoaderCallbacks}, sehingga meneruskan acuan +ke dirinya sendiri, {@code this}.</li> +</ul> +<p>Panggilan {@link android.app.LoaderManager#initLoader initLoader()} memastikan bahwa loader +telah dimulai dan aktif. Ia memiliki dua kemungkinan hasil:</p> +<ul> + <li>Jika loader yang disebutkan oleh ID sudah ada, loader yang dibuat terakhir akan digunakan +kembali.</li> + <li>Jika loader yang disebutkan oleh ID <em>tidak</em> ada, +{@link android.app.LoaderManager#initLoader initLoader()} akan memicu metode +{@link android.app.LoaderManager.LoaderCallbacks} {@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. +Di sinilah Anda mengimplementasikan kode untuk membuat instance dan mengembalikan loader baru. +Untuk diskusi selengkapnya, lihat bagian <a href="#onCreateLoader">onCreateLoader</a>.</li> +</ul> +<p>Dalam hal ini, implementasi {@link android.app.LoaderManager.LoaderCallbacks} +yang ditentukan akan dikaitkan dengan loader, dan akan dipanggil bila +status loader berubah. Jika saat panggilan ini status pemanggil sudah +dimulai, dan loader yang diminta sudah ada dan telah menghasilkan +datanya, maka sistem segera memanggil {@link +android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()} +(selama {@link android.app.LoaderManager#initLoader initLoader()}), +sehingga Anda harus siap bila hal ini terjadi. Lihat <a href="#onLoadFinished"> +onLoadFinished</a> untuk diskusi selengkapnya mengenai callback ini</p> + +<p>Perhatikan bahwa metode {@link android.app.LoaderManager#initLoader initLoader()} +mengembalikan {@link android.content.Loader} yang dibuat, namun Anda tidak +perlu menangkap acuan ke sana. {@link android.app.LoaderManager} mengelola +masa hidup loader secara otomatis. {@link android.app.LoaderManager} +memulai dan menghentikan pemuatan jika perlu, dan menjaga status loader +dan konten terkaitnya. Seperti yang tersirat di sini, Anda akan jarang berinteraksi dengan loader +secara langsung (meskipun misalnya menggunakan metode loader untuk menyempurnakan perilaku +loader, lihat contoh <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a>). +Anda paling sering akan menggunakan metode {@link +android.app.LoaderManager.LoaderCallbacks} untuk mengintervensi proses +pemuatan saat terjadi kejadian tertentu. Untuk diskusi selengkapnya mengenai topik ini, lihat <a href="#callback">Menggunakan Callback LoaderManager</a>.</p> + +<h3 id="restarting">Me-restart Loader</h3> + +<p>Bila Anda menggunakan {@link android.app.LoaderManager#initLoader initLoader()}, seperti +ditampilkan di atas, loader yang ada akan digunakan dengan ID yang ditetapkan jika ada. +Jika tidak ada, ID akan dibuat. Namun kadang-kadang Anda perlu membuang data lama +dan mulai dari awal.</p> + +<p>Untuk membuang data lama, gunakan {@link +android.app.LoaderManager#restartLoader restartLoader()}. Misalnya, implementasi +{@link android.widget.SearchView.OnQueryTextListener} ini akan me-restart +bila query pengguna berubah. Loader perlu di-restart +agar dapat menggunakan filter pencarian yang telah direvisi untuk melakukan query baru:</p> + +<pre> +public boolean onQueryTextChanged(String newText) { + // Called when the action bar search text has changed. Update + // the search filter, and restart the loader to do a new query + // with this filter. + mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; + getLoaderManager().restartLoader(0, null, this); + return true; +}</pre> + +<h3 id="callback">Menggunakan Callback LoaderManager</h3> + +<p>{@link android.app.LoaderManager.LoaderCallbacks} adalah antarmuka callback +yang memungkinkan klien berinteraksi dengan {@link android.app.LoaderManager}. </p> +<p>Loader, khususnya {@link android.content.CursorLoader}, diharapkan +mempertahankan datanya setelah dihentikan. Ini memungkinkan aplikasi mempertahankan +datanya di aktivitas atau metode {@link android.app.Activity#onStop +onStop()} fragmen dan {@link android.app.Activity#onStart onStart()}, sehingga +bila pengguna kembali ke aplikasi, mereka tidak harus menunggu data +dimuat kembali. Anda menggunakan metode {@link android.app.LoaderManager.LoaderCallbacks} +untuk mengetahui waktu membuat loader baru, dan memberi tahu aplikasi kapan +berhenti menggunakan data loader.</p> + +<p>{@link android.app.LoaderManager.LoaderCallbacks} berisi metode +ini:</p> +<ul> + <li>{@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} — +Membuat instance dan mengembalikan {@link android.content.Loader} baru untuk ID yang diberikan. +</li></ul> +<ul> + <li> {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()} +— Dipanggil bila loader yang dibuat sebelumnya selesai dimuat. +</li></ul> +<ul> + <li>{@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} + — Dipanggil bila loader yang dibuat sebelumnya sedang di-reset, sehingga datanya +tidak tersedia. +</li> +</ul> +<p>Metode ini dijelaskan lebih detail dalam bagian berikutnya.</p> + +<h4 id ="onCreateLoader">onCreateLoader</h4> + +<p>Saat Anda mencoba mengakses loader (misalnya, melalui {@link +android.app.LoaderManager#initLoader initLoader()}), ia akan memeriksa untuk mengetahui adanya +loader yang ditetapkan oleh ID. Jika tidak ada, ia akan memicu metode {@link +android.app.LoaderManager.LoaderCallbacks} {@link +android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. Di +sinilah Anda membuat loader baru. Biasanya ini adalah {@link +android.content.CursorLoader}, namun Anda bisa mengimplementasikan sendiri subkelas {@link +android.content.Loader}. </p> + +<p>Dalam contoh ini, metode callback {@link +android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} + akan membuat {@link android.content.CursorLoader}. Anda harus membuat +{@link android.content.CursorLoader} menggunakan metode konstruktornya, yang +memerlukan set informasi lengkap untuk melakukan query ke {@link +android.content.ContentProvider}. Secara khusus, ia memerlukan:</p> +<ul> + <li><em>uri</em> — URI untuk konten yang akan diambil. </li> + <li><em>projection</em> — Daftar berisi kolom yang akan dikembalikan. Meneruskan +<code>null</code> akan mengembalikan semua kolom, jadi tidak efisien. </li> + <li><em>selection</em> — Filter yang mendeklarasikan baris yang akan dikembalikan, +diformat sebagai klausa SQL WHERE (tidak termasuk WHERE itu sendiri). Meneruskan +<code>null</code> akan mengembalikan semua baris untuk URI yang diberikan. </li> + <li><em>selectionArgs</em> — Anda dapat menyertakan ?s dalam pilihan, yang akan +digantikan dengan nilai dari <em>selectionArgs</em>, agar muncul dalam +pilihan. Nilai-nilai akan diikat sebagai String. </li> + <li><em>sortOrder</em> — Cara menyusun baris, diformat sebagai klausa SQL +ORDER BY (tidak termasuk ORDER BY itu sendiri). Meneruskan <code>null</code> akan +menggunakan urutan sortir default, yang mungkin tidak berurutan.</li> +</ul> +<p>Misalnya:</p> +<pre> + // If non-null, this is the current filter the user has provided. +String mCurFilter; +... +public Loader<Cursor> onCreateLoader(int id, Bundle args) { + // This is called when a new Loader needs to be created. This + // sample only has one Loader, so we don't care about the ID. + // First, pick the base URI to use depending on whether we are + // currently filtering. + Uri baseUri; + if (mCurFilter != null) { + baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, + Uri.encode(mCurFilter)); + } else { + baseUri = Contacts.CONTENT_URI; + } + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + + Contacts.DISPLAY_NAME + " != '' ))"; + return new CursorLoader(getActivity(), baseUri, + CONTACTS_SUMMARY_PROJECTION, select, null, + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); +}</pre> +<h4 id="onLoadFinished">onLoadFinished</h4> + +<p>Metode ini dipanggil bila loader yang dibuat sebelumnya selesai dimuat. +Metode ini dijamin dipanggil sebelum pelepasan data terakhir +yang disediakan untuk loader ini. Di titik ini Anda harus menyingkirkan semua penggunaan +data lama (karena akan segera dilepas), namun jangan melepas sendiri +data tersebut karena loader memilikinya dan akan menanganinya.</p> + + +<p>Loader akan melepas data setelah mengetahui bahwa aplikasi tidak +lagi menggunakannya. Misalnya, jika data adalah kursor dari {@link +android.content.CursorLoader}, Anda tidak boleh memanggil {@link +android.database.Cursor#close close()} sendiri. Jika kursor ditempatkan +dalam {@link android.widget.CursorAdapter}, Anda harus menggunakan metode {@link +android.widget.SimpleCursorAdapter#swapCursor swapCursor()} agar +{@link android.database.Cursor} lama tidak ditutup. Misalnya:</p> + +<pre> +// This is the Adapter being used to display the list's data.<br +/>SimpleCursorAdapter mAdapter; +... + +public void onLoadFinished(Loader<Cursor> loader, Cursor data) { + // Swap the new cursor in. (The framework will take care of closing the + // old cursor once we return.) + mAdapter.swapCursor(data); +}</pre> + +<h4 id="onLoaderReset">onLoaderReset</h4> + +<p>Metode ini dipanggil bila loader yang dibuat sebelumnya sedang di-reset, sehingga datanya +tidak tersedia. Callback ini memungkinkan Anda mengetahui +kapan data akan dilepas sehingga dapat menghapus acuannya ke callback. </p> +<p>Implementasi ini memanggil +{@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()} +dengan nilai <code>null</code>:</p> + +<pre> +// This is the Adapter being used to display the list's data. +SimpleCursorAdapter mAdapter; +... + +public void onLoaderReset(Loader<Cursor> loader) { + // This is called when the last Cursor provided to onLoadFinished() + // above is about to be closed. We need to make sure we are no + // longer using it. + mAdapter.swapCursor(null); +}</pre> + + +<h2 id="example">Contoh</h2> + +<p>Sebagai contoh, berikut ini adalah implementasi penuh {@link +android.app.Fragment} yang menampilkan {@link android.widget.ListView} berisi +hasil query terhadap penyedia konten kontak. Ia menggunakan {@link +android.content.CursorLoader} untuk mengelola query pada penyedia.</p> + +<p>Agar aplikasi dapat mengakses kontak pengguna, seperti yang ditampilkan dalam contoh ini, +manifesnya harus menyertakan izin +{@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}.</p> + +<pre> +public static class CursorLoaderListFragment extends ListFragment + implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> { + + // This is the Adapter being used to display the list's data. + SimpleCursorAdapter mAdapter; + + // If non-null, this is the current filter the user has provided. + String mCurFilter; + + @Override public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + // Give some text to display if there is no data. In a real + // application this would come from a resource. + setEmptyText("No phone numbers"); + + // We have a menu item to show in action bar. + setHasOptionsMenu(true); + + // Create an empty adapter we will use to display the loaded data. + mAdapter = new SimpleCursorAdapter(getActivity(), + android.R.layout.simple_list_item_2, null, + new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS }, + new int[] { android.R.id.text1, android.R.id.text2 }, 0); + setListAdapter(mAdapter); + + // Prepare the loader. Either re-connect with an existing one, + // or start a new one. + getLoaderManager().initLoader(0, null, this); + } + + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + // Place an action bar item for searching. + MenuItem item = menu.add("Search"); + item.setIcon(android.R.drawable.ic_menu_search); + item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + SearchView sv = new SearchView(getActivity()); + sv.setOnQueryTextListener(this); + item.setActionView(sv); + } + + public boolean onQueryTextChange(String newText) { + // Called when the action bar search text has changed. Update + // the search filter, and restart the loader to do a new query + // with this filter. + mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; + getLoaderManager().restartLoader(0, null, this); + return true; + } + + @Override public boolean onQueryTextSubmit(String query) { + // Don't care about this. + return true; + } + + @Override public void onListItemClick(ListView l, View v, int position, long id) { + // Insert desired behavior here. + Log.i("FragmentComplexList", "Item clicked: " + id); + } + + // These are the Contacts rows that we will retrieve. + static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { + Contacts._ID, + Contacts.DISPLAY_NAME, + Contacts.CONTACT_STATUS, + Contacts.CONTACT_PRESENCE, + Contacts.PHOTO_ID, + Contacts.LOOKUP_KEY, + }; + public Loader<Cursor> onCreateLoader(int id, Bundle args) { + // This is called when a new Loader needs to be created. This + // sample only has one Loader, so we don't care about the ID. + // First, pick the base URI to use depending on whether we are + // currently filtering. + Uri baseUri; + if (mCurFilter != null) { + baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, + Uri.encode(mCurFilter)); + } else { + baseUri = Contacts.CONTENT_URI; + } + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + + Contacts.DISPLAY_NAME + " != '' ))"; + return new CursorLoader(getActivity(), baseUri, + CONTACTS_SUMMARY_PROJECTION, select, null, + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); + } + + public void onLoadFinished(Loader<Cursor> loader, Cursor data) { + // Swap the new cursor in. (The framework will take care of closing the + // old cursor once we return.) + mAdapter.swapCursor(data); + } + + public void onLoaderReset(Loader<Cursor> loader) { + // This is called when the last Cursor provided to onLoadFinished() + // above is about to be closed. We need to make sure we are no + // longer using it. + mAdapter.swapCursor(null); + } +}</pre> +<h3 id="more_examples">Contoh Selengkapnya</h3> + +<p>Ada beberapa contoh berbeda dalam <strong>ApiDemos</strong> yang +mengilustrasikan cara menggunakan loader:</p> +<ul> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html"> +LoaderCursor</a> — Versi lengkap dari +cuplikan yang ditampilkan di atas.</li> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a> — Contoh cara penggunaan throttling untuk +mengurangi jumlah query dari penyedia konten saat datanya berubah.</li> +</ul> + +<p>Untuk informasi tentang mengunduh dan menginstal contoh SDK, lihat <a href="http://developer.android.com/resources/samples/get.html"> Mendapatkan +Contoh</a>. </p> + diff --git a/docs/html-intl/intl/id/guide/components/processes-and-threads.jd b/docs/html-intl/intl/id/guide/components/processes-and-threads.jd new file mode 100644 index 000000000000..cdab715bbca8 --- /dev/null +++ b/docs/html-intl/intl/id/guide/components/processes-and-threads.jd @@ -0,0 +1,411 @@ +page.title=Proses dan Thread +page.tags=daur hidup,latar belakang + +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + +<h2>Dalam dokumen ini</h2> +<ol> +<li><a href="#Processes">Proses</a> + <ol> + <li><a href="#Lifecycle">Daur hidup proses</a></li> + </ol> +</li> +<li><a href="#Threads">Thread</a> + <ol> + <li><a href="#WorkerThreads">Thread pekerja</a></li> + <li><a href="#ThreadSafe">Metode thread-safe</a></li> + </ol> +</li> +<li><a href="#IPC">Komunikasi antarproses</a></li> +</ol> + +</div> +</div> + +<p>Bila komponen aplikasi dimulai dan tidak ada komponen aplikasi lain yang +berjalan, sistem Android akan memulai proses Linux baru untuk aplikasi dengan satu thread +eksekusi. Secara default, semua komponen aplikasi yang sama berjalan dalam proses dan +thread yang sama (disebut thread "utama"). Jika komponen aplikasi dimulai dan sudah ada +proses untuk aplikasi itu (karena komponen lain dari aplikasi itu sudah ada), maka komponen +akan dimulai dalam proses itu dan menggunakan thread eksekusi yang sama. Akan tetapi, Anda bisa +mengatur komponen berbeda di aplikasi agar berjalan di proses terpisah, dan Anda bisa membuat thread tambahan untuk +setiap proses.</p> + +<p>Dokumen ini membahas cara kerja proses dan thread di aplikasi Android.</p> + + +<h2 id="Processes">Proses</h2> + +<p>Secara default, semua komponen aplikasi yang sama berjalan dalam proses yang sama dan kebanyakan +aplikasi tidak boleh mengubah ini. Akan tetapi, jika Anda merasa perlu mengontrol proses milik +komponen tertentu, Anda dapat melakukannya dalam file manifes.</p> + +<p>Entri manifes untuk setiap tipe elemen komponen—<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code +<activity>}</a>, <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code +<service>}</a>, <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code +<receiver>}</a>, dan <a href="{@docRoot}guide/topics/manifest/provider-element.html">{@code +<provider>}</a>—mendukung atribut {@code android:process} yang bisa menetapkan +dalam proses mana komponen harus dijalankan. Anda bisa mengatur atribut ini agar setiap komponen +berjalan dalam prosesnya sendiri atau agar beberapa komponen menggunakan proses yang sama sementara yang lainnya tidak. Anda juga bisa mengatur +{@code android:process} agar komponen aplikasi yang berbeda berjalan dalam proses yang sama +—sepanjang aplikasi menggunakan ID Linux yang sama dan ditandatangani +dengan sertifikat yang sama.</p> + +<p>Elemen <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code +<application>}</a> juga mendukung atribut {@code android:process}, untuk mengatur +nilai default yang berlaku bagi semua komponen.</p> + +<p>Android bisa memutuskan untuk mematikan proses pada waktu tertentu, bila memori tinggal sedikit dan diperlukan oleh +proses lain yang lebih mendesak untuk melayani pengguna. Komponen +aplikasi yang berjalan dalam proses yang dimatikan maka sebagai konsekuensinya juga akan dimusnahkan. Proses dimulai +kembali untuk komponen itu bila ada lagi pekerjaan untuk mereka lakukan.</p> + +<p>Saat memutuskan proses yang akan dimatikan, sistem Android akan mempertimbangkan kepentingan relatifnya bagi +pengguna. Misalnya, sistem lebih mudah menghentikan proses yang menjadi host aktivitas yang tidak + lagi terlihat di layar, dibandingkan dengan proses yang menjadi host aktivitas yang terlihat. Karena itu, keputusan +untuk menghentikan proses bergantung pada keadaan komponen yang berjalan dalam proses tersebut. Aturan +yang digunakan untuk menentukan proses yang akan dihentikan dibahas di bawah ini. </p> + + +<h3 id="Lifecycle">Daur hidup proses</h3> + +<p>Sistem Android mencoba mempertahankan proses aplikasi selama mungkin, namun +pada akhirnya perlu menghapus proses lama untuk mengambil kembali memori bagi proses baru atau yang lebih penting. Untuk +menentukan proses yang akan +dipertahankan dan yang harus dimatikan, sistem menempatkan setiap proses ke dalam "hierarki prioritas" berdasarkan +komponen yang berjalan dalam proses dan status komponen tersebut. Proses yang memiliki +prioritas terendah akan dimatikan terlebih dahulu, kemudian yang terendah berikutnya, dan seterusnya, jika perlu +untuk memulihkan sumber daya sistem.</p> + +<p>Ada lima tingkatan dalam hierarki prioritas. Daftar berikut berisi beberapa +tipe proses berdasarkan urutan prioritas (proses pertama adalah yang <em>terpenting</em> dan +<em>dimatikan terakhir</em>):</p> + +<ol> + <li><b>Proses latar depan</b> + <p>Proses yang diperlukan untuk aktivitas yang sedang dilakukan pengguna. Proses +dianggap berada di latar depan jika salah satu kondisi berikut terpenuhi:</p> + + <ul> + <li>Proses menjadi host {@link android.app.Activity} yang berinteraksi dengan pengguna dengan metode ({@link +android.app.Activity}{@link android.app.Activity#onResume onResume()} telah +dipanggil).</li> + + <li>Proses menjadi host {@link android.app.Service} yang terikat dengan aktivitas yang sedang berinteraksi dengan +pengguna.</li> + + <li>Proses menjadi host {@link android.app.Service} yang berjalan "di latar depan"— +layanan telah memanggil{@link android.app.Service#startForeground startForeground()}. + + <li>Proses menjadi host {@link android.app.Service} yang menjalankan salah satu callback +daur hidupnya ({@link android.app.Service#onCreate onCreate()}, {@link android.app.Service#onStart +onStart()}, atau {@link android.app.Service#onDestroy onDestroy()}).</li> + + <li>Proses menjadi host {@link android.content.BroadcastReceiver} yang menjalankan metode {@link + android.content.BroadcastReceiver#onReceive onReceive()}-nya.</li> + </ul> + + <p>Secara umum, hanya ada beberapa proses latar depan pada waktu yang diberikan. Proses dimatikan hanya sebagai +upaya terakhir— jika memori hampir habis sehingga semuanya tidak bisa terus berjalan. Pada umumnya, pada +titik itu, perangkat dalam keadaan memory paging, sehingga menghentikan beberapa proses latar depan +diperlukan agar antarmuka pengguna tetap responsif.</p></li> + + <li><b>Proses yang terlihat</b> + <p>Proses yang tidak memiliki komponen latar depan, namun masih bisa +memengaruhi apa yang dilihat pengguna di layar. Proses dianggap terlihat jika salah satu kondisi +berikut terpenuhi:</p> + + <ul> + <li>Proses ini menjadi host {@link android.app.Activity} yang tidak berada di latar depan, namun masih +terlihat oleh penggunanya (metode {@link android.app.Activity#onPause onPause()} telah dipanggil). +Ini bisa terjadi, misalnya, jika aktivitas latar depan memulai dialog, sehingga +aktivitas sebelumnya terlihat berada di belakangnya.</li> + + <li>Proses menjadi host {@link android.app.Service} yang terikat dengan aktivitas yang terlihat (atau latar +depan)</li> + </ul> + + <p>Proses yang terlihat dianggap sangat penting dan tidak akan dimatikan kecuali jika hal itu +diperlukan agar semua proses latar depan tetap berjalan. </p> + </li> + + <li><b>Proses layanan</b> + <p>Proses yang menjalankan layanan yang telah dimulai dengan metode {@link +android.content.Context#startService startService()} dan tidak termasuk dalam salah satu dari dua kategori +yang lebih tinggi. Walaupun proses pelayanan tidak langsung terkait dengan semua yang dilihat oleh pengguna, proses ini +umumnya melakukan hal-hal yang dipedulikan pengguna (seperti memutar musik di latar belakang +atau mengunduh data di jaringan), jadi sistem membuat proses tetap berjalan kecuali memori tidak cukup untuk +mempertahankannya bersama semua proses latar depan dan proses yang terlihat. </p> + </li> + + <li><b>Proses latar belakang</b> + <p>Proses yang menampung aktivitas yang saat ini tidak terlihat oleh pengguna (metode +{@link android.app.Activity#onStop onStop()} aktivitas telah dipanggil). Proses ini tidak memiliki dampak +langsung pada pengalaman pengguna, dan sistem bisa menghentikannya kapan saja untuk memperoleh kembali memori bagi +proses latar depan, proses yang terlihat, +atau proses layanan. Biasanya ada banyak proses latar belakang yang berjalan, sehingga disimpan +dalam daftar LRU (least recently used atau paling sedikit digunakan) untuk memastikan bahwa proses dengan aktivitas yang paling baru +terlihat oleh pengguna sebagai yang terakhir untuk dimatikan. Jika aktivitas mengimplementasikan metode + daur hidupnya dengan benar, dan menyimpan statusnya saat ini, menghentikan prosesnya tidak akan memiliki efek +yang terlihat pada pengalaman pengguna, karena ketika pengguna kembali ke aktivitas, aktivitas itu memulihkan +semua statusnya yang terlihat. Lihat dokumen <a href="{@docRoot}guide/components/activities.html#SavingActivityState">Aktivitas</a> + untuk mendapatkan informasi tentang menyimpan dan memulihkan status.</p> + </li> + + <li><b>Proses kosong</b> + <p>Sebuah proses yang tidak berisi komponen aplikasi aktif apa pun. Alasan satu-satunya mempertahankan proses +seperti ini tetap hidup adalah untuk keperluan caching, meningkatkan waktu mulai (startup) bila +nanti komponen perlu dijalankan di dalamnya. Sistem sering menghentikan proses ini untuk menyeimbangkan sumber +daya sistem secara keseluruhan antara proses cache dan cache kernel yang mendasarinya.</p> + </li> +</ol> + + + <p>Android sebisa mungkin memeringkat proses setinggi +mungkin, berdasarkan prioritas komponen yang sedang aktif dalam proses. Misalnya, jika suatu proses menjadi host sebuah layanan dan +aktivitas yang terlihat, proses akan diperingkat sebagai proses yang terlihat, bukan sebagai proses layanan.</p> + + <p>Selain itu, peringkat proses dapat meningkat karena adanya proses lain yang bergantung padanya +—proses yang melayani proses lain tidak bisa diperingkat lebih rendah daripada proses yang +sedang dilayaninya. Misalnya, jika penyedia konten dalam proses A melayani klien dalam proses B, atau +jika layanan dalam proses A terikat dengan komponen dalam proses B, proses A selalu dipertimbangkan sebagai paling rendah +prioritasnya dibandingkan dengan proses B.</p> + + <p>Karena proses yang menjalankan layanan diperingkat lebih tinggi daripada aktivitas latar belakang, +aktivitas yang memulai operasi yang berjalan lama mungkin lebih baik memulai <a href="{@docRoot}guide/components/services.html">layanan</a> untuk operasi itu, daripada hanya +membuat thread pekerja—khususnya jika operasi mungkin akan berlangsung lebih lama daripada aktivitas. + Misalnya, aktivitas yang mengunggah gambar ke situs web harus memulai layanan +untuk mengunggah sehingga unggahan bisa terus berjalan di latar belakang meskipun pengguna meninggalkan aktivitas tersebut. +Menggunakan layanan akan memastikan operasi paling tidak memiliki prioritas "proses layanan", +apa pun yang terjadi pada aktivitas. Ini menjadi alasan yang sama yang membuat penerima siaran harus +menjalankan layanan daripada hanya menempatkan operasi yang menghabiskan waktu di thread.</p> + + + + +<h2 id="Threads">Thread</h2> + +<p>Bila aplikasi diluncurkan, sistem akan membuat thread eksekusi untuk aplikasi tersebut, yang diberi nama, +"main". Thread ini sangat penting karena bertugas mengirim kejadian ke widget +antarmuka pengguna yang sesuai, termasuk kejadian menggambar. Ini juga merupakan thread yang +membuat aplikasi berinteraksi dengan komponen dari Android UI toolkit (komponen dari paket {@link +android.widget} dan {@link android.view}). Karena itu, thread 'main' juga terkadang +disebut thread UI.</p> + +<p>Sistem ini <em>tidak</em> membuat thread terpisah untuk setiap instance komponen. Semua +komponen yang berjalan di proses yang sama akan dibuat instance-nya dalam thread UI, dan sistem akan memanggil +setiap komponen yang dikirim dari thread itu. Akibatnya, metode yang merespons callback sistem + (seperti {@link android.view.View#onKeyDown onKeyDown()} untuk melaporkan tindakan pengguna atau metode callback daur hidup) + selalu berjalan di thread UI proses.</p> + +<p>Misalnya saat pengguna menyentuh tombol pada layar, thread UI aplikasi akan mengirim kejadian +sentuh ke widget, yang selanjutnya menetapkan status ditekan dan mengirim permintaan yang tidak divalidasi ke +antrean kejadian. Thread UI akan menghapus antrean permintaan dan memberi tahu widget bahwa widget harus menggambar +dirinya sendiri.</p> + +<p>Saat aplikasi melakukan pekerjaan intensif sebagai respons terhadap interaksi pengguna, model +thread tunggal ini bisa menghasilkan kinerja yang buruk kecuali jika Anda mengimplementasikan aplikasi dengan benar. Khususnya jika + semua terjadi di thread UI, melakukan operasi yang panjang seperti akses ke jaringan atau query +database akan memblokir seluruh UI. Bila thread diblokir, tidak ada kejadian yang bisa dikirim, +termasuk kejadian menggambar. Dari sudut pandang pengguna, aplikasi +tampak mogok (hang). Lebih buruk lagi, jika thread UI diblokir selama lebih dari beberapa detik +(saat ini sekitar 5 detik) pengguna akan ditampilkan dialog "<a href="http://developer.android.com/guide/practices/responsiveness.html">aplikasi tidak +merespons</a>" (ANR) yang populer karena reputasi buruknya. Pengguna nanti bisa memutuskan untuk keluar dari aplikasi dan menghapus aplikasi +jika mereka tidak suka.</p> + +<p>Selain itu, toolkit Android UI <em>bukan</em> thread-safe. Jadi, Anda tidak harus memanipulasi +UI dari thread pekerja—Anda harus melakukan semua manipulasi pada antarmuka pengguna dari thread +UI. Sehingga hanya ada dua aturan untuk model thread tunggal Android:</p> + +<ol> +<li>Jangan memblokir thread UI +<li>Jangan mengakses toolkit Android UI dari luar thread UI +</ol> + +<h3 id="WorkerThreads">Thread pekerja</h3> + +<p>Karena model thread tunggal yang dijelaskan di atas, Anda dilarang memblokir thread +UI demi daya respons UI aplikasi. Jika memiliki operasi untuk dijalankan +yang tidak seketika, Anda harus memastikan untuk melakukannya di thread terpisah (thread "latar belakang" atau +thread "pekerja").</p> + +<p>Misalnya, berikut ini beberapa kode untuk listener klik yang mengunduh gambar dari +thread terpisah dan menampilkannya dalam {@link android.widget.ImageView}:</p> + +<pre> +public void onClick(View v) { + new Thread(new Runnable() { + public void run() { + Bitmap b = loadImageFromNetwork("http://example.com/image.png"); + mImageView.setImageBitmap(b); + } + }).start(); +} +</pre> + +<p>Awalnya hal ini tampak bekerja dengan baik, karena menciptakan thread baru untuk menangani +operasi jaringan. Akan tetapi, hal tersebut melanggar aturan kedua model thread tunggal: <em>jangan mengakses + toolkit Android UI dari luar thread UI</em>—sampel ini memodifikasi {@link +android.widget.ImageView} dari thread pekerja sebagai ganti thread UI. Ini bisa +mengakibatkan perilaku yang tidak terdefinisi dan tidak diharapkan, yang bisa menyulitkan dan menghabiskan waktu untuk melacaknya.</p> + +<p>Untuk memperbaiki masalah ini, Android menawarkan beberapa cara untuk mengakses thread UI dari +thread lainnya. Berikut ini daftar metode yang bisa membantu:</p> + +<ul> +<li>{@link android.app.Activity#runOnUiThread(java.lang.Runnable) +Activity.runOnUiThread(Runnable)}</li> +<li>{@link android.view.View#post(java.lang.Runnable) View.post(Runnable)}</li> +<li>{@link android.view.View#postDelayed(java.lang.Runnable, long) View.postDelayed(Runnable, +long)}</li> +</ul> + +<p>Misalnya, Anda bisa memperbaiki kode di atas dengan menggunakan metode {@link +android.view.View#post(java.lang.Runnable) View.post(Runnable)}:</p> + +<pre> +public void onClick(View v) { + new Thread(new Runnable() { + public void run() { + final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png"); + mImageView.post(new Runnable() { + public void run() { + mImageView.setImageBitmap(bitmap); + } + }); + } + }).start(); +} +</pre> + +<p>Kini implementasi ini thread-safe: operasi jaringan dilakukan terpisah dari thread + sementara {@link android.widget.ImageView} dimanipulasi dari thread UI.</p> + +<p>Akan tetapi, karena operasi semakin kompleks, jenis kode seperti ini bisa semakin rumit +dan sulit dipertahankan. Untuk menangani interaksi yang lebih kompleks dengan thread pekerja, Anda bisa mempertimbangkan + penggunaan {@link android.os.Handler}di thread pekerja, untuk memproses pesan yang dikirim dari + thread UI. Mungkin solusi terbaiknya adalah memperpanjang kelas {@link android.os.AsyncTask}, +yang akan menyederhanakan eksekusi tugas-tugas thread pekerja yang perlu berinteraksi dengan UI.</p> + + +<h4 id="AsyncTask">Menggunakan AsyncTask</h4> + +<p>Dengan {@link android.os.AsyncTask}, Anda bisa melakukan pekerjaan asinkron pada antarmuka +pengguna. AsyncTask memblokir operasi di thread pekerja kemudian mempublikasikan hasilnya +di thread UI, tanpa mengharuskan Anda untuk menangani sendiri thread dan/atau handler sendiri.</p> + +<p>Untuk menggunakannya, Anda harus menempatkan {@link android.os.AsyncTask} sebagai subkelas dan mengimplementasikan metode callback {@link +android.os.AsyncTask#doInBackground doInBackground()} yang berjalan di kumpulan +thread latar belakang. Untuk memperbarui UI, Anda harus mengimplementasikan {@link +android.os.AsyncTask#onPostExecute onPostExecute()}, yang memberikan hasil dari {@link +android.os.AsyncTask#doInBackground doInBackground()} dan berjalan di thread UI, jadi Anda bisa +memperbarui UI dengan aman. Selanjutnya Anda bisa menjalankan tugas dengan memanggil {@link android.os.AsyncTask#execute execute()} +dari thread UI.</p> + +<p>Misalnya, Anda bisa mengimplementasikan contoh sebelumnya menggunakan {@link android.os.AsyncTask} dengan cara +ini:</p> + +<pre> +public void onClick(View v) { + new DownloadImageTask().execute("http://example.com/image.png"); +} + +private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { + /** The system calls this to perform work in a worker thread and + * delivers it the parameters given to AsyncTask.execute() */ + protected Bitmap doInBackground(String... urls) { + return loadImageFromNetwork(urls[0]); + } + + /** The system calls this to perform work in the UI thread and delivers + * the result from doInBackground() */ + protected void onPostExecute(Bitmap result) { + mImageView.setImageBitmap(result); + } +} +</pre> + +<p>Kini UI aman dan kode jadi lebih sederhana, karena memisahkan pekerjaan ke +dalam bagian-bagian yang harus dilakukan pada thread pekerja dan thread UI.</p> + +<p>Anda harus membaca acuan {@link android.os.AsyncTask} untuk memahami sepenuhnya +cara menggunakan kelas ini, namun berikut ini ikhtisar singkat cara kerjanya:</p> + +<ul> +<li>Anda bisa menetapkan tipe parameter, nilai kemajuan, dan nilai + akhir tugas, dengan menggunakan generik</li> +<li>Metode {@link android.os.AsyncTask#doInBackground doInBackground()} berjalan secara otomatis pada +thread pekerja</li> +<li>{@link android.os.AsyncTask#onPreExecute onPreExecute()}, {@link +android.os.AsyncTask#onPostExecute onPostExecute()}, dan {@link +android.os.AsyncTask#onProgressUpdate onProgressUpdate()} semuanya dipanggil pada thread UI</li> +<li>Nilai yang dikembalikan oleh {@link android.os.AsyncTask#doInBackground doInBackground()} akan dikirim ke +{@link android.os.AsyncTask#onPostExecute onPostExecute()}</li> +<li>Anda bisa memangil {@link android.os.AsyncTask#publishProgress publishProgress()} setiap saat di {@link +android.os.AsyncTask#doInBackground doInBackground()} untuk mengeksekusi {@link +android.os.AsyncTask#onProgressUpdate onProgressUpdate()} pada thread UI</li> +<li>Anda bisa membatalkan tugas ini kapan saja, dari thread mana saja</li> +</ul> + +<p class="caution"><strong>Perhatian:</strong> Masalah lain yang mungkin Anda temui saat menggunakan +thread pekerja adalah restart tak terduga dalam aktivitas karena <a href="{@docRoot}guide/topics/resources/runtime-changes.html">perubahan konfigurasi runtime</a> + (seperti saat pengguna mengubah orientasi layar), yang bisa memusnahkan thread pekerja. Untuk +melihat cara mempertahankan tugas selama restart ini dan cara membatalkan +tugas dengan benar saat aktivitas dimusnahkan, lihat kode sumber untuk aplikasi sampel <a href="http://code.google.com/p/shelves/">Shelves</a>.</p> + + +<h3 id="ThreadSafe">Metode thread-safe</h3> + +<p> Dalam beberapa situasi, metode yang Anda implementasikan bisa dipanggil dari lebih dari satu thread, +dan karena itu harus ditulis agar menjadi thread-safe. </p> + +<p>Ini terutama terjadi untuk metode yang bisa dipanggil dari jauh —seperti metode dalam <a href="{@docRoot}guide/components/bound-services.html">layanan terikat</a>. Bila sebuah panggilan pada +metode yang dijalankan dalam {@link android.os.IBinder} berasal dari proses yang sama di mana +{@link android.os.IBinder IBinder} berjalan, metode ini akan dieksekusi di thread pemanggil. +Akan tetapi, bila panggilan berasal proses lain, metode akan dieksekusi dalam thread yang dipilih dari + kumpulan (pool) thread yang dipertahankan sistem dalam proses yang sama seperti{@link android.os.IBinder +IBinder} (tidak dieksekusi dalam thread UI proses). Misalnya, karena metode +{@link android.app.Service#onBind onBind()} layanan akan dipanggil dari thread UI +proses layanan, metode yang diimplementasikan dalam objek yang dikembalikan {@link android.app.Service#onBind +onBind()} (misalnya, subkelas yang mengimplementasikan metode RPC) akan dipanggil dari thread +di pool. Karena layanan bisa memiliki lebih dari satu klien, maka lebih dari satu pool thread bisa melibatkan + metode {@link android.os.IBinder IBinder} yang sama sekaligus. Metode {@link android.os.IBinder +IBinder} karenanya harus diimplementasikan sebagai thread-safe.</p> + +<p> Penyedia konten juga bisa menerima permintaan data yang berasal dalam proses lain. +Meskipun kelas {@link android.content.ContentResolver} dan {@link android.content.ContentProvider} + menyembunyikan detail cara komunikasi antarproses dikelola, metode {@link +android.content.ContentProvider} yang merespons permintaan itu—metode {@link +android.content.ContentProvider#query query()}, {@link android.content.ContentProvider#insert +insert()}, {@link android.content.ContentProvider#delete delete()}, {@link +android.content.ContentProvider#update update()}, dan {@link android.content.ContentProvider#getType +getType()}— dipanggil dari pool thread pada proses penyedia konten, bukan thread UI +untuk proses tersebut. Mengingat metode ini bisa dipanggil dari thread mana pun +sekaligus, metode-metode ini juga harus diimplementasikan sebagai thread-safe. </p> + + +<h2 id="IPC">Komunikasi Antarproses</h2> + +<p>Android menawarkan mekanisme komunikasi antarproses (IPC) menggunakan panggilan prosedur jauh + (RPC), yang mana metode ini dipanggil oleh aktivitas atau komponen aplikasi lain, namun dieksekusi dari +jauh (di proses lain), bersama hasil yang dikembalikan ke +pemanggil. Ini mengharuskan penguraian panggilan metode dan datanya ke tingkat yang bisa +dipahami sistem operasi, mentransmisikannya dari proses lokal dan ruang alamat untuk proses jauh +dan ruang proses, kemudian merakit kembali dan menetapkannya kembali di sana. Nilai-nilai yang dikembalikan +akan ditransmisikan dalam arah berlawanan. Android menyediakan semua kode untuk melakukan transaksi IPC + ini, sehingga Anda bisa fokus pada pendefinisian dan implementasi antarmuka pemrograman RPC. </p> + +<p>Untuk melakukan IPC, aplikasi Anda harus diikat ke layanan, dengan menggunakan {@link +android.content.Context#bindService bindService()}. Untuk informasi selengkapnya, lihat panduan pengembang <a href="{@docRoot}guide/components/services.html">Layanan</a>.</p> + + +<!-- +<h2>Beginner's Path</h2> + +<p>For information about how to perform work in the background for an indefinite period of time +(without a user interface), continue with the <b><a +href="{@docRoot}guide/components/services.html">Services</a></b> document.</p> +--> diff --git a/docs/html-intl/intl/id/guide/components/recents.jd b/docs/html-intl/intl/id/guide/components/recents.jd new file mode 100644 index 000000000000..286fdc12732e --- /dev/null +++ b/docs/html-intl/intl/id/guide/components/recents.jd @@ -0,0 +1,256 @@ +page.title=Layar Ikhtisar +page.tags="recents","overview" + +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + + <h2>Dalam dokumen ini</h2> + <ol> + <li><a href="#adding">Menambahkan Tugas ke Layar Ikhtisar</a> + <ol> + <li><a href="#flag-new-doc">Menggunakan flag Intent untuk menambahkan tugas</a></li> + <li><a href="#attr-doclaunch">Menggunakan atribut Aktivitas untuk menambahkan tugas</a></li> + </ol> + </li> + <li><a href="#removing">Menghapus Tugas</a> + <ol> + <li><a href="#apptask-remove">Menggunakan kelas AppTask untuk menghapus tugas</a></li> + <li><a href="#retain-finished">Mempertahankan tugas yang telah selesai</a></li> + </ol> + </li> + </ol> + + <h2>Kelas-kelas utama</h2> + <ol> + <li>{@link android.app.ActivityManager.AppTask}</li> + <li>{@link android.content.Intent}</li> + </ol> + + <h2>Kode contoh</h2> + <ol> + <li><a href="{@docRoot}samples/DocumentCentricApps/index.html">Aplikasi yang berorientasi dokumen</a></li> + </ol> + +</div> +</div> + +<p>Layar ikhtisar (juga disebut sebagai layar terbaru, daftar tugas terbaru, atau aplikasi terbaru) +UI tingkat sistem yang mencantumkan <a href="{@docRoot}guide/components/activities.html"> +aktivitas</a> dan <a href="{@docRoot}guide/components/tasks-and-back-stack.html">tugas</a> yang baru saja diakses. Pengguna +bisa menyusuri daftar ini dan memilih satu tugas untuk dilanjutkan, atau pengguna bisa menghapus tugas dari +daftar dengan gerakan mengusap. Dengan dirilisnya Android 5.0 (API level 21), beberapa instance aktivitas yang +sama yang berisi dokumen berbeda dapat muncul sebagai tugas di layar ikhtisar. Misalnya, +Google Drive mungkin memiliki satu tugas untuk setiap beberapa dokumen Google. Setiap dokumen muncul sebagai +tugas dalam layar ikhtisar.</p> + +<img src="{@docRoot}images/components/recents.png" alt="" width="284" /> +<p class="img-caption"><strong>Gambar 1.</strong> Layar ikhtisar menampilkan tiga dokumen +Google Drive, masing-masing dinyatakan sebagai tugas terpisah.</p> + +<p>Biasanya Anda harus mengizinkan sistem mendefinisikan cara menyatakan tugas dan +aktivitas di layar ikhtisar, dan Anda tidak perlu memodifikasi perilaku ini. +Akan tetapi, aplikasi Anda dapat menentukan cara dan waktu munculnya aktivitas di layar ikhtisar. Kelas +{@link android.app.ActivityManager.AppTask} memungkinkan Anda mengelola tugas, dan flag + aktivitas kelas {@link android.content.Intent} memungkinkan Anda menentukan kapan aktivitas ditambahkan atau dihapus dari +layar ikhtisar. Selain itu, atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html"> +<activity></a></code> memungkinkan Anda menetapkan perilaku di manifes.</p> + +<h2 id="adding">Menambahkan Tugas ke Layar Ikhtisar</h2> + +<p>Penggunaan flag kelas {@link android.content.Intent} untuk menambahkan tugas memberi kontrol lebih besar +atas waktu dan cara dokumen dibuka atau dibuka kembali di layar ikhtisar. Bila menggunakan atribut +<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> +, Anda dapat memilih antara selalu membuka dokumen dalam tugas baru atau menggunakan kembali tugas +yang ada untuk dokumen tersebut.</p> + +<h3 id="flag-new-doc">Menggunakan flag Intent untuk menambahkan tugas</h3> + +<p>Bila membuat dokumen baru untuk aktivitas, Anda memanggil metode +{@link android.app.ActivityManager.AppTask#startActivity(android.content.Context, android.content.Intent, android.os.Bundle) startActivity()} + dari kelas {@link android.app.ActivityManager.AppTask}, dengan meneruskannya ke intent yang +menjalankan aktivitas tersebut. Untuk menyisipkan jeda logis agar sistem memperlakukan aktivitas Anda sebagai tugas +baru di layar ikhtisar, teruskan flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} +dalam metode {@link android.content.Intent#addFlags(int) addFlags()} dari {@link android.content.Intent} +yang memulai aktivitas itu.</p> + +<p class="note"><strong>Catatan:</strong> Flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} +menggantikan flag {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET}, +yang tidak digunakan lagi pada Android 5.0 (API level 21).</p> + +<p>Jika Anda menetapkan flag {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} saat membuat +dokumen baru, sistem akan selalu membuat tugas baru dengan aktivitas target sebagai akar. +Dengan pengaturan ini, dokumen yang sama dapat dibuka di lebih dari satu tugas. Kode berikut memperagakan +cara aktivitas utama melakukannya:</p> + +<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html"> +DocumentCentricActivity.java</a></p> +<pre> +public void createNewDocument(View view) { + final Intent newDocumentIntent = newDocumentIntent(); + if (useMultipleTasks) { + newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + } + startActivity(newDocumentIntent); + } + + private Intent newDocumentIntent() { + boolean useMultipleTasks = mCheckbox.isChecked(); + final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class); + newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, incrementAndGet()); + return newDocumentIntent; + } + + private static int incrementAndGet() { + Log.d(TAG, "incrementAndGet(): " + mDocumentCounter); + return mDocumentCounter++; + } +} +</pre> + +<p class="note"><strong>Catatan:</strong> Aktivitas yang dimulai dengan flag {@code FLAG_ACTIVITY_NEW_DOCUMENT} + harus telah menetapkan nilai atribut {@code android:launchMode="standard"} (default) dalam +manifes.</p> + +<p>Bila aktivitas utama memulai aktivitas baru, sistem akan mencari tugas yang intent +-nya cocok dengan nama komponen intent dalam tugas-tugas yang sudah ada dan mencari aktivitas dalam data Intent. Jika tugas +tidak ditemukan, atau intent ada dalam flag {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} +, tugas baru akan dibuat dengan aktivitas tersebut sebagai akarnya. Jika ditemukan, sistem akan +mengedepankan tugas itu dan meneruskan intent baru ke {@link android.app.Activity#onNewIntent onNewIntent()}. +Aktivitas baru akan mendapatkan intent dan membuat dokumen baru di layar ikhtisar, seperti dalam +contoh berikut:</p> + +<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html"> +NewDocumentActivity.java</a></p> +<pre> +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_new_document); + mDocumentCount = getIntent() + .getIntExtra(DocumentCentricActivity.KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0); + mDocumentCounterTextView = (TextView) findViewById( + R.id.hello_new_document_text_view); + setDocumentCounterText(R.string.hello_new_document_counter); +} + +@Override +protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + /* If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this activity + is reused to create a new document. + */ + setDocumentCounterText(R.string.reusing_document_counter); +} +</pre> + + +<h3 id="#attr-doclaunch">Menggunakan atribut Aktivitas untuk menambahkan tugas</h3> + +<p>Aktivitas juga dapat menetapkan dalam manifesnya agar selalu dimulai ke dalam tugas baru dengan menggunakan +atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> +, <a href="{@docRoot}guide/topics/manifest/activity-element.html#dlmode"> +{@code android:documentLaunchMode}</a>. Atribut ini memiliki empat nilai yang menghasilkan efek berikut +bila pengguna membuka dokumen dengan aplikasi:</p> + +<dl> + <dt>"{@code intoExisting}"</dt> + <dd>Aktivitas menggunakan kembali tugas yang ada untuk dokumen tersebut. Ini sama dengan mengatur flag + {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} <em>tanpa</em> mengatur flag + {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}, seperti dijelaskan dalam + <a href="#flag-new-doc">Menggunakan flag Intent untuk menambahkan tugas</a>, di atas.</dd> + + <dt>"{@code always}"</dt> + <dd>Aktivitas ini membuat tugas baru untuk dokumen, meski dokumen sudah dibuka. Menggunakan + nilai ini sama dengan menetapkan flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} + maupun {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}.</dd> + + <dt>"{@code none”}"</dt> + <dd>Aktivitas ini tidak membuat tugas baru untuk dokumen. Layar ikhtisar memperlakukan + aktivitas seperti itu secara default: satu tugas ditampilkan untuk aplikasi, yang +dilanjutkan dari aktivitas apa pun yang terakhir dipanggil pengguna.</dd> + + <dt>"{@code never}"</dt> + <dd>Aktivitas ini tidak membuat tugas baru untuk dokumen. Mengatur nilai ini akan mengesampingkan + perilaku flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} + dan {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}, jika salah satunya ditetapkan di +intent, dan layar ikhtisar menampilkan satu tugas untuk aplikasi, yang dilanjutkan dari + aktivitas apa pun yang terakhir dipanggil pengguna.</dd> +</dl> + +<p class="note"><strong>Catatan:</strong> Untuk nilai selain {@code none} dan {@code never}, +aktivitas harus didefinisikan dengan {@code launchMode="standard"}. Jika atribut ini tidak ditetapkan, maka +{@code documentLaunchMode="none"} akan digunakan.</p> + +<h2 id="removing">Menghapus Tugas</h2> + +<p>Secara default, tugas dokumen secara otomatis dihapus dari layar ikhtisar bila aktivitasnya +selesai. Anda bisa mengesampingkan perilaku ini dengan kelas {@link android.app.ActivityManager.AppTask}, +dengan flag {@link android.content.Intent} atau atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html"> +<activity></a></code>.</p> + +<p>Kapan saja Anda bisa mengecualikan tugas dari layar ikhtisar secara keseluruhan dengan menetapkan atribut +<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> +, <a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude"> +{@code android:excludeFromRecents}</a> hingga {@code true}.</p> + +<p>Anda bisa menetapkan jumlah maksimum tugas yang dapat disertakan aplikasi Anda dalam layar ikhtisar dengan menetapkan +atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> + <a href="{@docRoot}guide/topics/manifest/activity-element.html#maxrecents">{@code android:maxRecents} +</a> ke satu nilai integer. Nilai default-nya adalah 16. Bila telah mencapai jumlah maksimum, tugas yang terakhir +digunakan akan dihapus dari layar ikhtisar. Nilai maksimum {@code android:maxRecents} + adalah 50 (25 pada perangkat dengan memori sedikit); nilai yang kurang dari 1 tidak berlaku.</p> + +<h3 id="#apptask-remove">Menggunakan kelas AppTask untuk menghapus tugas</h3> + +<p>Dalam aktivitas yang membuat tugas baru di layar ikhtisar, Anda bisa +menetapkan kapan menghapus tugas dan menyelesaikan semua aktivitas yang terkait dengannya +dengan memanggil metode {@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()}.</p> + +<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html"> +NewDocumentActivity.java</a></p> +<pre> +public void onRemoveFromRecents(View view) { + // The document is no longer needed; remove its task. + finishAndRemoveTask(); +} +</pre> + +<p class="note"><strong>Catatan:</strong> Penggunaan metode +{@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()} +akan mengesampingkan penggunaan tag {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS}, seperti +dibahas di bawah ini.</p> + +<h3 id="#retain-finished">Mempertahankan tugas yang telah selesai</h3> + +<p>Jika Anda ingin mempertahankan tugas di layar ikhtisar, sekalipun aktivitas sudah selesai, teruskan +flag {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS} dalam metode +{@link android.content.Intent#addFlags(int) addFlags()} dari Intent yang memulai aktivitas itu.</p> + +<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html"> +DocumentCentricActivity.java</a></p> +<pre> +private Intent newDocumentIntent() { + final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class); + newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | + android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS); + newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, incrementAndGet()); + return newDocumentIntent; +} +</pre> + +<p>Untuk memperoleh efek yang sama, tetapkan atribut +<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> + <a href="{@docRoot}guide/topics/manifest/activity-element.html#autoremrecents"> +{@code android:autoRemoveFromRecents}</a> hingga {@code false}. Nilai default-nya adalah {@code true} +untuk aktivitas dokumen, dan {@code false} untuk aktivitas biasa. Penggunaan atribut ini akan mengesampingkan flag +{@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS}, yang telah dibahas sebelumnya.</p> + + + + + + + diff --git a/docs/html-intl/intl/id/guide/components/services.jd b/docs/html-intl/intl/id/guide/components/services.jd new file mode 100644 index 000000000000..b36e5656b0ea --- /dev/null +++ b/docs/html-intl/intl/id/guide/components/services.jd @@ -0,0 +1,813 @@ +page.title=Layanan +@jd:body + +<div id="qv-wrapper"> +<ol id="qv"> +<h2>Dalam dokumen ini</h2> +<ol> +<li><a href="#Basics">Dasar-Dasar</a></li> +<ol> + <li><a href="#Declaring">Mendeklarasikan layanan dalam manifes</a></li> +</ol> +<li><a href="#CreatingAService">Membuat Layanan yang Sudah Dimulai</a> + <ol> + <li><a href="#ExtendingIntentService">Memperluas kelas IntentService</a></li> + <li><a href="#ExtendingService">Memperluas kelas Layanan</a></li> + <li><a href="#StartingAService">Memulai layanan</a></li> + <li><a href="#Stopping">Menghentikan layanan</a></li> + </ol> +</li> +<li><a href="#CreatingBoundService">Membuat Layanan Terikat</a></li> +<li><a href="#Notifications">Mengirim Pemberitahuan ke Pengguna</a></li> +<li><a href="#Foreground">Menjalankan Layanan di Latar Depan</a></li> +<li><a href="#Lifecycle">Mengelola Daur Hidup Layanan</a> +<ol> + <li><a href="#LifecycleCallbacks">Mengimplementasikan callback daur hidup</a></li> +</ol> +</li> +</ol> + +<h2>Kelas-kelas utama</h2> +<ol> + <li>{@link android.app.Service}</li> + <li>{@link android.app.IntentService}</li> +</ol> + +<h2>Contoh</h2> +<ol> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code + ServiceStartArguments}</a></li> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code + LocalService}</a></li> +</ol> + +<h2>Lihat juga</h2> +<ol> +<li><a href="{@docRoot}guide/components/bound-services.html">Layanan Terikat</a></li> +</ol> + +</div> + + +<p>{@link android.app.Service} adalah sebuah komponen aplikasi yang bisa melakukan +operasi yang berjalan lama di latar belakang dan tidak menyediakan antarmuka pengguna. Komponen +aplikasi lain bisa memulai layanan dan komponen aplikasi tersebut akan terus berjalan +di latar belakang walaupun pengguna beralih ke aplikasi lain. Selain itu, komponen bisa mengikat ke layanan +untuk berinteraksi dengannya dan bahkan melakukan komunikasi antarproses (IPC). Misalnya, layanan mungkin +menangani transaksi jaringan, memutar musik, melakukan file I/O, atau berinteraksi dengan penyedia konten +dari latar belakang.</p> + +<p>Ada dua bentuk dasar layanan:</p> + +<dl> + <dt>Sudah Dimulai</dt> + <dd>Layanan "sudah dimulai" bila komponen aplikasi (misalnya aktivitas) memulainya dengan +memanggil {@link android.content.Context#startService startService()}. Sesudah dimulai, layanan +bisa berjalan terus-menerus di latar belakang walaupun komponen yang memulainya telah dimusnahkan. Biasanya, +layanan yang sudah dimulai akan melakukan operasi tunggal dan tidak mengembalikan hasil ke pemanggilnya. +Misalnya, layanan bisa mengunduh atau mengunggah file melalui jaringan. Bila operasi selesai, +layanan seharusnya berhenti sendiri.</dd> + <dt>Terikat</dt> + <dd>Layanan "terikat" bila komponen aplikasi mengikat kepadanya dengan memanggil {@link +android.content.Context#bindService bindService()}. Layanan terikat menawarkan antarmuka +klien-server yang memungkinkan komponen berinteraksi dengan layanan tersebut, mengirim permintaan, mendapatkan hasil dan bahkan +melakukannya pada sejumlah proses dengan komunikasi antarproses (IPC). Layanan terikat hanya berjalan selama +ada komponen aplikasi lain yang terikat padanya. Sejumlah komponen bisa terikat pada layanan secara bersamaan, +namun bila semuanya melepas ikatan, layanan tersebut akan dimusnahkan.</dd> +</dl> + +<p>Walaupun dokumentasi ini secara umum membahas kedua jenis layanan secara terpisah, layanan +Anda bisa menggunakan keduanya—layanan bisa dimulai (untuk berjalan terus-menerus) sekaligus memungkinkan pengikatan. +Cukup mengimplementasikan dua metode callback: {@link +android.app.Service#onStartCommand onStartCommand()} untuk memungkinkan komponen memulainya dan {@link +android.app.Service#onBind onBind()} untuk memungkinkan pengikatan.</p> + +<p>Apakah aplikasi Anda sudah dimulai, terikat, atau keduanya, semua komponen aplikasi +bisa menggunakan layanan (bahkan dari aplikasi terpisah), demikian pula semua komponen bisa menggunakan +suatu aktivitas—dengan memulainya dengan {@link android.content.Intent}. Akan tetapi, Anda bisa mendeklarasikan +layanan sebagai privat, pada file manifes, dan memblokir akses dari aplikasi lain. Hal ini +dibahas selengkapnya di bagian tentang <a href="#Declaring">Mendeklarasikan layanan dalam +manifes</a>.</p> + +<p class="caution"><strong>Perhatian:</strong> Layanan berjalan di +thread utama proses yang menjadi host-nya—layanan <strong>tidak</strong> membuat thread-nya sendiri +dan <strong>tidak</strong> berjalan pada proses terpisah (kecuali bila Anda tentukan demikian). Artinya, +jika layanan Anda akan melakukan pekerjaan yang membutuhkan tenaga CPU besar atau operasi yang memblokir (seperti +pemutaran MP3 atau jaringan), Anda perlu membuat thread baru dalam layanan untuk melakukan pekerjaan tersebut. Dengan menggunakan +thread terpisah, Anda mengurangi risiko terjadinya kesalahan Aplikasi Tidak Merespons (Application Not Responding/ANR) dan +thread utama aplikasi bisa tetap dikhususkan pada interaksi pengguna dengan aktivitas Anda.</p> + + +<h2 id="Basics">Dasar-Dasar</h2> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h3>Haruskah menggunakan layanan atau thread?</h3> + <p>Layanan sekadar komponen yang bisa berjalan di latar belakang walaupun pengguna sedang tidak +berinteraksi dengan aplikasi Anda. Sehingga, Anda harus membuat layanan bila memang itu +yang dibutuhkan.</p> + <p>Bila Anda perlu melakukan pekerjaan di luar thread utama, namun hanya bila pengguna sedang berinteraksi +dengan aplikasi, maka Anda harus membuat thread baru sebagai ganti layanan baru. Misalnya, +bila Anda ingin memutar musik, namun hanya saat aktivitas Anda berjalan, Anda bisa membuat +thread dalam {@link android.app.Activity#onCreate onCreate()}, mulai menjalankannya di {@link +android.app.Activity#onStart onStart()}, kemudian menghentikannya di {@link android.app.Activity#onStop +onStop()}. Pertimbangkan juga untuk menggunakan {@link android.os.AsyncTask} atau {@link android.os.HandlerThread}, +sebagai ganti kelas {@link java.lang.Thread} yang lazim digunakan. Lihat dokumen <a href="{@docRoot}guide/components/processes-and-threads.html#Threads">Proses dan +Threading</a> untuk informasi selengkapnya tentang thread.</p> + <p>Ingatlah jika menggunakan layanan, layanan tersebut tetap berjalan di thread utama aplikasi Anda secara +default, jadi Anda harus tetap membuat thread baru dalam layanan bila layanan tersebut melakukan operasi yang intensif +atau operasi yang memblokir.</p> +</div> +</div> + +<p>Untuk membuat layanan, Anda harus membuat subkelas {@link android.app.Service} (atau +salah satu dari subkelasnya yang ada). Dalam implementasi, Anda perlu mengesampingkan sebagian metode callback yang +menangani aspek utama daur hidup layanan dan memberikan mekanisme bagi komponen untuk mengikat +pada layanan, bila dibutuhkan. Metode callback terpenting yang perlu Anda kesampingkan adalah:</p> + +<dl> + <dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt> + <dd>Sistem akan memanggil metode ini bila komponen lain, misalnya aktivitas, +meminta dimulainya layanan, dengan memanggil {@link android.content.Context#startService +startService()}. Setelah metode ini dieksekusi, layanan akan dimulai dan bisa berjalan di +latar belakang terus-menerus. Jika mengimplementasikan ini, Anda bertanggung jawab menghentikan layanan bila +bila pekerjaannya selesai, dengan memanggil {@link android.app.Service#stopSelf stopSelf()} atau {@link +android.content.Context#stopService stopService()}. (Jika hanya ingin menyediakan pengikatan, Anda tidak +perlu mengimplementasikan metode ini.)</dd> + <dt>{@link android.app.Service#onBind onBind()}</dt> + <dd>Sistem akan memanggil metode ini bila komponen lain ingin mengikat pada +layanan (misalnya untuk melakukan RPC), dengan memanggil {@link android.content.Context#bindService +bindService()}. Dalam mengimplementasikan metode ini, Anda harus menyediakan antarmuka yang digunakan +klien untuk berkomunikasi dengan layanan, dengan mengembalikan {@link android.os.IBinder}. Anda harus selalu +mengimplementasikan metode ini, namun jika tidak ingin mengizinkan pengikatan, Anda perlu mengembalikan null.</dd> + <dt>{@link android.app.Service#onCreate()}</dt> + <dd>Sistem memanggil metode ini bila layanan dibuat untuk pertama kalinya, untuk melakukan prosedur +penyiapan satu kali (sebelum memanggil {@link android.app.Service#onStartCommand onStartCommand()} atau +{@link android.app.Service#onBind onBind()}). Bila layanan sudah berjalan, metode ini tidak +dipanggil.</dd> + <dt>{@link android.app.Service#onDestroy()}</dt> + <dd>Sistem memanggil metode ini bila layanan tidak lagi digunakan dan sedang dimusnahkan. +Layanan Anda perlu mengimplementasikannya untuk membersihkan sumber daya seperti thread, listener +terdaftar, penerima, dll. Ini adalah panggilan terakhir yang diterima layanan.</dd> +</dl> + +<p>Bila komponen memulai layanan dengan memanggil {@link +android.content.Context#startService startService()} (yang menyebabkan panggilan ke {@link +android.app.Service#onStartCommand onStartCommand()}), maka layanan +terus berjalan hingga terhenti sendiri dengan {@link android.app.Service#stopSelf()} atau bila komponen +lain menghentikannya dengan memanggil {@link android.content.Context#stopService stopService()}.</p> + +<p>Bila komponen memanggil +{@link android.content.Context#bindService bindService()} untuk membuat layanan (dan {@link +android.app.Service#onStartCommand onStartCommand()} <em>tidak</em> dipanggil), maka layanan hanya berjalan +selama komponen terikat kepadanya. Setelah layanan dilepas ikatannya dari semua klien, +sistem akan menghancurkannya.</p> + +<p>Sistem Android akan menghentikan paksa layanan hanya bila memori tinggal sedikit dan sistem harus memulihkan +sumber daya sistem untuk aktivitas yang mendapatkan fokus pengguna. Jika layanan terikat pada suatu aktivitas yang mendapatkan +fokus pengguna, layanan tersebut lebih kecil kemungkinannya untuk dimatikan, dan jika layanan dideklarasikan untuk <a href="#Foreground">berjalan di latar depan</a> (akan dibahas kemudian), maka sudah hampir pasti ia tidak akan dimatikan. +Sebaliknya, bila layanan sudah dimulai dan berjalan lama, maka sistem akan menurunkan posisinya +dalam daftar tugas latar belakang seiring waktu dan layanan akan sangat rentan untuk +dimatikan—bila layanan Anda dimulai, maka Anda harus mendesainnya agar bisa menangani restart +oleh sistem dengan baik. Jika sistem mematikan layanan Anda, layanan akan dimulai kembali begitu sumber daya +kembali tersedia (tetapi ini juga bergantung pada nilai yang Anda kembalikan dari {@link +android.app.Service#onStartCommand onStartCommand()}, sebagaimana akan dibahas nanti). Untuk informasi selengkapnya +tentang kapan sistem mungkin akan memusnahkan layanan, lihat dokumen +<a href="{@docRoot}guide/components/processes-and-threads.html">Proses dan Threading</a>.</p> + +<p>Dalam bagian selanjutnya, Anda akan melihat bagaimana membuat masing-masing tipe layanan dan cara menggunakannya +dari komponen aplikasi lain.</p> + + + +<h3 id="Declaring">Mendeklarasikan layanan dalam manifes</h3> + +<p>Sebagaimana aktivitas (dan komponen lainnya), Anda harus mendeklarasikan semua layanan dalam file manifes +aplikasi Anda.</p> + +<p>Untuk mendeklarasikan layanan Anda, tambahkan sebuah elemen <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> +sebagai anak +elemen <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>. Misalnya:</p> + +<pre> +<manifest ... > + ... + <application ... > + <service android:name=".ExampleService" /> + ... + </application> +</manifest> +</pre> + +<p>Lihat acuan elemen <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> +untuk informasi selengkapnya tentang cara mendeklarasikan layanan Anda dalam manifes.</p> + +<p>Ada atribut lain yang bisa Anda sertakan dalam elemen <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> untuk +mendefinisikan properti seperti izin yang dibutuhkan untuk memulai layanan dan proses +tempat berjalannya layanan. <a href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a> adalah satu-satunya atribut yang diperlukan +—atribut tersebut menetapkan nama kelas layanan. Setelah +mempublikasikan aplikasi, Anda tidak boleh mengubah nama ini, karena jika melakukannya, Anda bisa merusak +kode karena dependensi terhadap intent eksplisit untuk memulai atau mengikat layanan (bacalah posting blog berjudul <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things +That Cannot Change</a>). + +<p>Untuk memastikan aplikasi Anda aman, <strong>selalu gunakan intent eksplisit saat memulai atau mengikat +{@link android.app.Service} Anda</strong> dan jangan mendeklarasikan filter intent untuk layanan. Jika +Anda perlu membiarkan adanya ambiguitas tentang layanan mana yang dimulai, Anda bisa +menyediakan filter intent bagi layanan dan tidak memasukkan nama komponen pada {@link +android.content.Intent}, namun Anda juga harus menyesuaikan paket bagi intent tersebut dengan {@link +android.content.Intent#setPackage setPackage()}, yang memberikan klarifikasi memadai bagi +target layanan.</p> + +<p>Anda juga bisa memastikan layanan tersedia hanya bagi aplikasi Anda dengan +menyertakan atribut <a href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a> +dan mengaturnya ke {@code "false"}. Hal ini efektif menghentikan aplikasi lain agar tidak memulai +layanan Anda, bahkan saat menggunakan intent eksplisit.</p> + + + + +<h2 id="CreatingStartedService">Membuat Layanan yang Sudah Dimulai</h2> + +<p>Layanan yang sudah dimulai adalah layanan yang dimulai komponen lain dengan memanggil {@link +android.content.Context#startService startService()}, yang menyebabkan panggilan ke metode +{@link android.app.Service#onStartCommand onStartCommand()} layanan.</p> + +<p>Bila layanan sudah dimulai, layanan tersebut memiliki daur hidup yang tidak bergantung pada +komponen yang memulainya dan bisa berjalan terus-menerus di latar belakang walaupun +komponen yang memulainya dimusnahkan. Dengan sendirinya, layanan akan berhenti sendiri bila pekerjaannya +selesai dengan memanggil {@link android.app.Service#stopSelf stopSelf()}, atau komponen lain bisa menghentikannya +dengan memanggil {@link android.content.Context#stopService stopService()}.</p> + +<p>Komponen aplikasi seperti aktivitas bisa memulai layanan dengan memanggil {@link +android.content.Context#startService startService()} dan meneruskan {@link android.content.Intent} +yang menetapkan layanan dan menyertakan data untuk digunakan layanan. Layanan menerima +{@link android.content.Intent} ini dalam metode {@link android.app.Service#onStartCommand +onStartCommand()}.</p> + +<p>Sebagai contoh, anggaplah aktivitas perlu menyimpan data ke database online. Aktivitas tersebut bisa +memulai layanan pendamping dan mengiriminya data untuk disimpan dengan meneruskan intent ke {@link +android.content.Context#startService startService()}. Layanan akan menerima intent dalam {@link +android.app.Service#onStartCommand onStartCommand()}, menghubungkan ke Internet dan melakukan +transaksi database. Bila transaksi selesai, layanan akan berhenti sendiri dan +dimusnahkan.</p> + +<p class="caution"><strong>Perhatian:</strong> Layanan berjalan dalam proses yang sama dengan aplikasi +tempatnya dideklarasikan dan dalam thread utama aplikasi tersebut, secara default. Jadi, bila layanan Anda +melakukan operasi yang intensif atau operasi pemblokiran saat pengguna berinteraksi dengan aktivitas dari +aplikasi yang sama, layanan akan memperlambat kinerja aktivitas. Agar tidak memengaruhi +kinerja aplikasi, Anda harus memulai thread baru di dalam layanan.</p> + +<p>Biasanya, ada dua kelas yang bisa Anda perluas untuk membuat layanan yang sudah dimulai:</p> +<dl> + <dt>{@link android.app.Service}</dt> + <dd>Ini adalah kelas dasar untuk semua layanan. Bila memperluas kelas ini, Anda perlu +membuat thread baru sebagai tempat melaksanakan semua pekerjaan layanan tersebut, karena layanan +menggunakan thread utama aplikasi Anda secara default, dan hal ini bisa memperlambat +kinerja aktivitas yang dijalankan aplikasi Anda.</dd> + <dt>{@link android.app.IntentService}</dt> + <dd>Ini adalah subkelas {@link android.app.Service} yang menggunakan thread pekerja untuk menangani +semua permintaan memulai, satu per satu. Ini adalah pilihan terbaik jika Anda tidak mengharuskan layanan +menangani beberapa permintaan sekaligus. Anda cukup mengimplementasikan {@link +android.app.IntentService#onHandleIntent onHandleIntent()}, yang menerima intent untuk setiap +permintaan memulai agar bisa melakukan pekerjaan latar belakang.</dd> +</dl> + +<p>Bagian selanjutnya membahas cara mengimplementasikan layanan Anda menggunakan +salah satu dari kelas-kelas ini.</p> + + +<h3 id="ExtendingIntentService">Memperluas kelas IntentService</h3> + +<p>Mengingat kebanyakan layanan yang sudah dimulai tidak perlu menangani beberapa permintaan +sekaligus (yang bisa berupa skenario multi-threading berbahaya), mungkin Anda sebaiknya mengimplementasikan +layanan menggunakan kelas {@link android.app.IntentService}.</p> + +<p>Berikut ini yang dilakukan {@link android.app.IntentService}:</p> + +<ul> + <li>Membuat thread pekerja default yang menjalankan semua intent yang disampaikan ke {@link +android.app.Service#onStartCommand onStartCommand()} terpisah dari thread utama aplikasi +Anda.</li> + <li>Membuat antrean pekerjaan yang meneruskan intent satu per satu ke implementasi {@link +android.app.IntentService#onHandleIntent onHandleIntent()}, sehingga Anda tidak perlu +mengkhawatirkan multi-threading.</li> + <li>Menghentikan layanan setelah semua permintaan memulai telah ditangani, jadi Anda tidak perlu memanggil +{@link android.app.Service#stopSelf}.</li> + <li>Menyediakan implementasi default {@link android.app.IntentService#onBind onBind()} yang +mengembalikan null.</li> + <li>Menyediakan implementasi default {@link android.app.IntentService#onStartCommand +onStartCommand()} yang mengirimkan intent ke antrean pekerjaan kemudian ke implementasi {@link +android.app.IntentService#onHandleIntent onHandleIntent()} Anda.</li> +</ul> + +<p>Oleh karena itu, Anda hanya perlu mengimplementasikan {@link +android.app.IntentService#onHandleIntent onHandleIntent()} untuk melakukan pekerjaan yang diberikan oleh +klien. (Akan tetapi, Anda juga perlu menyediakan konstruktor kecil bagi layanan.)</p> + +<p>Berikut ini contoh implementasi {@link android.app.IntentService}:</p> + +<pre> +public class HelloIntentService extends IntentService { + + /** + * A constructor is required, and must call the super {@link android.app.IntentService#IntentService} + * constructor with a name for the worker thread. + */ + public HelloIntentService() { + super("HelloIntentService"); + } + + /** + * The IntentService calls this method from the default worker thread with + * the intent that started the service. When this method returns, IntentService + * stops the service, as appropriate. + */ + @Override + protected void onHandleIntent(Intent intent) { + // Normally we would do some work here, like download a file. + // For our sample, we just sleep for 5 seconds. + long endTime = System.currentTimeMillis() + 5*1000; + while (System.currentTimeMillis() < endTime) { + synchronized (this) { + try { + wait(endTime - System.currentTimeMillis()); + } catch (Exception e) { + } + } + } + } +} +</pre> + +<p>Anda hanya memerlukan: konstruktor dan implementasi {@link +android.app.IntentService#onHandleIntent onHandleIntent()}.</p> + +<p>Jika Anda memutuskan untuk juga mengesampingkan metode callback lain, seperti {@link +android.app.IntentService#onCreate onCreate()}, {@link +android.app.IntentService#onStartCommand onStartCommand()}, atau {@link +android.app.IntentService#onDestroy onDestroy()}, pastikan memanggil implementasi super, sehingga +{@link android.app.IntentService} bisa menangani hidup thread pekerja dengan baik.</p> + +<p>Misalnya, {@link android.app.IntentService#onStartCommand onStartCommand()} harus mengembalikan +implementasi default (yang merupakan cara penyampaian intent ke {@link +android.app.IntentService#onHandleIntent onHandleIntent()}):</p> + +<pre> +@Override +public int onStartCommand(Intent intent, int flags, int startId) { + Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); + return super.onStartCommand(intent,flags,startId); +} +</pre> + +<p>Selain {@link android.app.IntentService#onHandleIntent onHandleIntent()}, satu-satunya metode lain +yang tidak mengharuskan Anda memanggil super kelas adalah {@link android.app.IntentService#onBind +onBind()} (namun Anda hanya perlu mengimplementasikannya bila layanan mengizinkan pengikatan).</p> + +<p>Dalam bagian berikutnya, Anda akan melihat bagaimana layanan serupa diimplementasikan saat +memperluas kelas {@link android.app.Service} basis, yang membutuhkan kode lebih banyak lagi, namun mungkin +cocok jika Anda perlu menangani beberapa permintaan memulai sekaligus.</p> + + +<h3 id="ExtendingService">Memperluas kelas Layanan</h3> + +<p>Seperti telah Anda lihat di bagian sebelumnya, menggunakan {@link android.app.IntentService} membuat +implementasi layanan yang sudah dimulai jadi sangat sederhana. Namun, bila Anda mengharuskan layanan untuk +melakukan multi-threading (sebagai ganti memproses permintaan memulai melalui antrean pekerjaan), maka Anda +bisa memperluas kelas {@link android.app.Service} untuk menangani masing-masing intent.</p> + +<p>Sebagai perbandingan, contoh kode berikut ini adalah implementasi kelas {@link +android.app.Service} yang melakukan pekerjaan yang persis sama dengan contoh di atas menggunakan {@link +android.app.IntentService}. Artinya, untuk setiap permintaan memulai, kode tersebut akan menggunakan thread pekerja +untuk melakukan pekerjaan dan memproses permintaan satu per satu.</p> + +<pre> +public class HelloService extends Service { + private Looper mServiceLooper; + private ServiceHandler mServiceHandler; + + // Handler that receives messages from the thread + private final class ServiceHandler extends Handler { + public ServiceHandler(Looper looper) { + super(looper); + } + @Override + public void handleMessage(Message msg) { + // Normally we would do some work here, like download a file. + // For our sample, we just sleep for 5 seconds. + long endTime = System.currentTimeMillis() + 5*1000; + while (System.currentTimeMillis() < endTime) { + synchronized (this) { + try { + wait(endTime - System.currentTimeMillis()); + } catch (Exception e) { + } + } + } + // Stop the service using the startId, so that we don't stop + // the service in the middle of handling another job + stopSelf(msg.arg1); + } + } + + @Override + public void onCreate() { + // Start up the thread running the service. Note that we create a + // separate thread because the service normally runs in the process's + // main thread, which we don't want to block. We also make it + // background priority so CPU-intensive work will not disrupt our UI. + HandlerThread thread = new HandlerThread("ServiceStartArguments", + Process.THREAD_PRIORITY_BACKGROUND); + thread.start(); + + // Get the HandlerThread's Looper and use it for our Handler + mServiceLooper = thread.getLooper(); + mServiceHandler = new ServiceHandler(mServiceLooper); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); + + // For each start request, send a message to start a job and deliver the + // start ID so we know which request we're stopping when we finish the job + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = startId; + mServiceHandler.sendMessage(msg); + + // If we get killed, after returning from here, restart + return START_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + // We don't provide binding, so return null + return null; + } + + @Override + public void onDestroy() { + Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); + } +} +</pre> + +<p>Seperti yang bisa Anda lihat, ini membutuhkan lebih banyak pekerjaan daripada menggunakan {@link android.app.IntentService}.</p> + +<p>Akan tetapi, karena Anda menangani sendiri setiap panggilan ke {@link android.app.Service#onStartCommand +onStartCommand()}, Anda bisa melakukan beberapa permintaan sekaligus. Itu bukan yang +dilakukan contoh ini, namun jika itu yang diinginkan, Anda bisa membuat thread baru untuk setiap +permintaan dan langsung menjalankannya (sebagai ganti menunggu permintaan sebelumnya selesai).</p> + +<p>Perhatikan bahwa metode {@link android.app.Service#onStartCommand onStartCommand()} harus mengembalikan +integer. Integer tersebut merupakan nilai yang menjelaskan cara sistem melanjutkan layanan dalam +kejadian yang dimatikan oleh sistem (sebagaimana dibahas di atas, implementasi default {@link +android.app.IntentService} menangani hal ini untuk Anda, walaupun Anda bisa memodifikasinya). Nilai yang dikembalikan +dari {@link android.app.Service#onStartCommand onStartCommand()} harus berupa salah satu +konstanta berikut ini:</p> + +<dl> + <dt>{@link android.app.Service#START_NOT_STICKY}</dt> + <dd>Jika sistem mematikan layanan setelah {@link android.app.Service#onStartCommand +onStartCommand()} dikembalikan, <em>jangan</em> membuat lagi layanan tersebut, kecuali jika ada intent +tertunda yang akan disampaikan. Inilah pilihan teraman untuk menghindari menjalankan layanan Anda +bila tidak diperlukan dan bila aplikasi Anda bisa me-restart pekerjaan yang belum selesai.</dd> + <dt>{@link android.app.Service#START_STICKY}</dt> + <dd>Jika sistem mematikan layanan setelah {@link android.app.Service#onStartCommand +onStartCommand()} dikembalikan, buat kembali layanan dan panggil {@link +android.app.Service#onStartCommand onStartCommand()}, namun <em>jangan</em> menyampaikan ulang intent terakhir. +Sebagai gantinya, sistem akan memanggil {@link android.app.Service#onStartCommand onStartCommand()} dengan +intent null, kecuali jika ada intent tertunda untuk memulai layanan, dan dalam hal ini, +intent tersebut disampaikan. Ini cocok bagi pemutar media (atau layanan serupa) yang tidak +mengeksekusi perintah, namun berjalan terus-menerus dan menunggu pekerjaan.</dd> + <dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt> + <dd>Jika sistem mematikan layanan setelah {@link android.app.Service#onStartCommand +onStartCommand()} kembali, buat kembali layanan dan panggil {@link +android.app.Service#onStartCommand onStartCommand()} dengan intent terakhir yang disampaikan ke +layanan. Intent yang tertunda akan disampaikan pada gilirannya. Ini cocok bagi layanan yang +aktif melakukan pekerjaan yang harus segera dilanjutkan, misalnya mengunduh file.</dd> +</dl> +<p>Untuk detail selengkapnya tentang nilai pengembalian ini, lihat dokumentasi acuan untuk setiap +konstanta.</p> + + + +<h3 id="StartingAService">Memulai Layanan</h3> + +<p>Anda bisa memulai layanan dari aktivitas atau komponen aplikasi lain dengan meneruskan +{@link android.content.Intent} (yang menetapkan layanan yang akan dimulai) ke {@link +android.content.Context#startService startService()}. Sistem Android akan memanggil metode {@link +android.app.Service#onStartCommand onStartCommand()} layanan dan meneruskan {@link +android.content.Intent} padanya. (Jangan sekali-kali memanggil {@link android.app.Service#onStartCommand +onStartCommand()} secara langsung.)</p> + +<p>Misalnya, aktivitas bisa memulai contoh layanan di bagian sebelumnya ({@code +HelloSevice}) menggunakan intent eksplisit dengan {@link android.content.Context#startService +startService()}:</p> + +<pre> +Intent intent = new Intent(this, HelloService.class); +startService(intent); +</pre> + +<p>Metode {@link android.content.Context#startService startService()} segera kembali dan +sistem Android akan memanggil metode {@link android.app.Service#onStartCommand +onStartCommand()} layanan. Jika layanan belum berjalan, sistem mula-mula memanggil {@link +android.app.Service#onCreate onCreate()}, kemudian memanggil {@link android.app.Service#onStartCommand +onStartCommand()}.</p> + +<p>Jika layanan juga tidak menyediakan pengikatan, intent yang disampaikan dengan {@link +android.content.Context#startService startService()} adalah satu-satunya mode komunikasi antara +komponen aplikasi dan layanan. Akan tetapi, jika Anda ingin agar layanan mengirimkan hasilnya kembali, maka +klien yang memulai layanan bisa membuat {@link android.app.PendingIntent} untuk siaran +(dengan {@link android.app.PendingIntent#getBroadcast getBroadcast()}) dan menyampaikannya ke layanan +dalam {@link android.content.Intent} yang memulai layanan. Layanan kemudian bisa menggunakan +siaran untuk menyampaikan hasil.</p> + +<p>Beberapa permintaan untuk memulai layanan menghasilkan beberapa panggilan pula ke +{@link android.app.Service#onStartCommand onStartCommand()} layanan. Akan tetapi, hanya satu permintaan untuk menghentikan +layanan (dengan {@link android.app.Service#stopSelf stopSelf()} atau {@link +android.content.Context#stopService stopService()}) dibutuhkan untuk menghentikannya.</p> + + +<h3 id="Stopping">Menghentikan layanan</h3> + +<p>Layanan yang sudah dimulai harus mengelola daur hidupnya sendiri. Artinya, sistem tidak menghentikan atau +memusnahkan layanan kecuali jika harus memulihkan memori sistem dan layanan +terus berjalan setelah {@link android.app.Service#onStartCommand onStartCommand()} kembali. Jadi, +layanan tersebut harus berhenti sendiri dengan memanggil {@link android.app.Service#stopSelf stopSelf()} atau +komponen lain bisa menghentikannya dengan memanggil {@link android.content.Context#stopService stopService()}.</p> + +<p>Setelah diminta untuk berhenti dengan {@link android.app.Service#stopSelf stopSelf()} atau {@link +android.content.Context#stopService stopService()}, sistem akan menghapus layanan +secepatnya.</p> + +<p>Akan tetapi, bila layanan Anda menangani beberapa permintaan ke {@link +android.app.Service#onStartCommand onStartCommand()} sekaligus, Anda tidak boleh menghentikan +layanan bila Anda baru selesai memproses permintaan memulai, karena setelah itu mungkin Anda sudah menerima permintaan memulai +yang baru (berhenti pada permintaan pertama akan menghentikan permintaan kedua). Untuk menghindari +masalah ini, Anda bisa menggunakan {@link android.app.Service#stopSelf(int)} untuk memastikan bahwa permintaan +Anda untuk menghentikan layanan selalu berdasarkan pada permintaan memulai terbaru. Artinya, bila Anda memanggil {@link +android.app.Service#stopSelf(int)}, Anda akan meneruskan ID permintaan memulai (<code>startId</code> +yang disampaikan ke {@link android.app.Service#onStartCommand onStartCommand()}) yang terkait dengan permintaan berhenti +Anda. Kemudian jika layanan menerima permintaan memulai baru sebelum Anda bisa memanggil {@link +android.app.Service#stopSelf(int)}, maka ID tidak akan sesuai dan layanan tidak akan berhenti.</p> + +<p class="caution"><strong>Perhatian:</strong> Aplikasi Anda perlu menghentikan layanannya +bila selesai bekerja untuk menghindari pemborosan sumber daya sistem dan tenaga baterai. Jika perlu, +komponen lain bisa menghentikan layanan secara eksplisit dengan memanggil {@link +android.content.Context#stopService stopService()}. Bahkan jika Anda mengaktifkan pengikatan bagi layanan, +Anda harus selalu menghentikan layanan sendiri jika layanan tersebut menerima panggilan ke {@link +android.app.Service#onStartCommand onStartCommand()}.</p> + +<p>Untuk informasi selengkapnya tentang daur hidup layanan, lihat bagian di bawah ini tentang <a href="#Lifecycle">Mengelola Daur Hidup Layanan</a>.</p> + + + +<h2 id="CreatingBoundService">Membuat Layanan Terikat</h2> + +<p>Layanan terikat adalah layanan yang memungkinkan komponen aplikasi untuk mengikatnya dengan memanggil {@link +android.content.Context#bindService bindService()} guna membuat koneksi yang berlangsung lama +(dan umumnya tidak mengizinkan komponen untuk <em>memulainya</em> dengan memanggil {@link +android.content.Context#startService startService()}).</p> + +<p>Anda sebaiknya membuat layanan terikat bila ingin berinteraksi dengan layanan dari aktivitas +dan komponen lain dalam aplikasi Anda atau mengeskpos sebagian fungsionalitas aplikasi Anda ke +ke aplikasi lain, melalui komunikasi antarproses (IPC).</p> + +<p>Untuk membuat layanan terikat, Anda harus mengimplementasikan metode callback {@link +android.app.Service#onBind onBind()} untuk mengembalikan {@link android.os.IBinder} yang +mendefinisikan antarmuka bagi komunikasi dengan layanan. Komponen aplikasi lain kemudian bisa memanggil +{@link android.content.Context#bindService bindService()} untuk mengambil antarmuka dan +mulai memanggil metode pada layanan. Layanan hanya hidup untuk melayani komponen aplikasi yang +terikat padanya, jadi bila tidak ada komponen yang terikat pada layanan, sistem akan memusnahkannya +(Anda <em>tidak</em> perlu menghentikan layanan terikat seperti halnya bila layanan dimulai +melalui {@link android.app.Service#onStartCommand onStartCommand()}).</p> + +<p>Untuk membuat layanan terikat, hal yang perlu dilakukan pertama kali adalah mendefinisikan antarmuka yang menetapkan +cara klien berkomunikasi dengan layanan. Antarmuka antara layanan +dan klien ini harus berupa implementasi {@link android.os.IBinder} dan yang harus dikembalikan +layanan Anda dari metode callback {@link android.app.Service#onBind +onBind()}. Setelah menerima {@link android.os.IBinder}, klien bisa mulai +berinteraksi dengan layanan melalui antarmuka tersebut.</p> + +<p>Beberapa klien bisa mengikat ke layanan sekaligus. Bila klien selesai berinteraksi dengan +layanan, klien akan memanggil {@link android.content.Context#unbindService unbindService()} untuk melepas ikatan. Bila +tidak ada klien yang terikat pada layanan, sistem akan menghapus layanan tersebut.</p> + +<p>Ada beberapa cara untuk mengimplementasikan layanan terikat dan implementasinya lebih +rumit daripada layanan yang sudah dimulai, jadi layanan terikat dibahas dalam dokumen +terpisah tentang <a href="{@docRoot}guide/components/bound-services.html">Layanan Terikat</a>.</p> + + + +<h2 id="Notifications">Mengirim Pemberitahuan ke Pengguna</h2> + +<p>Setelah berjalan, layanan bisa memberi tahu pengguna tentang suatu kejadian menggunakan <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Pemberitahuan Toast</a> atau <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan Baris Status</a>.</p> + +<p>Pemberitahuan Toast adalah pesan yang muncul sebentar pada permukaan jendela saat ini +kemudian menghilang, sementara pemberitahuan baris status memberikan ikon di baris status dengan +pesan yang bisa dipilih oleh pengguna untuk melakukan suatu tindakan (misalnya memulai suatu aktivitas).</p> + +<p>Biasanya, pemberitahuan baris status adalah teknik terbaik bila ada pekerjaan latar belakang yang sudah selesai +(misalnya file selesai +diunduh) dan pengguna kini bisa menggunakannya. Bila pengguna memilih pemberitahuan dari +tampilan diperluas, pemberitahuan akan bisa memulai aktivitas (misalnya menampilkan file yang baru diunduh).</p> + +<p>Lihat panduan pengembang <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Pemberitahuan Toast</a> atau <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan Baris Status</a> +untuk informasi selengkapnya.</p> + + + +<h2 id="Foreground">Menjalankan Layanan di Latar Depan</h2> + +<p>Layanan latar depan adalah layanan yang dianggap sebagai sesuatu yang +diketahui secara aktif oleh pengguna, jadi bukan sesuatu yang akan dihapus oleh sistem bila memori menipis. Sebuah +layanan latar depan harus memberikan pemberitahuan bagi baris status, yang ditempatkan pada +heading "Ongoing" yang artinya pemberitahuan tersebut tidak bisa diabaikan kecuali jika layanan +dihentikan atau dihapus dari latar depan.</p> + +<p>Misalnya, pemutar musik yang memutar musik dari suatu layanan harus diatur untuk berjalan di +latar depan, karena pengguna mengetahui operasi tersebut +secara eksplisit. Pemberitahuan di baris status bisa menunjukkan lagu saat ini dan memungkinkan +pengguna untuk menjalankan suatu aktivitas untuk berinteraksi dengan pemutar musik.</p> + +<p>Untuk meminta agar layanan Anda berjalan di latar depan, panggil {@link +android.app.Service#startForeground startForeground()}. Metode ini memerlukan dua parameter: sebuah integer +yang mengidentifikasi pemberitahuan secara unik dan {@link +android.app.Notification} untuk baris status. Misalnya:</p> + +<pre> +Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), + System.currentTimeMillis()); +Intent notificationIntent = new Intent(this, ExampleActivity.class); +PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); +notification.setLatestEventInfo(this, getText(R.string.notification_title), + getText(R.string.notification_message), pendingIntent); +startForeground(ONGOING_NOTIFICATION_ID, notification); +</pre> + +<p class="caution"><strong>Perhatian:</strong> ID integer yang Anda berikan ke {@link +android.app.Service#startForeground startForeground()} tidak boleh 0.</p> + + +<p>Untuk menghapus layanan dari latar depan, panggil {@link +android.app.Service#stopForeground stopForeground()}. Metode ini memerlukan boolean, yang menunjukkan +apakah pemberitahuan baris status juga akan dihapus. Metode ini <em>tidak</em> menghentikan +layanan. Akan tetapi, jika Anda menghentikan layanan saat masih berjalan di latar depan +maka pemberitahuan juga akan dihapus.</p> + +<p>Untuk informasi selengkapnya tentang pemberitahuan, lihat <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Membuat Pemberitahuan +Baris Status</a>.</p> + + + +<h2 id="Lifecycle">Mengelola Daur Hidup Layanan</h2> + +<p>Daur hidup layanan jauh lebih sederhana daripada daur hidup aktivitas. Akan tetapi, lebih penting lagi adalah +memerhatikan dengan cermat bagaimana layanan Anda dibuat dan dimusnahkan, karena suatu layanan +bisa berjalan di latar belakang tanpa disadari oleh pengguna.</p> + +<p>Daur hidup layanan—dari saat dibuat hingga dimusnahkan—bisa mengikuti +dua path berbeda:</p> + +<ul> +<li>Layanan yang sudah dimulai + <p>Layanan dibuat bila komponen lain memanggil {@link +android.content.Context#startService startService()}. Layanan kemudian berjalan terus-menerus dan harus +berhenti sendiri dengan memanggil {@link +android.app.Service#stopSelf() stopSelf()}. Komponen lain juga bisa menghentikan +layanan dengan memanggil {@link android.content.Context#stopService +stopService()}. Bila layanan dihentikan, sistem akan menghancurkannya.</p></li> + +<li>Layanan terikat + <p>Layanan dibuat bila komponen lain (klien) memanggil {@link +android.content.Context#bindService bindService()}. Klien kemudian berkomunikasi dengan layanan +melalui antarmuka {@link android.os.IBinder}. Klien bisa menutup koneksi dengan memanggil +{@link android.content.Context#unbindService unbindService()}. Sejumlah klien bisa mengikat pada +layanan yang sama dan bila semuanya melepas ikatan, sistem akan memusnahkan layanan tersebut. (Layanan +<em>tidak</em> perlu berhenti sendiri.)</p></li> +</ul> + +<p>Kedua path tersebut tidak benar-benar terpisah. Artinya, Anda bisa mengikat ke layanan yang sudah +dimulai dengan {@link android.content.Context#startService startService()}. Misalnya, layanan +musik latar belakang bisa dimulai dengan memanggil {@link android.content.Context#startService +startService()} dengan {@link android.content.Intent} yang mengidentifikasi musik yang akan diputar. Kemudian, +mungkin saat pengguna ingin mengontrol pemutar musik atau mendapatkan informasi +tentang lagu yang diputar, aktivitas bisa mengikat ke layanan dengan memanggil {@link +android.content.Context#bindService bindService()}. Dalam kasus seperti ini, {@link +android.content.Context#stopService stopService()} atau {@link android.app.Service#stopSelf +stopSelf()} tidak menghentikan layanan sampai semua klien melepas ikatan. </p> + + +<h3 id="LifecycleCallbacks">Mengimplementasikan callback daur hidup</h3> + +<p>Seperti halnya aktivitas, layanan memiliki metode callback daur hidup yang bisa Anda implementasikan +untuk memantau perubahan status layanan dan melakukan pekerjaan pada waktu yang tepat. Layanan skeleton +berikut memperagakan setiap metode daur hidup:</p> + +<pre> +public class ExampleService extends Service { + int mStartMode; // indicates how to behave if the service is killed + IBinder mBinder; // interface for clients that bind + boolean mAllowRebind; // indicates whether onRebind should be used + + @Override + public void {@link android.app.Service#onCreate onCreate}() { + // The service is being created + } + @Override + public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) { + // The service is starting, due to a call to {@link android.content.Context#startService startService()} + return <em>mStartMode</em>; + } + @Override + public IBinder {@link android.app.Service#onBind onBind}(Intent intent) { + // A client is binding to the service with {@link android.content.Context#bindService bindService()} + return <em>mBinder</em>; + } + @Override + public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) { + // All clients have unbound with {@link android.content.Context#unbindService unbindService()} + return <em>mAllowRebind</em>; + } + @Override + public void {@link android.app.Service#onRebind onRebind}(Intent intent) { + // A client is binding to the service with {@link android.content.Context#bindService bindService()}, + // after onUnbind() has already been called + } + @Override + public void {@link android.app.Service#onDestroy onDestroy}() { + // The service is no longer used and is being destroyed + } +} +</pre> + +<p class="note"><strong>Catatan:</strong> Tidak seperti metode callback daur hidup aktivitas, Anda +<em>tidak</em> perlu memanggil implementasi superkelas metode callback tersebut.</p> + +<img src="{@docRoot}images/service_lifecycle.png" alt="" /> +<p class="img-caption"><strong>Gambar 2.</strong> Daur hidup layanan. Diagram di sebelah kiri +menampilkan daur hidup bila layanan dibuat dengan {@link android.content.Context#startService +startService()} dan diagram di sebelah kanan menampilkan daur hidup bila layanan dibuat +dengan {@link android.content.Context#bindService bindService()}.</p> + +<p>Dengan mengimplementasikan metode-metode ini, Anda bisa memantau dua loop tersarang (nested loop) daur hidup layanan: </p> + +<ul> +<li><strong>Seluruh masa pakai</strong> layanan terjadi antara saat {@link +android.app.Service#onCreate onCreate()} dipanggil dan saat {@link +android.app.Service#onDestroy} kembali. Seperti halnya aktivitas, layanan melakukan penyiapan awal di +{@link android.app.Service#onCreate onCreate()} dan melepaskan semua sisa sumber daya yang ada di {@link +android.app.Service#onDestroy onDestroy()}. Misalnya, +layanan pemutar musik bisa membuat thread tempat musik akan diputar dalam {@link +android.app.Service#onCreate onCreate()}, kemudian menghentikan thread tersebut dalam {@link +android.app.Service#onDestroy onDestroy()}. + +<p>Metode {@link android.app.Service#onCreate onCreate()} dan {@link android.app.Service#onDestroy +onDestroy()} diperlukan semua layanan, baik yang +dibuat oleh {@link android.content.Context#startService startService()} maupun {@link +android.content.Context#bindService bindService()}.</p></li> + +<li><strong>Masa pakai aktif</strong> layanan dimulai dengan panggilan ke {@link +android.app.Service#onStartCommand onStartCommand()} atau {@link android.app.Service#onBind onBind()}. +Masing-masing metode diberikan {@link +android.content.Intent} yang diteruskan ke {@link android.content.Context#startService +startService()} atau {@link android.content.Context#bindService bindService()}. +<p>Jika layanan telah dimulai, masa pakai aktif akan berakhir pada saat yang sama dengan +berakhirnya seluruh masa pakai (layanan masih aktif bahkan setelah {@link android.app.Service#onStartCommand +onStartCommand()} kembali). Jika layanan tersebut terikat, masa pakai aktifnya akan berakhir bila {@link +android.app.Service#onUnbind onUnbind()} kembali.</p> +</li> +</ul> + +<p class="note"><strong>Catatan:</strong> Meskipun layanan yang sudah dimulai dihentikan dengan panggilan ke +{@link android.app.Service#stopSelf stopSelf()} atau {@link +android.content.Context#stopService stopService()}, tidak ada callback tersendiri bagi +layanan tersebut (tidak ada callback {@code onStop()}). Jadi, kecuali jika layanan terikat ke klien, +sistem akan memusnahkannya bila layanan dihentikan—{@link +android.app.Service#onDestroy onDestroy()} adalah satu-satunya callback yang diterima.</p> + +<p>Gambar 2 mengilustrasikan metode callback yang lazim bagi suatu layanan. Walaupun gambar tersebut memisahkan +layanan yang dibuat oleh {@link android.content.Context#startService startService()} dari layanan +yang dibuat oleh {@link android.content.Context#bindService bindService()}, ingatlah +bahwa suatu layanan, bagaimana pun dimulainya, bisa memungkinkan klien mengikat padanya. +Jadi, suatu layanan yang awalnya dimulai dengan {@link android.app.Service#onStartCommand +onStartCommand()} (oleh klien yang memanggil {@link android.content.Context#startService startService()}) +masih bisa menerima panggilan ke {@link android.app.Service#onBind onBind()} (bila klien memanggil +{@link android.content.Context#bindService bindService()}).</p> + +<p>Untuk informasi selengkapnya tentang membuat layanan yang menyediakan pengikatan, lihat dokumen <a href="{@docRoot}guide/components/bound-services.html">Layanan Terikat</a>, +yang menyertakan informasi selengkapnya tentang metode callback {@link android.app.Service#onRebind onRebind()} +di bagian tentang <a href="{@docRoot}guide/components/bound-services.html#Lifecycle">Mengelola Daur Hidup +Layanan Terikat</a>.</p> + + +<!-- +<h2>Beginner's Path</h2> + +<p>To learn how to query data from the system or other applications (such as contacts or media +stored on the device), continue with the <b><a +href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b> +document.</p> +--> diff --git a/docs/html-intl/intl/id/guide/components/tasks-and-back-stack.jd b/docs/html-intl/intl/id/guide/components/tasks-and-back-stack.jd new file mode 100644 index 000000000000..4c344ae126ae --- /dev/null +++ b/docs/html-intl/intl/id/guide/components/tasks-and-back-stack.jd @@ -0,0 +1,578 @@ +page.title=Tugas dan Back-Stack +parent.title=Aktivitas +parent.link=activities.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + +<h2>Dalam dokumen ini</h2> +<ol> +<li><a href="#ActivityState">Menyimpan Status Aktivitas</a></li></li> +<li><a href="#ManagingTasks">Mengelola Tugas</a> + <ol> + <li><a href="#TaskLaunchModes">Mendefinisikan mode peluncuran</a></li> + <li><a href="#Affinities">Menangani afinitas</a></li> + <li><a href="#Clearing">Menghapus back-stack</a></li> + <li><a href="#Starting">Memulai tugas</a></li> + </ol> +</li> +</ol> + +<h2>Artikel</h2> +<ol> + <li><a href="http://android-developers.blogspot.com/2010/04/multitasking-android-way.html"> + Multitasking Ala Android</a></li> +</ol> + +<h2>Lihat juga</h2> +<ol> + <li><a href="{@docRoot}design/patterns/navigation.html">Desain Android: +Navigasi</a></li> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html">Elemen manifes +{@code <activity>}</a></li> + <li><a href="{@docRoot}guide/components/recents.html">Layar Ikhtisar</a></li> +</ol> +</div> +</div> + + +<p>Sebuah aplikasi biasanya berisi beberapa <a href="{@docRoot}guide/components/activities.html">aktivitas</a>. Setiap aktivitas +harus didesain dengan jenis tindakan tertentu yang bisa dilakukan pengguna dan bisa memulai aktivitas +lain. Misalnya, aplikasi email mungkin memiliki satu aktivitas untuk menampilkan daftar pesan baru. +Bila pengguna memilih sebuah pesan, aktivitas baru akan terbuka untuk melihat pesan tersebut.</p> + +<p>Aktivitas bahkan bisa memulai aktivitas yang ada dalam aplikasi lain di perangkat. Misalnya +, jika aplikasi Anda ingin mengirim pesan email, Anda bisa mendefinisikan intent untuk melakukan tindakan +"kirim" dan menyertakan sejumlah data, seperti alamat email dan pesan. Aktivitas dari aplikasi +lain yang mendeklarasikan dirinya untuk menangani jenis intent ini akan terbuka. Dalam hal ini, intent +tersebut untuk mengirim email, sehingga aktivitas "menulis" pada aplikasi email akan dimulai (jika beberapa aktivitas +mendukung intent yang sama, maka sistem akan memungkinkan pengguna memilih mana yang akan digunakan). Bila email telah +dikirim, aktivitas Anda akan dilanjutkan dan seolah-olah aktivitas email adalah bagian dari aplikasi Anda. Meskipun +aktivitas mungkin dari aplikasi yang berbeda, Android akan tetap mempertahankan pengalaman pengguna yang mulus +dengan menjalankan kedua aktivitas dalam <em>tugas</em> yang sama.</p> + +<p>Tugas adalah kumpulan aktivitas yang berinteraksi dengan pengguna +saat melakukan pekerjaan tertentu. Aktivitas tersebut diatur dalam tumpukan (<em>back-stack</em>), dalam +urutan membuka setiap aktivitas.</p> + +<!-- SAVE FOR WHEN THE FRAGMENT DOC IS ADDED +<div class="sidebox-wrapper"> +<div class="sidebox"> +<h3>Adding fragments to a task's back stack</h3> + +<p>Your activity can also include {@link android.app.Fragment}s to the back stack. For example, +suppose you have a two-pane layout using fragments, one of which is a list view (fragment A) and the +other being a layout to display an item from the list (fragment B). When the user selects an item +from the list, fragment B is replaced by a new fragment (fragment C). In this case, it might be +desireable for the user to navigate back to reveal fragment B, using the <em>Back</em> button.</p> +<p>In order to add fragment B to the back stack so that this is possible, you must call {@link +android.app.FragmentTransaction#addToBackStack addToBackStack()} before you {@link +android.app.FragmentTransaction#commit()} the transaction that replaces fragment B with fragment +C.</p> +<p>For more information about using fragments and adding them to the back stack, see the {@link +android.app.Fragment} class documentation.</p> + +</div> +</div> +--> + +<p>Layar Home perangkat adalah tempat memulai hampir semua tugas. Bila pengguna menyentuh ikon di launcher +aplikasi +(atau pintasan pada layar Home), tugas aplikasi tersebut akan muncul pada latar depan. Jika tidak ada +tugas untuk aplikasi (aplikasi tidak digunakan baru-baru ini), maka tugas baru +akan dibuat dan aktivitas "utama" untuk aplikasi tersebut akan terbuka sebagai aktivitas akar dalam back-stack.</p> + +<p>Bila aktivitas saat ini dimulai lagi, aktivitas baru akan didorong ke atas back-stack dan +mengambil fokus. Aktivitas sebelumnya tetap dalam back-stack, namun dihentikan. Bila aktivitas +dihentikan, sistem akan mempertahankan status antarmuka penggunanya saat ini. Bila pengguna menekan tombol +<em>Back</em> +, aktivitas saat ini akan dikeluarkan dari atas back-stack (aktivitas dimusnahkan) dan + aktivitas sebelumnya dilanjutkan (status UI sebelumnya dipulihkan). Aktivitas dalam back-stack +tidak pernah disusun ulang, hanya didorong dan dikeluarkan dari back-stack—yang didorong ke back-stack saat dimulai oleh +aktivitas saat ini dan dikeluarkan bila pengguna meninggalkannya menggunakan tombol <em>Back</em>. Dengan demikian, +back-stack +beroperasi sebagai struktur objek "masuk terakhir, keluar pertama". Gambar 1 melukiskan perilaku +ini dengan jangka waktu yang menunjukkan kemajuan antar aktivitas beserta +back-stack pada setiap waktu.</p> + +<img src="{@docRoot}images/fundamentals/diagram_backstack.png" alt="" /> +<p class="img-caption"><strong>Gambar 1.</strong> Representasi tentang cara setiap aktivitas baru dalam +tugas menambahkan item ke back-stack. Bila pengguna menekan tombol <em>Back</em>, aktivitas +saat ini +akan dimusnahkan dan aktivitas sebelumnya dilanjutkan.</p> + + +<p>Jika pengguna terus menekan <em>Back</em>, maka setiap aktivitas dalam back-stack akan dikeluarkan untuk +menampilkan +yang sebelumnya, sampai pengguna kembali ke layar Home (atau aktivitas mana pun yang sedang dijalankan saat tugas +dimulai. Bila semua aktivitas telah dihapus dari back-stack, maka tugas tidak akan ada lagi.</p> + +<div class="figure" style="width:287px"> +<img src="{@docRoot}images/fundamentals/diagram_multitasking.png" alt="" /> <p +class="img-caption"><strong>Gambar 2.</strong> Dua tugas: Tugas B menerima interaksi pengguna +di latar depan, sedangkan Tugas A di latar belakang, menunggu untuk dilanjutkan.</p> +</div> +<div class="figure" style="width:215px"> + <img src="{@docRoot}images/fundamentals/diagram_multiple_instances.png" alt="" /> <p +class="img-caption"><strong>Gambar 3.</strong> Satu aktivitas dibuat instance-nya beberapa kali.</p> +</div> + +<p>Tugas adalah unit kohesif yang bisa dipindahkan ke "latar belakang" bila pengguna memulai tugas baru atau masuk ke +layar Home, melalui tombol<em>Home</em>. Sementara di latar belakang, semua aktivitas dalam +tugas +dihentikan, namun back-stack untuk tugas tidak berubah—tugas kehilangan fokus saat +tugas lain berlangsung, seperti yang ditampilkan dalam gambar 2. Kemudian, tugas bisa kembali ke "latar depan" agar pengguna +bisa melanjutkan tugas di tempat menghentikannya. Anggaplah, misalnya, tugas saat ini (Tugas A) memiliki tiga +aktivitas dalam back-stack—dua pada aktivitas saat ini. Pengguna menekan tombol <em>Home</em> +, kemudian +memulai aplikasi baru dari launcher aplikasi. Bila muncul layar Home, Tugas A akan beralih +ke latar belakang. Bila aplikasi baru dimulai, sistem akan memulai tugas untuk aplikasi tersebut +(Tugas B) dengan back-stack aktivitas sendiri. Setelah berinteraksi dengan aplikasi +tersebut, pengguna akan kembali ke Home lagi dan memilih aplikasi yang semula +memulai Tugas A. Sekarang, Tugas A muncul di +latar depan—ketiga aktivitas dalam back-stack tidak berubah dan aktivitas di atas +back-stack akan dilanjutkan. Pada +titik ini pengguna juga bisa beralih kembali ke Tugas B dengan masuk ke Home dan memilih ikon aplikasi +yang memulai tugas tersebut (atau dengan memilih tugas aplikasi dari +<a href="{@docRoot}guide/components/recents.html">layar ikhtisar</a>). +Ini adalah contoh dari melakukan multitasking di Android.</p> + +<p class="note"><strong>Catatan:</strong> Beberapa tugas bisa berlangsung di latar belakang secara bersamaan. +Akan tetapi, jika pengguna menjalankan banyak tugas di latar belakang sekaligus, sistem mungkin mulai +menghapus aktivitas latar belakang untuk memulihkan memori, yang akan menyebabkan status aktivitas hilang. +Lihat bagian berikut tentang <a href="#ActivityState">Status aktivitas</a>.</p> + +<p>Karena aktivitas di back-stack tidak pernah diatur ulang, jika aplikasi Anda memungkinkan +pengguna untuk memulai aktivitas tertentu dari lebih dari satu aktivitas, instance baru +aktivitas tersebut akan dibuat dan didorong ke back-stack (bukannya memunculkan instance sebelumnya dari +aktivitas ke atas). Dengan demikian, satu aktivitas pada aplikasi Anda mungkin dibuat beberapa +kali (bahkan dari beberapa tugas), seperti yang ditampilkan dalam gambar 3. Dengan demikian, jika pengguna mengarahkan mundur +menggunakan tombol <em>Back</em>, setiap instance aktivitas ini akan ditampilkan dalam urutan saat +dibuka (masing-masing +dengan status UI sendiri). Akan tetapi, Anda bisa memodifikasi perilaku ini jika tidak ingin aktivitas +dibuat instance-nya lebih dari sekali. Caranya dibahas di bagian selanjutnya tentang <a href="#ManagingTasks">Mengelola Tugas</a>.</p> + + +<p>Untuk meringkas perilaku default aktivitas dan tugas:</p> + +<ul> + <li>Bila Aktivitas A memulai Aktivitas B, Aktivitas A dihentikan, namun sistem mempertahankan statusnya +(seperti posisi gulir dan teks yang dimasukkan ke dalam formulir). +Jika pengguna menekan tombol <em>Back</em> saat dalam Aktivitas B, Aktivitas A akan dilanjutkan dengan status +yang dipulihkan.</li> + <li>Bila pengguna meninggalkan tugas dengan menekan tombol <em>Home</em> aktivitas saat ini akan +dihentikan dan +tugas beralih ke latar belakang. Sistem akan mempertahankan status setiap aktivitas dalam tugas. Jika +nanti pengguna melanjutkan tugas dengan memilih ikon launcher yang memulai tugas, tugas tersebut akan +beralih ke latar depan dan melanjutkan aktivitas di atas back-stack.</li> + <li>Jika pengguna menekan tombol <em>Back</em>, aktivitas saat ini akan dikeluarkan dari back-stack +dan +dimusnahkan. Aktivitas sebelumnya dalam back-stack akan dilanjutkan. Bila suatu aktivitas dimusnahkan, sistem +<em>tidak akan</em>mempertahankan status aktivitas.</li> + <li>Aktivitas bisa dibuat instance-nya beberapa kali, bahkan dari tugas-tugas lainnya.</li> +</ul> + + +<div class="note design"> +<p><strong>Desain Navigasi</strong></p> + <p>Untuk mengetahui selengkapnya tentang cara kerja navigasi aplikasi di Android, baca panduan <a href="{@docRoot}design/patterns/navigation.html">Navigasi</a> Desain Android.</p> +</div> + + +<h2 id="ActivityState">Menyimpan Status Aktivitas</h2> + +<p>Seperti dibahas di atas, perilaku default sistem akan mempertahankan status aktivitas bila +dihentikan. Dengan cara ini, bila pengguna mengarah kembali ke aktivitas sebelumnya, antarmuka pengguna akan muncul +seperti saat ditinggalkan. Akan tetapi, Anda bisa—dan <strong>harus</strong>—secara proaktif mempertahankan +status aktivitas menggunakan metode callback, jika aktivitas ini dimusnahkan dan harus +dibuat kembali.</p> + +<p>Bila sistem menghentikan salah satu aktivitas (seperti saat aktivitas baru dimulai atau tugas +dipindah ke latar belakang), sistem mungkin memusnahkan aktivitas sepenuhnya jika perlu memulihkan +memori sistem. Bila hal ini terjadi, informasi tentang status aktivitas akan hilang. Jika hal ini terjadi, sistem +masih +mengetahui bahwa aktivitas memiliki tempat di back-stack, namun saat aktivitas tersebut dibawa ke bagian teratas +back-stack, sistem harus membuatnya kembali (bukan melanjutkannya). Untuk +menghindari hilangnya pekerjaan pengguna, Anda harus secara proaktif mempertahankannya dengan menerapkan metode callback +{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()} +dalam aktivitas.</p> + +<p>Untuk informasi selengkapnya tentang cara menyimpan status aktivitas Anda, lihat dokumen +<a href="{@docRoot}guide/components/activities.html#SavingActivityState">Aktivitas</a>.</p> + + + +<h2 id="ManagingTasks">Mengelola Tugas</h2> + +<p>Cara Android mengelola tugas dan back-stack, seperti yang dijelaskan di atas—dengan menempatkan semua +aktivitas yang dimulai secara berurutan dalam tugas yang sama dan dalam back-stack "masuk terakhir, keluar pertama"—berfungsi +dengan baik untuk kebanyakan aplikasi dan Anda tidak perlu khawatir tentang cara mengaitkan aktivitas +dengan tugas atau cara penempatannya di back-stack. Akan tetapi, Anda bisa memutuskan apakah ingin menyela +perilaku normal. Mungkin Anda ingin agar suatu aktivitas dalam aplikasi untuk memulai tugas baru bila telah +dimulai (sebagai ganti menempatkannya dalam tugas saat ini); atau, bila memulai aktivitas, Anda ingin +memajukan instance yang ada (sebagai ganti membuat instance +baru pada bagian teratas back-stack); atau, Anda ingin back-stack dihapus dari semua +aktivitas selain untuk aktivitas akar bila pengguna meninggalkan tugas.</p> + +<p>Anda bisa melakukan semua ini dan lainnya, dengan atribut dalam elemen manifes +<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> +dan dengan flag pada intent yang Anda teruskan ke +{@link android.app.Activity#startActivity startActivity()}.</p> + +<p>Dalam hal ini, atribut<a href="{@docRoot}guide/topics/manifest/activity-element.html"> +{@code <activity>}</a> utama yang bisa Anda gunakan adalah:</p> + +<ul class="nolist"> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff"> + {@code taskAffinity}</a></li> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode"> + {@code launchMode}</a></li> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent"> + {@code allowTaskReparenting}</a></li> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#clear"> + {@code clearTaskOnLaunch}</a></li> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#always"> + {@code alwaysRetainTaskState}</a></li> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#finish"> + {@code finishOnTaskLaunch}</a></li> +</ul> + +<p>Dan flag intent utama yang bisa Anda gunakan adalah:</p> + +<ul class="nolist"> + <li>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</li> + <li>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</li> + <li>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</li> +</ul> + +<p>Dalam bagian berikut, Anda akan melihat cara menggunakan beberapa atribut manifes ini dan flag +intent untuk mendefinisikan cara mengaitkan aktivitas dengan tugas dan cara perilakunya di back-stack.</p> + +<p>Juga, pertimbangan cara menyatakan dan mengelola tugas dan aktivitas +dibahas secara terpisah di layar ikhtisar. Lihat <a href="{@docRoot}guide/components/recents.html">Layar Ikhtisar</a> +untuk informasi selengkapnya. Biasanya Anda harus mengizinkan sistem mendefinisikan cara menyatakan tugas dan +aktivitas di layar ikhtisar, dan Anda tidak perlu memodifikasi perilaku ini.</p> + +<p class="caution"><strong>Perhatian:</strong> Kebanyakan aplikasi tidak harus menyela perilaku +default untuk aktivitas dan tugas. Jika merasa bahwa aktivitas Anda perlu memodifikasi +perilaku default, lakukan dengan hati-hati dan pastikan menguji kegunaan aktivitas selama +dijalankan dan saat mengarahkan kembali ke sana dari aktivitas dan tugas lain dengan tombol <em>Back</em>. +Pastikan menguji perilaku navigasi yang mungkin bertentangan dengan perilaku yang diharapkan pengguna.</p> + + +<h3 id="TaskLaunchModes">Mendefinisikan mode peluncuran</h3> + +<p>Mode peluncuran memungkinkan Anda mendefinisikan cara mengaitkan instance baru dari suatu aktivitas dengan +tugas saat ini. Anda bisa mendefinisikan beragam mode peluncuran dalam dua cara:</p> +<ul class="nolist"> + <li><a href="#ManifestForTasks">Menggunakan file manifes</a> + <p>Bila Anda mendeklarasikan aktivitas dalam file manifes, Anda bisa menetapkan cara mengaitkan aktivitas +dengan tugas-tugas saat mulai.</li> + <li><a href="#IntentFlagsForTasks">Menggunakan flag intent</a> + <p>Saat memanggil{@link android.app.Activity#startActivity startActivity()}, +Anda bisa menyertakan flag dalam {@link android.content.Intent} yang menyatakan cara (atau +apakah) aktivitas baru tersebut harus dikaitkan dengan tugas saat ini.</p></li> +</ul> + +<p>Dengan demikian, jika Aktivitas A memulai Aktivitas B, Aktivitas B bisa mendefinisikan dalam manifesnya cara +mengaitkan dengan tugas saat ini (jika sama sekali) dan Aktivitas A juga bisa meminta cara mengaitkan Aktivitas B +dengan tugas saat ini. Jika kedua aktivitas mendefinisikan cara mengaitkan Aktivitas B +dengan tugas, maka permintaan Aktivitas A (sebagaimana didefinisikan dalam intent) lebih dihargai daripada +permintaan Aktivitas B (sebagaimana didefinisikan dalam manifesnya).</p> + +<p class="note"><strong>Catatan:</strong> Beberapa mode peluncuran yang tersedia untuk file manifes +tidak tersedia sebagai flag untuk intent dan, juga, beberapa mode peluncuran yang tersedia sebagai flag +untuk intent tidak bisa didefinisikan dalam manifest.</p> + + +<h4 id="ManifestForTasks">Menggunakan file manifes</h4> + +<p>Saat mendeklarasikan aktivitas dalam file manifes, Anda bisa menetapkan cara mengaitkan aktivitas +dengan tugas menggunakan <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> +melalui atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code +launchMode}</a> elemen.</p> + +<p>Atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code +launchMode}</a> menetapkan instruksi tentang cara meluncurkan aktivitas +ke dalam tugas. Ada empat macam mode peluncuran yang bisa Anda tetapkan ke atribut +<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launchMode</a></code> +:</p> + +<dl> +<dt>{@code "standard"} (mode default)</dt> + <dd>Default. Sistem membuat instance baru aktivitas dalam tugas yang +akan menjadi tempat memulainya dan mengarahkan intent ke sana. Aktivitas ini bisa dibuat instance-nya beberapa kali, +masing-masing instance bisa dimiliki oleh tugas berbeda, dan satu tugas bisa memiliki beberapa instance.</dd> +<dt>{@code "singleTop"}</dt> + <dd>Jika instance aktivitas sudah ada di bagian teratas tugas saat ini, sistem +akan mengarahkan intent ke instance tersebut melalui panggilan ke metode {@link +android.app.Activity#onNewIntent onNewIntent()}, bukan membuat instance baru dari +aktivitas tersebut. Aktivitas bisa dibuat instance-nya beberapa kali, masing-masing instance bisa dimiliki +oleh tugas berbeda, dan satu tugas bisa memiliki beberapa instance (namun hanya jika +aktivitas di bagian teratas back-stack <em>bukan</em> instance yang ada dari aktivitas tersebut). + <p>Misalnya, anggaplah back-stack tugas terdiri dari aktivitas A akar dengan aktivitas B, C, +dan D di bagian teratas (back-stack adalah A-B-C-D; D yang teratas). Intent masuk untuk aktivitas tipe D. +Jika D memiliki mode peluncuran {@code "standard"} default, instance baru dari kelas ini akan diluncurkan dan +back-stack menjadi A-B-C-D-D. Namun, jika mode peluncuran D adalah {@code "singleTop"}, instance +yang ada dari D akan menerima intent melalui {@link +android.app.Activity#onNewIntent onNewIntent()}, karena ada di bagian teratas back-stack— +back-stack tetap A-B-C-D. Akan tetapi, jika intent masuk untuk aktivitas tipe B, maka +instance B baru akan ditambahkan ke back-stack, sekalipun mode peluncuran adalah{@code "singleTop"}.</p> + <p class="note"><strong>Catatan:</strong> Bila instance dari aktivitas baru telah dibuat, +pengguna bisa menekan tombol <em>Back</em> untuk kembali ke aktivitas sebelumnya. Namun bila instance +yang ada dari +aktivitas menangani intent baru, pengguna tidak bisa menekan tombol <em>Back</em> untuk kembali ke +status +aktivitas sebelum intent baru masuk di {@link android.app.Activity#onNewIntent +onNewIntent()}.</p> +</dd> + +<dt>{@code "singleTask"}</dt> + <dd>Sistem membuat tugas baru dan membuat instance aktivitas di akar tugas baru. +Akan tetapi, jika instance aktivitas sudah ada dalam tugas terpisah, sistem akan mengarahkan +intent ke instance yang ada melalui panggilan ke metode {@link +android.app.Activity#onNewIntent onNewIntent()}, bukan membuat instance baru. Hanya +boleh ada satu instance aktivitas untuk setiap kalinya. + <p class="note"><strong>Catatan:</strong> Meskipun aktivitas dimulai di tugas baru, tombol +<em>Back</em> tetap akan mengembalikan pengguna ke aktivitas sebelumnya.</p></dd> +<dt>{@code "singleInstance"}.</dt> + <dd>Sama seperti {@code "singleTask"}, namun sistem tidak meluncurkan aktivitas lain ke +tugas yang menyimpan instance. Aktivitas selalu satu dan satu-satunya anggota dari tugasnya; +aktivitas apa pun yang dimulai dengan ini akan dibuka di tugas yang terpisah.</dd> +</dl> + + +<p>Sebagai contoh lainnya, aplikasi Browser Android mendeklarasikan bahwa aktivitas browser web harus +selalu dibuka dalam tugasnya sendiri—dengan menetapkan mode pembuka {@code singleTask} dalam elemen<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a>. +Ini berarti bahwa jika aplikasi Anda mengeluarkan +intent untuk membuka Browser Android, aktivitasnya <em>tidak</em> akan ditempatkan dalam tugas +yang sama seperti aplikasi Anda. Sebagai gantinya, tugas baru akan dimulai untuk Browser atau, jika Browser +sudah memiliki tugas yang berjalan di latar belakang, tugas tersebut akan dimajukan untuk menangani intent +baru.</p> + +<p>Baik aktivitas dimulai dalam tugas baru atau maupun dalam tugas yang sama seperti aktivitas yang memulainya, tombol +<em>Back</em> selalu membawa pengguna ke aktivitas sebelumnya. Akan tetapi, jika +Anda memulai aktivitas yang menetapkan mode pembuka {@code singleTask}, maka jika instance +aktivitas tersebut ada dalam tugas latar belakang, seluruh tugas tersebut akan dibawa ke latar depan. Pada titik +ini, back-stack sekarang menyertakan semua aktivitas dari tugas yang dimajukan, di atas +back-stack. Gambar 4 mengilustrasikan tipe skenario ini.</p> + +<img src="{@docRoot}images/fundamentals/diagram_backstack_singletask_multiactivity.png" alt="" /> +<p class="img-caption"><strong>Gambar 4.</strong> Representasi tentang cara aktivitas dengan +mode pembuka "singleTask" ditambahkan ke back-stack. Jika aktivitas tersebut sudah menjadi bagian dari +tugas latar belakang dengan back-stack sendiri, maka seluruh back-stack juga +dimajukan, di atas tugas saat ini.</p> + +<p>Untuk informasi selengkapnya tentang menggunakan mode pembuka dalam file manifes, lihat dokumentasi elemen +<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> +, di mana atribut {@code launchMode} dan nilai-nilai yang diterima +akan dibahas selengkapnya.</p> + +<p class="note"><strong>Catatan:</strong> Perilaku yang Anda tentukan untuk aktivitas dengan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> +bisa dikesampingkan dengan flag yang disertakan bersama intent yang memulai aktivitas Anda, seperti dibahas dalam +bagian berikutnya.</p> + + + +<h4 id="#IntentFlagsForTasks">Menggunakan flag Intent</h4> + +<p>Saat memulai aktivitas, Anda bisa memodifikasi asosiasi default aktivitas pada tugasnya + dengan menyertakan flag dalam intent yang Anda kirimkan ke {@link +android.app.Activity#startActivity startActivity()}. Flag yang bisa Anda gunakan untuk memodifikasi perilaku default +adalah:</p> + +<p> + <dt>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</dt> + <dd>Memulai aktivitas dalam tugas baru. Jika tugas sudah dijalankan untuk aktivitas yang sekarang +Anda mulai, tugas tersebut akan dibawa ke latar depan dengan status terakhir yang dipulihkan dan aktivitas +akan menerima intent baru dalam {@link android.app.Activity#onNewIntent onNewIntent()}. + <p>Ini menghasilkan perilaku yang sama dengan nilai {@code "singleTask"} <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> +yang dibahas di bagian sebelumnya.</p></dd> + <dt>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</dt> + <dd>Jika aktivitas yang dimulai adalah aktivitas saat ini (di bagian teratas back-stack), maka +instance yang ada akan menerima panggilan ke {@link android.app.Activity#onNewIntent onNewIntent()} +sebagai ganti membuat instance baru aktivitas. + <p>Ini menghasilkan perilaku yang sama dengan nilai {@code "singleTop"} <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> +yang dibahas di bagian sebelumnya.</p></dd> + <dt>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</dt> + <dd>Jika aktivitas yang dimulai sudah berjalan dalam tugas saat ini, maka sebagai +ganti meluncurkan instance baru aktivitas tersebut, semua kegiatan lain di atasnya akan +dimusnahkan dan intent ini akan disampaikan ke instance aktivitas yang dilanjutkan (sekarang di atas), +melalui {@link android.app.Activity#onNewIntent onNewIntent()}). + <p>Tidak ada nilai untuk atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> + yang menghasilkan perilaku ini.</p> + <p>{@code FLAG_ACTIVITY_CLEAR_TOP} paling sering digunakan bersama dengan + {@code FLAG_ACTIVITY_NEW_TASK}. +Bila digunakan bersama-sama, flag ini adalah cara penempatan aktivitas yang ada +dalam tugas lain dan meletakkannya dalam posisi yang memungkinkannya merespons intent. </p> + <p class="note"><strong>Catatan:</strong> Jika mode pembuka aktivitas yang didesain adalah +{@code "standard"}, +ini juga akan dihapus dari back-stack dan instance baru akan diluncurkan di tempatnya untuk menangani +intent yang masuk. Itu karena instance baru selalu dibuat untuk intent baru bila +mode peluncuran adalah {@code "standard"}. </p> +</dd> +</dl> + + + + + +<h3 id="Affinities">Menangani afinitas</h3> + +<p><em>Afinitas</em> menunjukkan tugas mana yang disukai aktivitas untuk dimiliki. Secara default, semua +aktivitas aplikasi yang sama memiliki afinitas untuk satu sama lain. Jadi, secara default, semua +aktivitas dalam aplikasi yang sama lebih menyukai berada dalam tugas yang sama. Akan tetapi, Anda bisa memodifikasi +afinitas default untuk suatu aktivitas. Aktivitas yang didefinisikan dalam +aplikasi yang berbeda bisa berbagi afinitas, atau aktivitas yang didefinisikan dalam aplikasi yang sama bisa +diberi afinitas tugas yang berbeda.</p> + +<p>Anda bisa memodifikasi afinitas untuk setiap yang diberikan +dengan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a> +elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a>.</p> + +<p>Atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a> +mengambil nilai string, yang harus unik dari nama paket default +yang dideklarasikan dalam elemen <a href="{@docRoot}guide/topics/manifest/manifest-element.html"> +{@code <manifest>} +</a>, karena sistem menggunakan nama untuk mengidentifikasi afinitas +tugas default untuk aplikasi.</p> + +<p>Afinitas berperan dalam dua keadaan:</p> +<ul> + <li>Bila intent yang meluncurkan aktivitas berisi flag + {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} +. + +<p>Aktivitas baru, secara default, diluncurkan ke dalam tugas aktivitas +yang disebut {@link android.app.Activity#startActivity startActivity()}. Ini didorong ke back-stack +yang sama seperti caller. Akan tetapi, jika intent yang diteruskan ke +{@link android.app.Activity#startActivity startActivity()} +berisi flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} +, maka sistem akan mencari tugas yang berbeda untuk menampung aktivitas baru. Sering kali, itu adalah tugas baru. +Akan tetapi, tidak harus demikian. Jika sudah ada tugas lama dengan afinitas yang sama seperti +aktivitas baru, aktivitas ini akan diluncurkan ke dalam tugas tersebut. Jika tidak, tugas baru akan dimulai.</p> + +<p>Jika flag ini menyebabkan aktivitas memulai tugas baru dan pengguna menekan tombol <em>Home</em> +untuk meninggalkannya, +harus ada cara bagi pengguna untuk mengarahkan kembali ke tugas. Beberapa entitas (seperti +notification manager) selalu memulai aktivitas dalam tugas eksternal, tidak pernah sebagai bagian dari miliknya sendiri, jadi +selalu menempatkan {@code FLAG_ACTIVITY_NEW_TASK} dalam intent yang diteruskan ke +{@link android.app.Activity#startActivity startActivity()}. +Jika Anda memiliki aktivitas yang bisa dipanggil melalui +entitas eksternal yang mungkin menggunakan flag ini, hati-hatilah karena pengguna memiliki cara independen untuk kembali +ke tugas yang telah dimulai, seperti dengan ikon launcher (aktivitas akar dari tugas +memiliki filter intent {@link android.content.Intent#CATEGORY_LAUNCHER}; lihat bagian <a href="#Starting">Memulai tugas</a> di bawah ini).</p> +</li> + + <li>Bila aktivitas memiliki atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent"> +{@code allowTaskReparenting}</a> sendiri yang diatur ke {@code "true"}. + <p>Dalam hal ini, aktivitas bisa berpindah dari tugas yang dimulainya ke tugas yang afinitasnya +dimilikinya, bila tugas tersebut di bawa ke latar depan.</p> + <p>Misalnya, anggaplah sebuah aktivitas melaporkan kondisi cuaca di sejumlah kota terpilih +yang didefinisikan sebagai bagian dari aplikasi perjalanan. Aktivitas memiliki afinitas yang sama dengan aktivitas lain dalam aplikasi +yang sama (afinitas aplikasi default) dan aktivitas ini memungkinkan re-parenting dengan atribut ini. +Bila salah satu aktivitas Anda memulai aktivitas laporan cuaca, awalnya aktivitas ini dimiliki oleh tugas +yang sama dengan aktivitas Anda. Akan tetapi, bila tugas aplikasi perjalanan di bawa ke latar depan, +aktivitas laporan cuaca akan ditetapkan kembali ke tugas itu dan ditampilkan di dalamnya.</p> +</li> +</ul> + +<p class="note"><strong>Tip:</strong> Jika file {@code .apk} berisi lebih dari satu "aplikasi" +dari sudut pandang pengguna, Anda mungkin perlu menggunakan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a> + untuk menetapkan afinitas berbeda pada aktivitas yang terkait dengan setiap "aplikasi".</p> + + + +<h3 id="Clearing">Menghapus back-stack</h3> + +<p>Jika pengguna meninggalkan tugas dalam waktu yang lama, sistem akan menghapus tugas semua aktivitas kecuali +aktivitas akar. Bila pengguna kembali ke tugas itu lagi, hanya aktivitas akar yang akan dipulihkan. +Sistem berperilaku seperti ini, karena, setelah sekian waktu, pengguna mungkin telah mengabaikan +apa yang mereka kerjakan sebelum dan kembali ke tugas itu untuk memulai sesuatu yang baru. </p> + +<p>Ada beberapa atribut aktivitas yang bisa Anda gunakan untuk memodifikasi perilaku ini: </p> + +<dl> +<dt><code><a +href="{@docRoot}guide/topics/manifest/activity-element.html#always">alwaysRetainTaskState</a></code> +</dt> +<dd>Jika atribut ini ditetapkan ke {@code "true"} dalam aktivitas akar tugas, +perilaku default yang baru dijelaskan tidak akan terjadi. + Tugas akan mempertahankan semua aktivitas dalam back-stack bahkan setelah sekian lama.</dd> + +<dt><code><a +href="{@docRoot}guide/topics/manifest/activity-element.html#clear">clearTaskOnLaunch</a></code></dt> +<dd>Jika atribut ini diatur ke {@code "true"} dalam aktivitas akar tugas, back- +stack akan dihapus hingga aktivitas akar bila pengguna meninggalkan tugas +dan kembali lagi. Dengan kata lain, ini adalah lawan dari +<a href="{@docRoot}guide/topics/manifest/activity-element.html#always"> +{@code alwaysRetainTaskState}</a>. Pengguna selalu kembali ke tugas dengan +status awalnya, walaupun hanya sebentar meninggalkan tugas.</dd> + +<dt><code><a +href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTaskLaunch</a></code> +</dt> +<dd>Atribut ini seperti <a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">{@code clearTaskOnLaunch}</a>, +namun beroperasi pada +satu aktivitas, bukan pada seluruh tugas. Hal ini juga bisa menyebabkan aktivitas +hilang, termasuk aktivitas akar. Bila ini diatur ke {@code "true"}, +aktivitas akan tetap menjadi bagian dari tugas hanya untuk sesi saat ini. Jika pengguna +keluar dan kemudian kembali ke tugas tersebut, tugas tidak akan ada lagi.</dd> +</dl> + + + + +<h3 id="Starting">Memulai tugas</h3> + +<p>Anda bisa mengatur aktivitas sebagai titik masuk untuk tugas dengan memberikan filter intent dengan +{@code "android.intent.action.MAIN"} sebagai tindakan yang ditetapkan dan +{@code "android.intent.category.LAUNCHER"} +sebagai kategori yang ditetapkan. Misalnya:</p> + +<pre> +<activity ... > + <intent-filter ... > + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + ... +</activity> +</pre> + +<p>Filter intent semacam ini akan menyebabkan ikon dan label untuk +aktivitas ditampilkan dalam launcher aplikasi, yang akan memberi cara kepada pengguna untuk meluncurkan aktivitas dan +kembali ke tugas yang dibuatnya kapan saja setelah ia telah diluncurkan. +</p> + +<p>Kemampuan kedua ini penting: Pengguna harus bisa meninggalkan tugas dan kemudian kembali ke tugas tersebut +nanti dengan menggunakan launcher aktivitas ini. Karena itu, kedua <a href="#LaunchModes">mode +pembuka</a> yang menandai aktivitas selalu memulai tugas, {@code "singleTask"} dan +{@code "singleInstance"}, hanya boleh digunakan bila aktivitas memiliki filter +{@link android.content.Intent#ACTION_MAIN} +dan {@link android.content.Intent#CATEGORY_LAUNCHER}. Bayangkan, misalnya, apa yang akan +terjadi jika filter tidak ada: Intent meluncurkan aktivitas{@code "singleTask"}, memulai +tugas yang baru, dan pengguna menghabiskan lebih banyak waktu mengerjakan tugas tersebut. Pengguna kemudian menekan tombol +<em>Home</em>. Tugas kini dikirim ke latar belakang dan tidak terlihat. Sekarang pengguna tidak memiliki cara untuk kembali +ke tugas tersebut, karena tidak dinyatakan dalam launcher aplikasi.</p> + +<p>Untuk kasus-kasus di mana Anda tidak ingin pengguna bisa kembali ke aktivitas, atur dalam +<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> + pada +<a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">{@code finishOnTaskLaunch}</a> +elemen ke {@code "true"} (lihat <a href="#Clearing">Menghapus back-stack</a>).</p> + +<p>Informasi lebih jauh tentang cara menyatakan dan mengelola tugas dan aktivitas dalam +layar ikhtisar tersedia dalam<a href="{@docRoot}guide/components/recents.html"> +Layar Ikhtisar</a>.</p> + +<!-- +<h2>Beginner's Path</h2> + +<p>For more information about how to use intents to +activate other application components and publish the intents to which your components +respond, continue with the <b><a +href="{@docRoot}guide/components/intents-filters.html">Intents and Intent +Filters</a></b> document.</p> +--> |