Copy IN files to ID, temporarily leaving IN in place.
Change-Id: I1a92e4254fe57817cb555629059539aaec47e182
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
page.title=Panduan Pengujian
|
||||
page.image=images/cards/card-n-guide_2x.png
|
||||
meta.tags="preview", "testing"
|
||||
page.tags="preview", "developer preview"
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#runtime-permissions">Izin Pengujian</a></li>
|
||||
<li><a href="#doze-standby">Menguji Istirahatkan dan Aplikasi Siaga</a></li>
|
||||
<li><a href="#ids">Pencadangan Otomatis dan Identifier Perangkat</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Android N memberi Anda kesempatan untuk memastikan aplikasi bekerja pada
|
||||
platform versi berikutnya. Pratinjau ini berisi beberapa API dan perubahan perilaku yang bisa
|
||||
memengaruhi aplikasi Anda, sebagaimana dijelaskan dalam <a href="{@docRoot}preview/api-overview.html">Ringkasan
|
||||
API</a> dan <a href="{@docRoot}preview/behavior-changes.html">Perubahan Perilaku</a>. Dalam menguji
|
||||
aplikasi dengan pratinjau, ada beberapa perubahan sistem spesifik yang harus Anda fokuskan untuk
|
||||
memastikan pengguna mendapatkan pengalaman yang bagus.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Panduan ini menjelaskan apa dan bagaimana menguji fitur pratinjau dengan aplikasi Anda. Anda harus
|
||||
mengutamakan pengujian fitur pratinjau spesifik ini, dikarenakan pengaruhnya yang besar pada
|
||||
perilaku aplikasi Anda:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="#runtime-permissions">Izin</a>
|
||||
</li>
|
||||
<li><a href="#doze-standby">Istirahatkan dan Aplikasi Siaga</a>
|
||||
</li>
|
||||
<li><a href="#ids">Pencadangan Otomatis dan Identifier Perangkat</a></li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Untuk informasi selengkapnya tentang cara menyiapkan perangkat atau perangkat maya dengan citra sistem pratinjau
|
||||
untuk pengujian, lihat <a href="{@docRoot}preview/setup-sdk.html">Menyiapkan
|
||||
Android N SDK</a>.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="runtime-permissions">Izin Pengujian</h2>
|
||||
|
||||
<p>
|
||||
Model <a href="{@docRoot}preview/features/runtime-permissions.html">Izin</a> yang baru
|
||||
mengubah cara alokasi izin untuk aplikasi Anda oleh pengguna. Sebagai ganti memberi semua
|
||||
izin selama prosedur pemasangan, aplikasi Anda harus meminta izin kepada pengguna secara individual
|
||||
pada waktu proses. Bagi pengguna, perilaku ini memberi kontrol yang lebih detail atas setiap aktivitas aplikasi, dan
|
||||
juga konteks yang lebih untuk memahami sebab aplikasi meminta izin tertentu. Pengguna
|
||||
bisa memberi atau mencabut izin yang diberikan pada suatu aplikasi secara individual kapan saja. Fitur
|
||||
pratinjau ini kemungkinan besar memengaruhi perilaku aplikasi Anda dan mungkin menghambat fungsi beberapa
|
||||
fitur aplikasi Anda, atau mengurangi kualitas kerjanya.
|
||||
</p>
|
||||
|
||||
<p class="caution">
|
||||
Perubahan ini memengaruhi semua aplikasi yang berjalan di platform baru, bahkan aplikasi yang tidak menargetkan versi
|
||||
platform baru. Platform ini memberikan perilaku kompatibilitas terbatas untuk aplikasi lawas, namun Anda
|
||||
harus mulai merencanakan migrasi aplikasi ke model izin baru sekarang juga, dengan tujuan
|
||||
mempublikasikan versi terbaru aplikasi Anda saat peluncuran platform secara resmi.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="permission-test-tips">Tip pengujian</h3>
|
||||
|
||||
<p>
|
||||
Gunakan tip berikut untuk membantu Anda merencanakan dan menjalankan pengujian aplikasi dengan
|
||||
perilaku izin yang baru.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Identifikasi izin aplikasi Anda saat ini dan jalur kode terkait.</li>
|
||||
<li>Uji alur pengguna pada semua layanan dan data yang dilindungi izin.</li>
|
||||
<li>Uji dengan berbagai kombinasi izin yang diberikan/dicabut.</li>
|
||||
<li>Gunakan alat bantu {@code adb} untuk mengelola izin dari baris perintah:
|
||||
<ul>
|
||||
<li>Cantumkan daftar izin dan status berdasarkan kelompok:
|
||||
<pre>adb shell pm list permissions -d -g</pre>
|
||||
</li>
|
||||
<li>Beri atau cabut satu atau beberapa izin menggunakan sintaks berikut:<br>
|
||||
<pre>adb shell pm [grant|revoke] <permission.name> ...</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Analisis aplikasi Anda untuk layanan yang menggunakan izin.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="permission-test-strategy">Strategi pengujian</h3>
|
||||
|
||||
<p>
|
||||
Perubahan izin memengaruhi struktur dan desain aplikasi Anda, begitu juga
|
||||
pengalaman pengguna dan alur yang Anda sediakan untuk pengguna. Anda harus menilai penggunaan izin
|
||||
aplikasi saat ini dan mulai merencanakan alur baru yang ingin ditawarkan. Rilis platform
|
||||
resmi menyediakan perilaku kompatibilitas, namun Anda harus merencanakan pembaruan aplikasi dan tidak
|
||||
bergantung pada perilaku ini.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Identifikasi izin yang sebenarnya diperlukan dan digunakan aplikasi Anda, kemudian temukan berbagai
|
||||
jalur kode yang menggunakan layanan yang dilindungi izin. Anda bisa melakukan ini melalui kombinasi
|
||||
pengujian pada platform baru dan analisis kode. Dalam pengujian, Anda harus fokus pada pemilihan
|
||||
izin waktu proses dengan mengubah {@code targetSdkVersion} aplikasi ke versi pratinjau. Untuk
|
||||
informasi selengkapnya, lihat <a href="{@docRoot}preview/setup-sdk.html#">Menyiapkan
|
||||
Android N SDK</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Uji dengan berbagai kombinasi izin yang dicabut dan ditambahkan, untuk menyoroti alur pengguna yang
|
||||
bergantung pada izin. Jika dependensi tidak jelas atau logis, Anda harus mempertimbangkan
|
||||
optimalisasi atau kompartementalisasi alur tersebut untuk mengeliminasi dependensi atau menjelaskan alasan
|
||||
diperlukannya izin.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Untuk informasi selengkapnya tentang perilaku izin waktu proses, pengujian, dan praktik terbaik, lihat
|
||||
halaman pratinjau <a href="{@docRoot}preview/features/runtime-permissions.html">Izin</a>
|
||||
pengembang.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="doze-standby">Menguji Istirahatkan dan Aplikasi Siaga</h2>
|
||||
|
||||
<p>
|
||||
Fitur penghematan daya Istirahatkan dan Aplikasi Siaga membatasi jumlah pemrosesan latar belakang yang
|
||||
bisa dikerjakan aplikasi Anda saat perangkat dalam keadaan diam atau saat aplikasi Anda sedang tidak fokus. Pembatasan
|
||||
yang dapat diberlakukan oleh sistem pada aplikasi termasuk akses jaringan terbatas atau tidak ada,
|
||||
tugas latar belakang yang ditangguhkan, Pemberitahuan yang ditangguhkan, permintaan membangunkan yang diabaikan, serta alarm. Untuk memastikan
|
||||
aplikasi Anda berperilaku dengan benar pada optimalisasi penghematan daya ini, Anda harus menguji aplikasi dengan
|
||||
menyimulasikan keadaan baterai yang sedang tinggal sedikit ini.
|
||||
</p>
|
||||
|
||||
<h4 id="doze">Menguji aplikasi Anda dengan Istirahatkan</h4>
|
||||
|
||||
<p>Untuk menguji Istirahatkan dengan aplikasi Anda:</p>
|
||||
|
||||
<ol>
|
||||
<li>Konfigurasikan perangkat keras atau perangkat maya dengan citra sistem Android N.</li>
|
||||
<li>Hubungkan perangkat dengan mesin pengembangan dan pasang aplikasi Anda.</li>
|
||||
<li>Jalankan aplikasi Anda dan biarkan aktif.</li>
|
||||
<li>Simulasikan perangkat yang sedang masuk ke dalam mode Istirahatkan dengan menjalankan perintah berikut:
|
||||
|
||||
<pre>
|
||||
$ adb shell dumpsys battery unplug
|
||||
$ adb shell dumpsys deviceidle step
|
||||
$ adb shell dumpsys deviceidle -h
|
||||
</pre>
|
||||
|
||||
</li>
|
||||
<li>Amati perilaku aplikasi Anda saat perangkat diaktifkan kembali. Pastikan aplikasi
|
||||
pulih dengan baik saat perangkat keluar dari Istirahatkan.</li>
|
||||
</ol>
|
||||
|
||||
|
||||
<h4 id="standby">Menguji aplikasi dengan Aplikasi Siaga</h4>
|
||||
|
||||
<p>Untuk menguji mode Aplikasi Siaga dengan aplikasi Anda:</p>
|
||||
|
||||
<ol>
|
||||
<li>Konfigurasikan perangkat keras atau perangkat maya dengan citra sistem Android N.</li>
|
||||
<li>Hubungkan perangkat dengan mesin pengembangan dan pasang aplikasi Anda.</li>
|
||||
<li>Jalankan aplikasi Anda dan biarkan aktif.</li>
|
||||
<li>Simulasikan aplikasi yang sedang masuk ke dalam mode siaga dengan menjalankan perintah berikut:
|
||||
|
||||
<pre>
|
||||
$ adb shell am broadcast -a android.os.action.DISCHARGING
|
||||
$ adb shell am set-idle <packageName> true
|
||||
</pre>
|
||||
|
||||
</li>
|
||||
<li>Simulasikan membangunkan aplikasi Anda menggunakan perintah berikut:
|
||||
<pre>$ adb shell am set-idle <packageName> false</pre>
|
||||
</li>
|
||||
<li>Amati perilaku aplikasi Anda saat dibangunkan. Pastikan aplikasi pulih dengan baik
|
||||
dari mode siaga. Secara khusus, Anda harus memeriksa apakah Pemberitahuan aplikasi dan pekerjaan latar belakang
|
||||
tetap berjalan sebagaimana yang diharapkan.</li>
|
||||
</ol>
|
||||
|
||||
<h2 id="ids">Auto Backup for Apps dan Identifier Perangkat Spesifik</h2>
|
||||
|
||||
<p>Jika aplikasi Anda mempertahankan identifier perangkat spesifik, seperti ID pendaftaran Google
|
||||
Cloud Messaging, dalam penyimpanan internal,
|
||||
pastikan Anda mengikuti praktik terbaik untuk mengecualikan lokasi
|
||||
penyimpanan dari pencadangan otomatis, seperti dijelaskan dalam <a href="{@docRoot}preview/backup/index.html">Auto
|
||||
Backup for Apps</a>. </p>
|
||||
@@ -0,0 +1,610 @@
|
||||
page.title=Perubahan Perilaku
|
||||
page.keywords=pratinjau,sdk,kompatibilitas
|
||||
meta.tags="preview", "compatibility"
|
||||
page.tags="preview", "developer preview"
|
||||
page.image=images/cards/card-n-changes_2x.png
|
||||
@jd:body
|
||||
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
|
||||
<ol>
|
||||
<li><a href="#perf">Peningkatan Kinerja</a>
|
||||
<ol>
|
||||
<li><a href="#doze">Istirahatkan</a></li>
|
||||
<li><a href="#bg-opt">Optimalisasi Latar Belakang</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#perm">Perubahan Izin</a>
|
||||
</li>
|
||||
<li><a href="#sharing-files">Berbagi File Antar Aplikasi</a></li>
|
||||
<li><a href="#accessibility">Peningkatan Aksesibilitas</a>
|
||||
<ol>
|
||||
<li><a href="#screen-zoom">Perbesaran Layar</a></li>
|
||||
<li><a href="#vision-settings">Vision Settings di Setup Wizard</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#ndk">Penautan Aplikasi NDK ke Pustaka Platform</a></li>
|
||||
<li><a href="#afw">Android for Work</a></li>
|
||||
<li><a href="#annotations">Retensi Anotasi</a></li>
|
||||
<li><a href="#other">Poin Penting Lainnya</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>Lihat Juga</h2>
|
||||
<ol>
|
||||
<li><a href="{@docRoot}preview/api-overview.html">
|
||||
Ringkasan Android N API</a></li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>
|
||||
Bersama fitur dan kemampuan baru, Android N
|
||||
menyertakan berbagai macam perubahan sistem dan perubahan perilaku API. Dokumen ini
|
||||
menyoroti beberapa perubahan utama yang harus dipahami dan diperhitungkan
|
||||
dalam aplikasi Anda.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Jika Anda sebelumnya telah mempublikasikan aplikasi untuk Android, ketahuilah bahwa aplikasi Anda
|
||||
mungkin dipengaruhi oleh perubahan dalam platform.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="perf">Baterai dan Memori</h2>
|
||||
|
||||
<p>
|
||||
Android N menyertakan perubahan perilaku sistem yang bertujuan untuk meningkatkan daya tahan baterai
|
||||
perangkat dan mengurangi penggunaan RAM. Perubahan ini bisa memengaruhi akses aplikasi Anda ke
|
||||
sumber daya sistem, termasuk cara aplikasi Anda berinteraksi dengan aplikasi lain melalui
|
||||
intent implisit tertentu.
|
||||
</p>
|
||||
|
||||
<h3 id="doze">Istirahatkan</h3>
|
||||
|
||||
<p>
|
||||
Diperkenalkan dalam Android 6.0 (API level 23), Istirahatkan meningkatkan daya tahan baterai dengan
|
||||
menangguhkan aktivitas CPU dan jaringan bila pengguna tidak mencabut perangkat,
|
||||
tidak bergerak, dan layar dinonaktifkan. Android N lebih
|
||||
menyempurnakan Istirahatkan dengan menerapkan subset CPU dan pembatasan jaringan
|
||||
bila perangkat dicabut dan layar dinonaktifkan, namun tidak harus
|
||||
diam, misalnya, bila handset dibawa bepergian di saku pengguna.
|
||||
</p>
|
||||
|
||||
|
||||
<img src="{@docRoot}images/android-7.0/doze-diagram-1.png" alt="" height="251px" id="figure1" />
|
||||
<p class="img-caption">
|
||||
<strong>Gambar 1.</strong> Ilustrasi tentang cara Istirahatkan menerapkan pembatasan
|
||||
aktivitas sistem level pertama untuk meningkatkan daya tahan baterai.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Bila perangkat sedang menggunakan daya baterai, dan layar telah nonaktif selama jangka waktu
|
||||
tertentu, perangkat akan memasuki Istirahatkan dan menerapkan subset pembatasan pertama: Perangkat
|
||||
akan menutup akses jaringan aplikasi, serta menangguhkan pekerjaan dan sinkronisasi. Jika perangkat sedang
|
||||
diam selama jangka waktu tertentu setelah memasuki Istirahatkan, sistem akan menerapkan
|
||||
pembatasan Istirahatkan selebihnya terhadap alarm {@link android.os.PowerManager.WakeLock},
|
||||
{@link android.app.AlarmManager}, GPS, dan pemindaian Wi-Fi. Tidak peduli
|
||||
apakah sebagian atau semua pembatasan Istirahatkan diterapkan, sistem akan membangunkan
|
||||
perangkat selama jeda pemeliharaan singkat, dan selama itu aplikasi diizinkan
|
||||
mengakses jaringan dan bisa mengeksekusi semua pekerjaan/sinkronisasi yang telah ditangguhkan.
|
||||
</p>
|
||||
|
||||
|
||||
<img src="{@docRoot}images/android-7.0/doze-diagram-2.png" alt="" id="figure2" />
|
||||
<p class="img-caption">
|
||||
<strong>Gambar 2.</strong> Ilustrasi tentang cara Istirahatkan menerapkan pembatasan
|
||||
aktivitas sistem level kedua setelah perangkat diam selama jangka waktu tertentu.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Perhatikan, mengaktifkan layar atau mencolokkan steker perangkat akan mengeluarkan dari Istirahatkan
|
||||
dan membuang pembatasan pemrosesan ini. Perilaku tambahan ini tidak
|
||||
memengaruhi rekomendasi dan praktik terbaik dalam menyesuaikan aplikasi Anda dengan versi
|
||||
Istirahatkan sebelumnya yang diperkenalkan dalam Android 6.0 (API level 23), seperti yang dibahas di
|
||||
<a href="{@docRoot}training/monitoring-device-state/doze-standby.html">
|
||||
Mengoptimalkan untuk Istirahatkan dan Aplikasi Siaga</a>. Anda tetap harus
|
||||
mengikuti rekomendasi itu, seperti menggunakan Google Cloud Messaging (GCM) untuk
|
||||
mengirim dan menerima pesan, serta mulai merencanakan pembaruan
|
||||
untuk mengakomodasi perilaku Istirahatkan tambahan.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="bg-opt">Project Svelte: Optimalisasi Latar Belakang</h3>
|
||||
|
||||
<p>
|
||||
Android N membuang tiga siaran implisit untuk membantu mengoptimalkan
|
||||
penggunaan memori dan konsumsi daya. Perubahan ini penting karena siaran
|
||||
implisit sering memulai aplikasi yang telah didaftarkan untuk mendengarkannya di
|
||||
latar belakang. Membuang siaran ini bisa sangat menguntungkan
|
||||
kinerja perangkat dan pengalaman pengguna.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Perangkat seluler seringkali mengalami perubahan konektivitas, seperti saat berpindah
|
||||
antara Wi-Fi dan data seluler. Saat ini, aplikasi bisa memantau perubahan dalam
|
||||
konektivitas dengan mendaftarkan suatu penerima untuk siaran implisit {@link
|
||||
android.net.ConnectivityManager#CONNECTIVITY_ACTION} dalam manifes
|
||||
mereka. Karena banyak aplikasi yang didaftarkan untuk menerima siaran ini, switch jaringan tunggal
|
||||
bisa menyebabkan semuanya aktif dan memproses siaran tersebut
|
||||
secara bersamaan.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Demikian pula, dalam Android versi sebelumnya, aplikasi bisa mendaftar untuk menerima siaran implisit {@link
|
||||
android.hardware.Camera#ACTION_NEW_PICTURE} dan {@link
|
||||
android.hardware.Camera#ACTION_NEW_VIDEO} dari aplikasi lain, seperti
|
||||
Kamera. Bila pengguna mengambil gambar dengan aplikasi Kamera, semua aplikasi ini akan aktif
|
||||
untuk memproses siaran.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Untuk meminimalkan masalah ini, Android N menerapkan optimalisasi
|
||||
berikut:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Aplikasi yang menargetkan Android N tidak menerima siaran {@link
|
||||
android.net.ConnectivityManager#CONNECTIVITY_ACTION}, sekalipun
|
||||
memiliki entri manifes untuk meminta pemberitahuan mengenai kejadian ini. Aplikasi
|
||||
yang berjalan tetap bisa mendengarkan {@code CONNECTIVITY_CHANGE} pada thread utama
|
||||
jika mereka meminta pemberitahuan dengan {@link android.content.BroadcastReceiver}.
|
||||
</li>
|
||||
|
||||
<li>Aplikasi tidak bisa mengirim atau menerima siaran {@link
|
||||
android.hardware.Camera#ACTION_NEW_PICTURE} atau {@link
|
||||
android.hardware.Camera#ACTION_NEW_VIDEO}. Optimalisasi ini
|
||||
memengaruhi semua aplikasi, bukan hanya aplikasi yang menargetkan Android N.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Jika aplikasi Anda menggunakan intent ini, Anda harus membuang dependensi padanya
|
||||
secepat mungkin agar Anda bisa menargetkan perangkat Android N dengan benar.
|
||||
Kerangka kerja Android menyediakan beberapa solusi untuk mengurangi kebutuhan akan
|
||||
siaran implisit ini. Misalnya, {@link
|
||||
android.app.job.JobScheduler} API menyediakan mekanisme yang tangguh untuk menjadwalkan
|
||||
operasi jaringan bila kondisi yang ditetapkan, seperti koneksi ke jaringan
|
||||
berbiaya tetap, terpenuhi. Anda juga dapat menggunakan {@link
|
||||
android.app.job.JobScheduler} untuk bereaksi terhadap perubahan pada penyedia materi.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Untuk informasi selengkapnya tentang optimalisasi latar belakang di N dan cara menyesuaikan aplikasi Anda,
|
||||
lihat <a href="{@docRoot}preview/features/background-optimization.html">Optimalisasi
|
||||
Latar Belakang</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="perm">Perubahan Izin</h2>
|
||||
|
||||
<p>
|
||||
Android N menyertakan perubahan pada izin yang bisa memengaruhi aplikasi Anda.
|
||||
</p>
|
||||
|
||||
<h3 id="permfilesys">Perubahan izin sistem file</h3>
|
||||
|
||||
<p>
|
||||
Guna meningkatkan keamanan file privat, direktori privat
|
||||
aplikasi yang menargetkan Android N atau yang lebih tinggi memiliki akses terbatas (<code>0700</code>).
|
||||
Pengaturan ini mencegah kebocoran metadata dari file privat, seperti ukuran
|
||||
atau eksistensi. Perubahan izin ini memiliki beberapa efek samping:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Izin file privat tidak boleh dianggap remeh oleh pemilik,
|
||||
dan usaha untuk melakukannya menggunakan
|
||||
{@link android.content.Context#MODE_WORLD_READABLE} dan/atau
|
||||
{@link android.content.Context#MODE_WORLD_WRITEABLE}, akan memicu sebuah
|
||||
{@link java.lang.SecurityException}.
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Seperti sebelumnya, pembatasan ini tidak sepenuhnya diterapkan.
|
||||
Aplikasi mungkin masih memodifikasi izin ke direktori privat mereka menggunakan
|
||||
API asal atau {@link java.io.File File} API. Akan tetapi, kami sangat
|
||||
tidak menyarankan Anda meremehkan izin direktori privat.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Meneruskan URI <code>file://</code> di luar domain paket dapat meninggalkan
|
||||
penerima dengan jalur yang tidak bisa di akses. Karena itu, upaya untuk meneruskan URI
|
||||
<code>file://</code> akan memicu
|
||||
<code>FileUriExposedException</code>. Cara yang disarankan adalah
|
||||
materi file privat menggunakan {@link
|
||||
android.support.v4.content.FileProvider}.
|
||||
</li>
|
||||
<li>
|
||||
{@link android.app.DownloadManager} tidak bisa lagi berbagi
|
||||
file yang tersimpan secara privat berdasarkan nama file. Aplikasi lawas dapat mengakibatkan
|
||||
jalur yang tidak dapat diakses saat mengakses {@link
|
||||
android.app.DownloadManager#COLUMN_LOCAL_FILENAME}. Aplikasi yang menargetkan
|
||||
Android N atau yang lebih tinggi akan memicu {@link java.lang.SecurityException} saat
|
||||
berupaya mengakses
|
||||
{@link android.app.DownloadManager#COLUMN_LOCAL_FILENAME}.
|
||||
Aplikasi lawas yang menyetel lokasi unduhan ke lokasi publik dengan
|
||||
menggunakan
|
||||
{@link
|
||||
android.app.DownloadManager.Request#setDestinationInExternalFilesDir
|
||||
DownloadManager.Request.setDestinationInExternalFilesDir()} atau
|
||||
{@link
|
||||
android.app.DownloadManager.Request#setDestinationInExternalPublicDir
|
||||
DownloadManager.Request.setDestinationInExternalPublicDir()}
|
||||
tetap bisa mengakses jalur tersebut di
|
||||
{@link android.app.DownloadManager#COLUMN_LOCAL_FILENAME}, akan tetapi,
|
||||
metode ini sangat tidak disarankan. Cara yang disarankan untuk mengakses file
|
||||
yang diekspos oleh {@link android.app.DownloadManager} adalah menggunakan
|
||||
{@link android.content.ContentResolver#openFileDescriptor
|
||||
ContentResolver.openFileDescriptor()}.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="sharing-files">Berbagi File Antar Aplikasi</h2>
|
||||
|
||||
<p>
|
||||
Untuk aplikasi yang menargetkan Android N, kerangka kerja Android menerapkan
|
||||
kebijakan {@link android.os.StrictMode} API yang melarang mengekspos URI {@code file://}
|
||||
di luar aplikasi Anda. Jika sebuah intent berisi URI file meninggalkan aplikasi Anda, aplikasi tersebut akan gagal
|
||||
dengan pengecualian {@code FileUriExposedException}.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Untuk berbagi file antar aplikasi, Anda harus mengirim URI {@code content://}
|
||||
dan memberikan izin akses sementara pada URI. Cara termudah untuk memberikan izin ini adalah dengan
|
||||
menggunakan kelas {@link android.support.v4.content.FileProvider}. Untuk informasi selengkapnya
|
||||
mengenai izin dan berbagi file,
|
||||
lihat <a href="{@docRoot}training/secure-file-sharing/index.html">Berbagi File</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="accessibility">Peningkatan Aksesibilitas</h2>
|
||||
|
||||
<p>
|
||||
Android N menyertakan perubahan yang bertujuan meningkatkan kegunaan
|
||||
platform untuk pengguna dengan penglihatan yang rendah atau lemah. Perubahan ini umumnya tidak
|
||||
memerlukan perubahan kode dalam aplikasi Anda, akan tetapi Anda harus memeriksa
|
||||
fitur ini dan mengujinya dengan aplikasi untuk menilai kemungkinan dampaknya terhadap pengalaman
|
||||
pengguna.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="screen-zoom">Perbesaran Layar</h3>
|
||||
|
||||
<p>
|
||||
Android N memungkinkan pengguna menyetel <strong>Display size</strong> yang akan memperbesar
|
||||
atau memperkecil semua elemen pada layar, sehingga meningkatkan aksesibilitas perangkat
|
||||
bagi pengguna yang kurang melihat. Pengguna tidak bisa memperbesar layar melewati lebar layar
|
||||
minimum <a href="http://developer.android.com/guide/topics/resources/providing-resources.html">
|
||||
sw320dp</a>, yang merupakan lebar Nexus 4, yakni ponsel ukuran sedang pada umumnya.
|
||||
</p>
|
||||
|
||||
<div class="cols">
|
||||
|
||||
<div class="col-6">
|
||||
<img src="{@docRoot}images/android-7.0/screen-zoom-1.png" alt="" height="XXX" id="figure1" />
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<img src="{@docRoot}images/android-7.0/screen-zoom-2.png" alt="" height="XXX" id="figure1" />
|
||||
</div>
|
||||
|
||||
</div> <!-- end cols -->
|
||||
<p class="img-caption">
|
||||
<strong>Gambar 3.</strong> Layar di sebelah kanan menampilkan efek
|
||||
penambahan Display size perangkat yang menjalankan citra sistem Android N.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
Bila kepadatan perangkat berubah, sistem akan memberi tahu aplikasi yang sedang berjalan dengan
|
||||
cara berikut:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Jika aplikasi menargetkan API level 23 atau yang lebih rendah, sistem secara otomatis akan mematikan
|
||||
semua proses latar belakang. Artinya, jika pengguna beralih dari
|
||||
aplikasi tersebut untuk membuka layar <em>Settings</em> dan mengubah
|
||||
setelan <strong>Display size</strong>, maka sistem akan mematikan aplikasi tersebut dengan cara yang
|
||||
sama dengan saat memori tinggal sedikit. Jika aplikasi memiliki beberapa proses
|
||||
latar depan, sistem akan memberi tahu proses tersebut mengenai perubahan konfigurasi seperti
|
||||
dijelaskan dalam <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani Perubahan
|
||||
Waktu Proses</a>, seolah-olah orientasi perangkat telah berubah.
|
||||
</li>
|
||||
|
||||
<li>Jika sebuah aplikasi menargetkan Android N, semua prosesnya
|
||||
(latar depan dan latar belakang) akan diberi tahu mengenai perubahan konfigurasi seperti
|
||||
dijelaskan dalam <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani Perubahan
|
||||
Waktu Proses</a>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Sebagian besar aplikasi tidak perlu melakukan perubahan untuk mendukung fitur ini, asalkan
|
||||
aplikasi tersebut mengikuti praktik terbaik Android. Hal-hal tertentu yang harus diperiksa:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Uji aplikasi Anda pada perangkat dengan lebar layar <code><a href=
|
||||
"{@docRoot}guide/topics/resources/providing-resources.html">sw320dp</a></code>
|
||||
dan pastikan aplikasi berjalan dengan semestinya.
|
||||
</li>
|
||||
|
||||
<li>Bila konfigurasi perangkat berubah, perbarui informasi cache
|
||||
yang bergantung pada kepadatan, seperti bitmap di cache atau sumber daya yang dimuat dari
|
||||
jaringan. Periksa perubahan konfigurasi bila aplikasi melanjutkan dari status dihentikan
|
||||
sementara.
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Catatan: Jika Anda meng-cache data yang bergantung pada konfigurasi, ada
|
||||
baiknya untuk menyertakan metadata yang relevan seperti ukuran layar
|
||||
atau kepadatan piksel yang sesuai untuk data tersebut. Menyimpan metadata ini memungkinkan Anda untuk
|
||||
memutuskan apakah Anda perlu segarkan data cache setelah perubahan
|
||||
konfigurasi.
|
||||
</p>
|
||||
</li>
|
||||
|
||||
<li>Hindari menetapkan dimensi dengan satuan px, karena satuan ini tidak diskalakan dengan
|
||||
kepadatan layar. Sebagai gantinya, tetapkan dimensi dengan satuan <a href="{@docRoot}guide/practices/screens_support.html">piksel yang tidak bergantung kepadatan
|
||||
</a> (<code>dp</code>).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="vision-settings">Vision Settings di Setup Wizard</h3>
|
||||
|
||||
<p>
|
||||
Android N menyertakan Vision Settings di layar Sambutan, di mana pengguna bisa
|
||||
menyiapkan setelan aksesibilitas berikut pada perangkat baru:
|
||||
<strong>Magnification gesture</strong>, <strong>Font size</strong>,
|
||||
<strong>Display size</strong> dan <strong>TalkBack</strong>. Perubahan ini
|
||||
meningkatkan visibilitas bug terkait dengan setelan layar yang berbeda. Untuk
|
||||
mengurangi dampak fitur ini, Anda harus menguji aplikasi dengan setelan ini
|
||||
diaktifkan. Anda bisa menemukannya pada <strong>Settings >
|
||||
Accessibility</strong>.
|
||||
</p>
|
||||
|
||||
<h2 id="ndk">Penautan Aplikasi NDK ke Pustaka Platform</h2>
|
||||
|
||||
<p>
|
||||
Android N menyertakan perubahan ruang nama untuk mencegah pemuatan API non-publik.
|
||||
Jika menggunakan NDK, Anda hanya boleh menggunakan API publik dari platform
|
||||
Android. Menggunakan API non-publik dalam rilis Android resmi berikutnya
|
||||
bisa menyebabkan aplikasi mogok.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Untuk memberi tahu Anda agar menggunakan API non-publik, aplikasi yang berjalan pada perangkat
|
||||
Android N akan menghasilkan kesalahan dalam keluaran logcat bila aplikasi memanggil API non-publik.
|
||||
Kesalahan ini juga ditampilkan di layar perangkat berupa pesan untuk membantu
|
||||
meningkatkan kepedulian terhadap situasi ini. Anda harus memeriksa kode aplikasi untuk
|
||||
membuang penggunaan API platform non-publik dan secara saksama menguji aplikasi Anda menggunakan
|
||||
perangkat pratinjau atau emulator.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Jika aplikasi Anda bergantung pada pustaka platform, lihat dokumentasi NDK untuk
|
||||
perbaikan tipikal guna menggantikan API privat umum dengan padanan API publik.
|
||||
Anda mungkin juga menautkan ke pustaka platform tanpa menyadarinya,
|
||||
terutama jika aplikasi Anda menggunakan pustaka yang merupakan bagian dari platform ini (seperti
|
||||
<code>libpng</code>), namun bukan bagian dari NDK. Dalam hal itu, pastikan
|
||||
APK Anda berisi semua file .so yang ingin ditautkan.
|
||||
</p>
|
||||
|
||||
<p class="caution">
|
||||
<strong>Perhatian:</strong> Beberapa pustaka pihak ketiga mungkin menautkan ke API
|
||||
non-publik. Jika menggunakan pustaka ini, aplikasi Anda bisa mogok saat dijalankan
|
||||
pada rilis resmi Android berikutnya.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Aplikasi tidak boleh bergantung pada atau menggunakan pustaka bawaan yang tidak disertakan dalam
|
||||
NDK, karena bisa mengalami perubahan, atau dipindahkan dari satu rilis Android ke
|
||||
rilis lainnya. Peralihan dari OpenSSL ke BoringSSL merupakan satu contoh dari perubahan semacam ini.
|
||||
Selain itu, perangkat yang berbeda bisa menawarkan tingkat kompatibilitas yang berbeda, karena
|
||||
tidak ada persyaratan kompatibilitas untuk pustaka platform yang tidak disertakan
|
||||
dalam NDK. Jika Anda harus mengakses pustaka non-NDK pada perangkat yang lebih lama, jadikan
|
||||
pemuatan bergantung pada level Android API.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Untuk membantu Anda mendiagnosis tipe masalah ini ada beberapa contoh kesalahan Java dan NDK
|
||||
yang mungkin Anda temui saat berusaha membangun aplikasi dengan Android N:
|
||||
</p>
|
||||
|
||||
<p>Contoh kesalahan Java:</p>
|
||||
<pre class="no-pretty-print">
|
||||
java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libcutils.so"
|
||||
is not accessible for the namespace "classloader-namespace"
|
||||
</pre>
|
||||
|
||||
<p>Contoh kesalahan NDK:</p>
|
||||
<pre class="no-pretty-print">
|
||||
dlopen failed: cannot locate symbol "__system_property_get" referenced by ...
|
||||
</pre>
|
||||
|
||||
|
||||
<p>
|
||||
Inilah beberapa perbaikan tipikal untuk aplikasi yang mengalami tipe kesalahan ini:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Penggunaan getJavaVM dan getJNIEnv dari libandroid_runtime.so bisa diganti
|
||||
dengan fungsi JNI standar:
|
||||
<pre class="no-pretty-print">
|
||||
AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
|
||||
AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
|
||||
JavaVM::AttachCurrentThread from <jni.h>.
|
||||
</pre>
|
||||
</li>
|
||||
|
||||
<li>Penggunaan simbol {@code property_get} dari {@code libcutils.so} bisa
|
||||
diganti dengan {@code alternative __system_property_get} publik.
|
||||
Caranya, gunakan {@code __system_property_get} dengan menyertakan yang berikut:
|
||||
<pre>
|
||||
#include <sys/system_properties.h>
|
||||
</pre>
|
||||
</li>
|
||||
|
||||
<li>Penggunaan simbol {@code SSL_ctrl} dari {@code libcrypto.so} harus
|
||||
diganti dengan aplikasi versi lokal. Misalnya, Anda harus menautkan
|
||||
{@code libcyrpto.a} secara statis dalam file {@code .so} atau menyertakan
|
||||
{@code libcrypto.so} Anda sendiri secara dinamis dari BoringSSL atau OpenSSL dalam aplikasi Anda.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="afw">Android for Work</h2>
|
||||
<p>
|
||||
Android N berisi perubahan untuk aplikasi yang menargetkan Android for Work, termasuk
|
||||
perubahan pada pemasangan sertifikat, penyetelan ulang sandi, manajemen pengguna
|
||||
tambahan, dan akses ke identifier perangkat. Jika Anda membangun aplikasi untuk
|
||||
lingkungan Android for Work, Anda harus meninjau perubahan ini dan memodifikasi
|
||||
aplikasi sebagaimana mestinya.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Anda harus pasang pemasang sertifikat yang didelegasikan sebelum DPC bisa
|
||||
menyetelnya. Untuk aplikasi profil dan aplikasi pemilik perangkat yang menargetkan N SDK, Anda harus
|
||||
pasang pemasang sertifikat yang didelegasikan sebelum pengontrol kebijakan
|
||||
perangkat (DPC) memanggil
|
||||
<code>DevicePolicyManager.setCertInstallerPackage()</code>. Jika pemasang
|
||||
belum dipasang, sistem akan melontarkan
|
||||
<code>IllegalArgumentException</code>.
|
||||
</li>
|
||||
|
||||
<li>Pembatasan sandi penyetelan ulang untuk admin perangkat sekarang diterapkan ke pemilik
|
||||
profil. Admin perangkat tidak bisa lagi menggunakan
|
||||
{@code DevicePolicyManager.resetPassword()} untuk menghapus sandi atau mengubah
|
||||
sandi yang sudah disetel. Admin perangkat tetap bisa menyetel sandi, namun hanya
|
||||
bila perangkat belum memiliki sandi, PIN, atau pola.
|
||||
</li>
|
||||
|
||||
<li>Pemilik perangkat dan profil bisa mengelola akun meskipun pembatasan
|
||||
telah disetel. Pemilik perangkat dan pemilik profil bisa memanggil Account Management API
|
||||
sekalipun pembatasan pengguna <code>DISALLOW_MODIFY_ACCOUNTS</code> diberlakukan.
|
||||
</li>
|
||||
|
||||
<li>Pemilik perangkat bisa mengelola pengguna tambahan lebih mudah. Bila perangkat
|
||||
berjalan dalam mode pemilik perangkat, maka pembatasan <code>DISALLOW_ADD_USER</code>
|
||||
secara otomatis akan ditetapkan. Ini mencegah pengguna membuat pengguna tambahan yang
|
||||
tidak terkelola. Selain itu, <code>CreateUser()</code> dan
|
||||
<code>createAndInitializeUser()</code> metode tidak digunakan lagi; metode
|
||||
<code>DevicePolicyManager.createAndManageUser()</code> telah menggantikannya.
|
||||
</li>
|
||||
|
||||
<li>Pemilik perangkat bisa mengakses identifier perangkat. Pemilik perangkat bisa mengakses
|
||||
alamat MAC Wi-Fi dari perangkat, menggunakan
|
||||
<code>DevicePolicyManagewr.getWifiMacAddress()</code>. Jika Wi-Fi belum pernah
|
||||
diaktifkan pada perangkat tersebut, metode ini akan mengembalikan nilai {@code null}.
|
||||
</li>
|
||||
|
||||
<li>Setelan Mode Kerja mengontrol akses ke aplikasi kerja. Bila mode kerja tidak aktif, peluncur sistem
|
||||
akan menunjukkan aplikasi kerja tidak tersedia dengan membuat warnanya jadi abu-abu. Mengaktifkan kembali
|
||||
mode kerja akan memulihkan perilaku normal.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Untuk informasi selengkapnya tentang perubahan Android for Work di Android N, lihat
|
||||
<a href="{@docRoot}preview/features/afw.html">Pembaruan Android for Work</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="annotations">Retensi Anotasi</h2>
|
||||
|
||||
<p>
|
||||
Android N memperbaiki bug dengan visibilitas anotasi diabaikan.
|
||||
Masalah ini mengaktifkan waktu proses untuk mengakses anotasi yang seharusnya tidak bisa
|
||||
dilakukan. Anotasi ini termasuk:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>{@code VISIBILITY_BUILD}: Dimaksudkan agar hanya bisa terlihat pada waktu pembuatan.</li>
|
||||
<li>{@code VISIBILITY_SYSTEM}: Dimaksud agar bisa terlihat pada waktu proses, namun hanya pada
|
||||
sistem yang mendasarinya.</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Jika aplikasi Anda mengandalkan perilaku ini, tambahkan kebijakan retensi untuk anotasi yang harus
|
||||
tersedia di waktu proses. Caranya dengan menggunakan {@code @Retention(RetentionPolicy.RUNTIME)}.
|
||||
</p>
|
||||
|
||||
<h2 id="other">Poin Penting Lainnya</h2>
|
||||
|
||||
<ul>
|
||||
<li>Bila aplikasi berjalan pada Android N, namun menargetkan level API yang lebih rendah,
|
||||
dan pengguna mengubah ukuran tampilan, proses aplikasi akan dimatikan. Aplikasi
|
||||
harus dapat menangani skenario ini dengan lancar. Jika tidak, maka akan mogok
|
||||
bila pengguna memulihkannya dari Recents.
|
||||
|
||||
<p>
|
||||
Anda harus menguji aplikasi untuk memastikan
|
||||
perilaku ini tidak terjadi.
|
||||
Anda bisa melakukannya dengan menyebabkan suatu mogok yang identik
|
||||
saat mematikan aplikasi secara manual melalui DDMS.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Aplikasi yang menargetkan N dan yang di atasnya tidak secara otomatis dimatikan saat perubahan kepadatan;
|
||||
akan tetapi, aplikasi tersebut mungkin tetap merespons perubahan konfigurasi dengan buruk.
|
||||
</p>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Aplikasi pada Android N harus mampu menangani perubahan konfigurasi dengan lancar,
|
||||
dan tidak boleh mengalami mogok pada start selanjutnya. Anda bisa memverifikasi perilaku aplikasi
|
||||
dengan mengubah ukuran font (<strong>Setting</strong> >
|
||||
<strong>Display</strong> > <strong>Font size</strong>), kemudian memulihkan
|
||||
aplikasi dari Recents.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Dikarenakan adanya bug di versi Android sebelumnya, sistem tidak menandai penulisan
|
||||
ke soket TCP di thread utama sebagai pelanggaran mode-ketat. Android N memperbaiki bug ini.
|
||||
Aplikasi yang menunjukkan perilaku ini kini melontarkan sebuah {@code android.os.NetworkOnMainThreadException}.
|
||||
Secara umum, melakukan operasi jaringan di thread utama tidak baik karena operasi ini
|
||||
biasanya memiliki latensi tinggi yang menyebabkan ANR dan jank.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Kelompok metode {@code Debug.startMethodTracing()} kini default ke
|
||||
keluaran penyimpanan di direktori paket tertentu di penyimpanan bersama,
|
||||
sebagai ganti di level teratas
|
||||
kartu SD. Berarti aplikasi tidak perlu lagi meminta izin {@code WRITE_EXTERNAL_STORAGE} untuk menggunakan API ini.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Banyak platform API yang kini mulai memeriksa beban besar yang dikirim
|
||||
ke seluruh transaksi {@link android.os.Binder}, dan sistem
|
||||
kini melontarkan kembali {@code TransactionTooLargeExceptions}
|
||||
sebagai {@code RuntimeExceptions}, sebagai ganti logging secara diam-diam atau menyembunyikannya. Satu contoh
|
||||
umum adalah menyimpan terlalu banyak data di
|
||||
{@link android.app.Activity#onSaveInstanceState Activity.onSaveInstanceState()},
|
||||
yang menyebabkan {@code ActivityThread.StopInfo} melontarkan
|
||||
{@code RuntimeException} bila aplikasi Anda menargetkan Android N.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Jika sebuah aplikasi mengeposkan tugas {@link java.lang.Runnable} ke{@link android.view.View}, dan
|
||||
{@link android.view.View}
|
||||
tidak terpasang ke jendela, sistem
|
||||
akan mengantrekan tugas {@link java.lang.Runnable} dengan {@link android.view.View};
|
||||
tugas {@link java.lang.Runnable} tidak akan dieksekusi hingga
|
||||
{@link android.view.View} terpasang
|
||||
ke jendela. Perilaku ini mengatasi bug berikut:
|
||||
<ul>
|
||||
<li>Jika sebuah aplikasi mengeposkan ke {@link android.view.View} dari thread selain thread UI jendela yang dimaksud,
|
||||
maka {@link java.lang.Runnable} mungkin akan menjalankan thread yang salah.
|
||||
</li>
|
||||
<li>Jika tugas {@link java.lang.Runnable} diposkan dari thread selain
|
||||
looper-thread, aplikasi bisa mengekspos tugas {@link java.lang.Runnable}.</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Jika sebuah aplikasi di Android N dengan
|
||||
izin{@link android.Manifest.permission#DELETE_PACKAGES DELETE_PACKAGES}
|
||||
mencoba menghapus sebuah paket, namun sebuah aplikasi berbeda telah memasang paket itu,
|
||||
sistem akan memerlukan konfirmasi pengguna. Dalam skenario ini, aplikasi harus mengharapkan
|
||||
{@link android.content.pm.PackageInstaller#STATUS_PENDING_USER_ACTION STATUS_PENDING_USER_ACTION}
|
||||
sebagai status kembalian bila memanggil
|
||||
{@link android.content.pm.PackageInstaller#uninstall PackageInstaller.uninstall()}.
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
page.title=Contoh
|
||||
page.tags="preview", "samples", "android"
|
||||
page.image=images/cards/card-n-samples_2x.png
|
||||
@jd:body
|
||||
|
||||
<p>
|
||||
Contoh kode berikut disediakan untuk Android N. Untuk
|
||||
mengunduh contoh di Android Studio, pilih opsi menu <b>File > Import
|
||||
Samples</b>.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Proyek yang bisa diunduh ini didesain
|
||||
untuk digunakan bersama Gradle dan Android Studio.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="mw">Playground Multi-Jendela</h3>
|
||||
<img src="{@docRoot}images/android-7.0/sample-multiwindow.png" style="float: left; padding-right: 0.5em" height="250" width="156" />
|
||||
<p>
|
||||
Contoh ini memperagakan cara memanfaatkan antarmuka pengguna
|
||||
multi-jendela bersama aplikasi Anda.
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/googlesamples/android-MultiWindowPlayground">
|
||||
Dapatkan di GitHub</a>
|
||||
</p>
|
||||
|
||||
<div style="clear: both;"></div>
|
||||
<h3 id="an">Pemberitahuan Aktif</h3>
|
||||
<img src="{@docRoot}images/android-7.0/sample-activenotifications.png" style="float: left; padding-right: 0.5em" height="250" width="141" />
|
||||
<p>
|
||||
Ini adalah contoh yang sudah ada sebelumnya, menampilkan layanan sederhana yang mengirimkan
|
||||
pemberitahuan menggunakan NotificationCompat. Setiap percakapan yang belum dibaca dari pengguna
|
||||
dikirimkan sebagai pemberitahuan berbeda.
|
||||
</p>
|
||||
<p>
|
||||
Contoh ini telah diperbarui untuk memanfaatkan fitur pemberitahuan baru
|
||||
yang tersedia di Android N.
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/googlesamples/android-ActiveNotifications">
|
||||
Dapatkan di GitHub</a>
|
||||
</p>
|
||||
|
||||
<div style="clear: both;"></div>
|
||||
<h3 id="ms">Layanan Perpesanan</h3>
|
||||
<img src="{@docRoot}images/android-7.0/sample-messagingservice.png" style="float: left; padding-right: 0.5em" height="250" width="150" />
|
||||
<p>
|
||||
Ini adalah contoh yang telah ada sebelumnya yang memperagakan cara menggunakan
|
||||
NotificationManager untuk memberi tahu jumlah pemberitahuan yang saat ini ditampilkan
|
||||
oleh aplikasi.
|
||||
</p>
|
||||
<p>
|
||||
Contoh ini telah diperbarui untuk memanfaatkan fitur pemberitahuan baru
|
||||
yang tersedia di Android N.
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/googlesamples/android-MessagingService">
|
||||
Dapatkan di GitHub</a>
|
||||
</p>
|
||||
|
||||
<div style="clear: both;"></div>
|
||||
<h3 id="fbe">Direct Boot</h3>
|
||||
<img src="{@docRoot}images/android-7.0/sample-directboot.png" style="float: left; padding-right: 0.5em" height="250" width="141" />
|
||||
<p>
|
||||
Contoh ini memperagakan cara menyimpan dan mengakses data dalam penyimpanan yang dienkripsi
|
||||
dengan perangkat yang selalu tersedia saat perangkat booting.
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/googlesamples/android-DirectBoot">
|
||||
Dapatkan di GitHub</a>
|
||||
</p>
|
||||
|
||||
<div style="clear: both;"></div>
|
||||
<h3 id="sda">Scoped Directory Access</h3>
|
||||
<img src="{@docRoot}images/android-7.0/sample-scopeddirectoryaccess.png" style="float: left; padding-right: 0.5em" height="250" width="141" />
|
||||
<p>
|
||||
Contoh ini memperagakan cara membaca dan menulis data dari direktori
|
||||
spesifik, sekaligus meminta izin lebih sedikit.
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/googlesamples/android-ScopedDirectoryAccess">
|
||||
Dapatkan di GitHub</a>
|
||||
</p>
|
||||
1039
docs/html-intl/intl/id/about/versions/nougat/android-7.0.jd
Normal file
1039
docs/html-intl/intl/id/about/versions/nougat/android-7.0.jd
Normal file
File diff suppressed because it is too large
Load Diff
110
docs/html-intl/intl/id/about/versions/nougat/index.jd
Normal file
110
docs/html-intl/intl/id/about/versions/nougat/index.jd
Normal file
@@ -0,0 +1,110 @@
|
||||
page.title=Android 7.0 Nougat
|
||||
page.tags="androidn","versions"
|
||||
meta.tags="android n", "nougat", "android 7.0"
|
||||
fullpage=true
|
||||
forcelocalnav=true
|
||||
header.hide=1
|
||||
footer.hide=1
|
||||
@jd:body
|
||||
|
||||
<section class="dac-expand dac-hero dac-light">
|
||||
<div class="wrap" style="max-width:1100px;margin-top:0">
|
||||
<a href="{@docRoot}about/versions/nougat/android-7.0.html">
|
||||
<div class="cols dac-hero-content" style="padding-bottom:1em;">
|
||||
|
||||
<div class="col-7of16 col-push-8of16" style="padding-left:2em">
|
||||
<h1 class="dac-hero-title">Android 7.0 Nougat</h1>
|
||||
<p class="dac-hero-description">
|
||||
Bersiaplah menyambut Android Nougat!
|
||||
<strong>Uji aplikasi Anda</strong> pada perangkat Nexus dan perangkat lainnya. Dukung perilaku sistem
|
||||
baru untuk <strong>menghemat daya dan memori</strong>.
|
||||
Tambah aplikasi Anda dengan <strong>UI multi-jendela</strong>,
|
||||
<strong>pemberitahuan balasan langsung</strong> dan lainnya.
|
||||
</p>
|
||||
|
||||
<a class="dac-hero-cta" href="{@docRoot}about/versions/nougat/android-7.0.html">
|
||||
<span class="dac-sprite dac-auto-chevron"></span>
|
||||
Mulai
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-7of16 col-pull-6of16 dac-hero-figure" style="margin-top:1.5em;padding-right:1.5em;">
|
||||
<a href="{@docRoot}about/versions/nougat/android-7.0.html">
|
||||
<img class="dac-hero-image" src="{@docRoot}images/home/n-preview-hero.png"
|
||||
srcset="{@docRoot}images/home/n-preview-hero.png 1x,
|
||||
{@docRoot}images/home/n-preview-hero_2x.png 2x" />
|
||||
</a>
|
||||
</div>
|
||||
</div></a>
|
||||
<div class="dac-section dac-small">
|
||||
<div class="resource-widget resource-flow-layout col-16"
|
||||
data-query="collection:nougat/landing/resources"
|
||||
data-cardSizes="6x2"
|
||||
data-maxResults="3"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<div class="dac-section dac-slim dac-gray dac-expand">
|
||||
<div class="wrap dac-offset-parent">
|
||||
<a class="dac-fab dac-scroll-button" data-scroll-button href="#latest">
|
||||
<i class="dac-sprite dac-arrow-down-gray"></i>
|
||||
</a>
|
||||
<ul class="dac-actions">
|
||||
<li class="dac-action">
|
||||
<a class="dac-action-link" href="https://source.android.com/source/report-bugs.html">
|
||||
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
|
||||
Laporkan masalah
|
||||
</a>
|
||||
</li>
|
||||
<li class="dac-action">
|
||||
<a class="dac-action-link" href="{@docRoot}preview/dev-community">
|
||||
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
|
||||
Bergabunglah dengan komunitas pengembang
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!-- end .wrap -->
|
||||
</div><!-- end .dac-actions -->
|
||||
|
||||
<section class="dac-section dac-light dac-small" id="latest"><div class="wrap">
|
||||
<h2 class="norule">Terbaru</h2>
|
||||
<div class="resource-widget resource-flow-layout col-16"
|
||||
data-query="type:blog+tag:androidn+tag:featured, type:youtube+tag:androidn+tag:featured"
|
||||
data-sortOrder="-timestamp"
|
||||
data-cardSizes="6x6"
|
||||
data-items-per-page="6"
|
||||
data-maxResults="15"
|
||||
data-initial-results="3"></div>
|
||||
</div></section>
|
||||
|
||||
<section class="dac-section dac-gray" id="videos"><div class="wrap">
|
||||
<h1 class="dac-section-title">Videos</h1>
|
||||
<div class="dac-section-subtitle">
|
||||
New Android capabilities and the right way to use them in your apps.
|
||||
</div>
|
||||
|
||||
<div class="resource-widget resource-flow-layout col-16"
|
||||
data-query="collection:nougat/landing/videos/first,type:youtube+tag:androidn"
|
||||
data-sortOrder="-timestamp"
|
||||
data-cardSizes="6x6"
|
||||
data-items-per-page="6"
|
||||
data-maxResults="15"
|
||||
data-initial-results="3">
|
||||
</div>
|
||||
</div></section>
|
||||
|
||||
<section class="dac-section dac-light" id="resources"><div class="wrap">
|
||||
<h1 class="dac-section-title">Sumber Daya</h1>
|
||||
<div class="dac-section-subtitle">
|
||||
Informasi penting guna membantu mempersiapkan aplikasi untuk Android Nougat.
|
||||
</div>
|
||||
|
||||
<div class="resource-widget resource-flow-layout col-16"
|
||||
data-query="collection:nougat/landing/more"
|
||||
data-cardSizes="6x6"
|
||||
data-items-per-page="6"
|
||||
data-maxResults="15"
|
||||
data-initial-results="6"></div>
|
||||
</div>
|
||||
</section>
|
||||
307
docs/html-intl/intl/id/design/get-started/principles.jd
Normal file
307
docs/html-intl/intl/id/design/get-started/principles.jd
Normal file
@@ -0,0 +1,307 @@
|
||||
page.title=Prinsip Desain Android
|
||||
@jd:body
|
||||
|
||||
<p>Prinsip desain ini dikembangkan oleh dan untuk Tim Pengalaman Pengguna
|
||||
Android agar selalu mempertimbangkan kepentingan pengguna.
|
||||
Untuk pengembang dan desainer Android, mereka terus
|
||||
meletakkan dasar pedoman desain yang lebih detail untuk beragam tipe
|
||||
perangkat.</p>
|
||||
|
||||
<p>
|
||||
Perhatikan prinsip-prinsip ini saat Anda menerapkan
|
||||
kreativitas dan pemikiran desain sendiri. Menyimpang dengan sengaja.
|
||||
</p>
|
||||
|
||||
<h2 id="enchant-me">Pikat Saya</h2>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="delight-me">Senangkan saya dengan cara yang mengejutkan</h4>
|
||||
<p>Permukaan yang cantik, animasi yang ditempatkan dengan hati-hati, atau efek suara di saat yang tepat sungguh menyenangkan untuk
|
||||
dinikmati. Efek yang lembut menimbulkan perasaan serba mudah dan kesadaran bahwa kekuatan yang
|
||||
bisa diandalkan ada dalam genggaman.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_delight.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="real-objects-more-fun">Objek sungguhan lebih menyenangkan daripada tombol dan menu</h4>
|
||||
<p>Biarkan orang langsung menyentuh dan memanipulasi objek dalam aplikasi Anda. Ini mengurangi upaya kognitif
|
||||
yang diperlukan untuk menjalankan tugas sekaligus membuatnya lebih memuaskan secara emosional.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_real_objects.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="make-it-mine">Biarkan saya memilikinya</h4>
|
||||
<p>Orang suka menambahkan sentuhan pribadi karena membantu mereka merasa betah dan memegang kendali. Memberikan
|
||||
default yang pantas dan indah, tetapi juga mempertimbangkan penyesuaian opsional yang menyenangkan, yang tidak mengganggu
|
||||
tugas utama.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_make_it_mine.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="get-to-know-me">Kenali saya</h4>
|
||||
<p>Pelajari preferensi orang dari waktu ke waktu. Daripada meminta mereka untuk membuat pilihan yang sama
|
||||
berulang-ulang, tempatkan pilihan sebelumnya agar mudah dijangkau.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_get_to_know_me.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 id="simplify-my-life">Sederhanakan Hidup Saya</h2>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="keep-it-brief">Persingkat</h4>
|
||||
<p>Gunakan frasa pendek dengan kata-kata sederhana. Orang cenderung melewatkan kalimat-kalimat panjang.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_keep_it_brief.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="pictures-faster-than-words">Gambar lebih cepat dibanding kata-kata</h4>
|
||||
<p>Pertimbangkan menggunakan gambar untuk menjelaskan gagasan. Gambar menarik perhatian orang dan bisa jauh lebih efisien
|
||||
dibanding kata-kata.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_pictures.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="decide-for-me">Putuskan untuk saya tetapi biarkan saya yang menentukan</h4>
|
||||
<p>Gunakan tebakan terbaik Anda dan bertindaklah daripada meminta terlebih dahulu. Terlalu banyak pilihan dan keputusan membuat orang
|
||||
tidak suka. Untuk berjaga-jaga jika Anda salah, izinkan 'pembatalan'.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_decide_for_me.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="only-show-when-i-need-it">Cukup tunjukkan yang saya perlukan ketika saya memerlukannya</h4>
|
||||
<p>Orang merasa kewalahan ketika melihat terlalu banyak hal sekaligus. Uraikan tugas dan informasi menjadi potongan-potongan
|
||||
kecil yang mudah dicerna. Sembunyikan opsi yang tidak perlu pada saat ini, dan ajari orang sambil jalan.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_information_when_need_it.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="always-know-where-i-am">Saya harus selalu tahu di mana saya berada</h4>
|
||||
<p>Beri orang kepercayaan diri bahwa mereka tahu di mana berada. Buat agar tempat-tempat dalam aplikasi Anda terlihat berbeda dan
|
||||
gunakan transisi untuk menunjukkan hubungan antar layar. Berikan umpan balik tentang tugas yang sedang berlangsung.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_navigation.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="never-lose-my-stuff">Jangan sekali-kali menghilangkan milik saya</h4>
|
||||
<p>Simpan apa yang telah susah-payah dibuat orang dan biarkan mereka mengaksesnya dari mana saja. Ingat pengaturan,
|
||||
sentuhan pribadi, dan kreasi lintas ponsel, tablet, dan komputer. Itu membuat pemutakhiran menjadi
|
||||
hal termudah di dunia.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_never_lose_stuff.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="looks-same-should-act-same">Jika terlihat sama, seharusnya fungsinya sama</h4>
|
||||
<p>Bantu orang merasakan perbedaan fungsional dengan membuat mereka terlihat berbeda daripada mirip.
|
||||
Hindari mode, yaitu tempat yang terlihat mirip tetapi berbeda fungsinya pada input yang sama.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_looks_same.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="interrupt-only-if-important">Sela saya jika penting saja</h4>
|
||||
<p>Layaknya asisten pribadi yang baik, lindungi orang dari detail yang tidak penting. Orang ingin tetap
|
||||
fokus, dan kecuali jika memang penting dan sensitif waktu, interupsi bisa melelahkan dan menjengkelkan.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_important_interruption.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 id="make-me-amazing">Buat Saya Terpesona</h2>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="give-me-tricks">Beri saya trik yang efektif di mana saja</h4>
|
||||
<p>Orang merasa senang ketika mereka memahami sendiri sesuatu. Jadikan aplikasi Anda lebih mudah dipelajari dengan
|
||||
memanfaatkan pola visual dan memori otot dari aplikasi Android lainnya. Misalnya, gerakan menggeser
|
||||
dapat menjadi pintasan navigasi yang bagus.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_tricks.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="its-not-my-fault">Bukan salah saya</h4>
|
||||
<p>Bersikap ramahlah dalam meminta orang untuk melakukan koreksi. Mereka ingin merasa pintar ketika menggunakan
|
||||
aplikasi Anda. Jika terjadi kesalahan, berikan petunjuk perbaikan yang jelas tetapi lepaskan mereka dari detail teknis.
|
||||
Jika Anda dapat memperbaikinya secara diam-diam, tentu lebih baik.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_error.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="sprinkle-encouragement">Berikan dorongan</h4>
|
||||
<p>Uraikan tugas-tugas rumit menjadi langkah-langkah kecil yang dapat dilakukan dengan mudah. Beri umpan balik tentang tindakan,
|
||||
meskipun hanya sesuatu yang sederhana.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_sprinkle_encouragement.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="do-heavy-lifting-for-me">Lakukan pekerjaan yang sulit untuk saya</h4>
|
||||
<p>Buatlah pemula merasa seperti ahli dengan memungkinkan mereka untuk melakukan hal-hal yang mereka pikir tidak akan bisa.
|
||||
Misalnya, pintasan yang menggabungkan beberapa efek foto dapat membuat foto amatir terlihat mengagumkan hanya
|
||||
dalam beberapa langkah.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_heavy_lifting.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vspace size-2"> </div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-7">
|
||||
|
||||
<h4 id="make-important-things-fast">Percepat hal penting</h4>
|
||||
<p>Tidak semua tindakan itu sama. Putuskan apa yang terpenting dalam aplikasi Anda dan permudah untuk menemukannya serta
|
||||
cepat untuk digunakan, seperti tombol rana pada kamera, atau tombol jeda pada pemutar musik.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
<img src="{@docRoot}design/media/principles_make_important_fast.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
186
docs/html-intl/intl/id/design/material/index.jd
Normal file
186
docs/html-intl/intl/id/design/material/index.jd
Normal file
@@ -0,0 +1,186 @@
|
||||
page.title=Material Design for Android
|
||||
page.tags=Material,design
|
||||
page.type=design
|
||||
page.image=images/cards/design-material-for-android_2x.jpg
|
||||
|
||||
@jd:body
|
||||
|
||||
<!-- developer docs box -->
|
||||
<a class="notice-developers right" href="{@docRoot}training/material/index.html">
|
||||
<div>
|
||||
<h3>Dokumen Pengembang</h3>
|
||||
<p>Membuat Aplikasi dengan Desain Bahan</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- video box -->
|
||||
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=p4gmvHyuZzw">
|
||||
<div>
|
||||
<h3>Video</h3>
|
||||
<p>Pengantar Desain Bahan</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- video box -->
|
||||
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=YaG_ljfzeUw">
|
||||
<div>
|
||||
<h3>Video</h3>
|
||||
<p>Kertas dan Tinta: Bahan Penting</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- video box -->
|
||||
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=XOcCOBe8PTc">
|
||||
<div>
|
||||
<h3>Video</h3>
|
||||
<p>Desain Bahan di Aplikasi Google I/O</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<p itemprop="description">Desain bahan adalah panduan komprehensif untuk desain visual, gerak, dan
|
||||
interaksi lintas platform dan perangkat. Android kini menyertakan dukungan untuk
|
||||
aplikasi desain bahan. Untuk menggunakan desain bahan di aplikasi Android, ikuti panduan yang didefinisikan
|
||||
dalam <a href="http://www.google.com/design/spec">spesifikasi desain bahan</a> dan gunakan
|
||||
komponen dan fungsionalitas baru yang tersedia di Android 5.0 (API level 21) ke atas.</p>
|
||||
|
||||
<p>Android menyediakan elemen berikut untuk membangun aplikasi desain bahan:</p>
|
||||
|
||||
<ul>
|
||||
<li>Tema baru</li>
|
||||
<li>Widget baru untuk tampilan yang kompleks</li>
|
||||
<li>API baru untuk animasi dan bayangan custom</li>
|
||||
</ul>
|
||||
|
||||
<p>Untuk informasi selengkapnya tentang mengimplementasikan desain bahan pada Android, lihat
|
||||
<a href="{@docRoot}training/material/index.html">Membuat Aplikasi dengan Desain Bahan</a>.</p>
|
||||
|
||||
|
||||
<h3>Tema Bahan</h3>
|
||||
|
||||
<p>Tema bahan menyediakan gaya baru untuk aplikasi Anda, widget sistem yang memungkinkan Anda mengatur
|
||||
palet warnanya, dan animasi default untuk umpan balik sentuh dan transisi aktivitas.</p>
|
||||
|
||||
<!-- two columns -->
|
||||
<div style="width:700px;margin-top:25px;margin-bottom:20px">
|
||||
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
|
||||
<img src="{@docRoot}design/material/images/MaterialDark.png" width="500" height="238" />
|
||||
<div style="width:140px;margin:0 auto">
|
||||
<p style="margin-top:8px">Tema bahan gelap</p>
|
||||
</div>
|
||||
</div>
|
||||
<div style="float:left;width:250px;margin-right:0px;">
|
||||
<img src="{@docRoot}design/material/images/MaterialLight.png" width="500" height="238" />
|
||||
<div style="width:140px;margin:0 auto">
|
||||
<p style="margin-top:8px">Tema bahan terang</p>
|
||||
</div>
|
||||
</div>
|
||||
<br style="clear:left"/>
|
||||
</div>
|
||||
|
||||
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/theme.html">Menggunakan Tema
|
||||
Bahan</a>.</p>
|
||||
|
||||
|
||||
<h3>Daftar dan Kartu</h3>
|
||||
|
||||
<p>Android menyediakan dua widget baru untuk menampilkan kartu dan daftar dengan gaya desain bahan
|
||||
dan animasi:</p>
|
||||
|
||||
<!-- two columns -->
|
||||
<div style="width:700px;margin-top:25px;margin-bottom:20px">
|
||||
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
|
||||
<img src="{@docRoot}design/material/images/list_mail.png" width="500" height="426" />
|
||||
<p>Widget <code>RecyclerView</code> baru adalah versi <code>ListView</code>
|
||||
yang lebih mudah dimasukkan dan mendukung beragam tipe layout serta memberikan peningkatan kinerja.</p>
|
||||
</div>
|
||||
<div style="float:left;width:250px;margin-right:0px;">
|
||||
<img src="{@docRoot}design/material/images/card_travel.png" width="500" height="426" />
|
||||
<p>Widget <code>CardView</code> baru memungkinkan Anda menampilkan potongan informasi penting dalam
|
||||
kartu yang memiliki tampilan dan cara kerja yang konsisten.</p>
|
||||
</div>
|
||||
<br style="clear:left"/>
|
||||
</div>
|
||||
|
||||
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/lists-cards.html">Membuat Daftar
|
||||
dan Kartu</a>.</p>
|
||||
|
||||
|
||||
<h3>Bayangan Tampilan</h3>
|
||||
|
||||
<p>Selain properti X dan Y, tampilan di Android kini memiliki
|
||||
properti Z. Properti baru ini mewakili ketinggian tampilan, yang menentukan:</p>
|
||||
|
||||
<ul>
|
||||
<li>Ukuran bayangan: tampilan dengan nilai Z lebih tinggi menghasilkan bayangan lebih besar.</li>
|
||||
<li>Urutan penggambaran: tampilan dengan nilai Z lebih tinggi muncul di atas tampilan lainnya.</li>
|
||||
</ul>
|
||||
|
||||
<div style="width:290px;margin-left:35px;float:right">
|
||||
<div class="framed-nexus5-port-span-5">
|
||||
<video class="play-on-hover" autoplay>
|
||||
<source src="{@docRoot}design/material/videos/ContactsAnim.mp4"/>
|
||||
<source src="{@docRoot}design/videos/ContactsAnim.webm"/>
|
||||
<source src="{@docRoot}design/videos/ContactsAnim.ogv"/>
|
||||
</video>
|
||||
</div>
|
||||
<div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
|
||||
<em>Untuk memutar ulang film, klik layar perangkat</em>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/shadows-clipping.html">Mendefinisikan
|
||||
Bayangan dan Memangkas Tampilan</a>.</p>
|
||||
|
||||
|
||||
<h3>Animasi</h3>
|
||||
|
||||
<p>API animasi baru memungkinkan Anda membuat animasi custom untuk umpan balik sentuh dalam kontrol UI,
|
||||
perubahan status tampilan, dan transisi aktivitas.</p>
|
||||
|
||||
<p>API ini memungkinkan Anda:</p>
|
||||
|
||||
<ul>
|
||||
<li style="margin-bottom:15px">
|
||||
Merespons kejadian sentuh dalam tampilan Anda dengan animasi <strong>umpan balik sentuh</strong>.
|
||||
</li>
|
||||
<li style="margin-bottom:15px">
|
||||
Menyembunyikan dan memperlihatkan tampilan dengan animasi <strong>membuka melingkar</strong>.
|
||||
</li>
|
||||
<li style="margin-bottom:15px">
|
||||
Peralihan antar aktivitas dengan animasi <strong>transisi aktivitas</strong> custom.
|
||||
</li>
|
||||
<li style="margin-bottom:15px">
|
||||
Membuat animasi yang lebih alami dengan <strong>gerak melengkung</strong>.
|
||||
</li>
|
||||
<li style="margin-bottom:15px">
|
||||
Menganimasikan perubahan dalam satu atau beberapa properti tampilan dengan animasi <strong>perubahan status tampilan</strong>.
|
||||
</li>
|
||||
<li style="margin-bottom:15px">
|
||||
Menampilkan animasi di <strong>drawable daftar status</strong> di antara perubahan status tampilan.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Animasi umpan balik sentuh dimasukkan ke dalam beberapa tampilan standar, misalnya tombol. API baru
|
||||
ini memungkinkan Anda menyesuaikan animasi ini dan menambahkannya ke tampilan custom Anda.</p>
|
||||
|
||||
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/animations.html">Mendefinisikan Animasi
|
||||
Custom</a>.</p>
|
||||
|
||||
|
||||
<h3>Drawable</h3>
|
||||
|
||||
<p>Kemampuan baru untuk drawable ini membantu Anda mengimplementasikan aplikasi desain bahan:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong>Drawable vektor</strong> bisa diubah skalanya tanpa kehilangan definisi dan cocok
|
||||
untuk ikon satu-warna dalam-aplikasi.</li>
|
||||
<li><strong>Pewarnaan drawable</strong> memungkinkan Anda mendefinisikan bitmap sebagai alpha-mask dan mewarnainya
|
||||
saat runtime.</li>
|
||||
<li><strong>Ekstraksi warna</strong> memungkinkan Anda mengekstrak warna mencolok secara otomatis dari
|
||||
gambar bitmap.</li>
|
||||
</ul>
|
||||
|
||||
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/drawables.html">Bekerja dengan
|
||||
Drawable</a>.</p>
|
||||
70
docs/html-intl/intl/id/design/patterns/compatibility.jd
Normal file
70
docs/html-intl/intl/id/design/patterns/compatibility.jd
Normal file
@@ -0,0 +1,70 @@
|
||||
page.title=Kompatibilitas Mundur
|
||||
page.tags="support"
|
||||
page.metaDescription=Catatan tentang bagaimana Android 4.x menyesuaikan UI yang didesain untuk perangkat keras dan versi OS yang lebih lama.
|
||||
@jd:body
|
||||
|
||||
<a class="notice-developers" href="{@docRoot}training/basics/supporting-devices/index.html">
|
||||
<div>
|
||||
<h3>Dokumen Pengembang</h3>
|
||||
<p>Mendukung Perangkat Berbeda</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<p>Perubahan signifikan dalam Android 3.0 meliputi:</p>
|
||||
<ul>
|
||||
<li>Dihilangkannya tombol perangkat keras navigasi (Back, Menu, Search, Home) untuk membantu menangani navigasi
|
||||
melalui kontrol maya (Back, Home, Recents).</li>
|
||||
<li>Pola yang tangguh untuk penggunaan menu pada action-bar.</li>
|
||||
</ul>
|
||||
<p>Android 4.0 membawa perubahan ini untuk tablet dengan platform ponsel.</p>
|
||||
|
||||
<h2 id="older-hardware">Menyesuaikan Android 4.0 dengan Perangkat Keras dan Aplikasi yang Lebih Lama</h2>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-6">
|
||||
|
||||
<h4>Ponsel dengan kontrol navigasi virtual</h4>
|
||||
<p>Aplikasi Android yang ditulis untuk Android 3.0 dan yang lebih baru menampilkan tindakan dalam action-bar. Tindakan yang tidak
|
||||
muat dalam action-bar atau tidak cukup penting untuk ditampilkan di tingkat atas akan muncul dalam
|
||||
action-overflow.</p>
|
||||
<p>Pengguna mengakses action-overflow dengan menyentuhnya dalam action-bar.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-7">
|
||||
|
||||
<img src="{@docRoot}design/media/compatibility_virtual_nav.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-6">
|
||||
|
||||
<h4>Ponsel dengan tombol navigasi fisik</h4>
|
||||
<p>Ponsel Android dengan tombol perangkat keras navigasi biasa tidak menampilkan baris navigasi virtual di
|
||||
bagian bawah layar. Sebagai gantinya, action-overflow tersedia dari tombol perangkat keras menu. Popup
|
||||
tindakan yang dihasilkan memiliki gaya yang sama dengan contoh sebelumnya, tetapi ditampilkan di bagian bawah layar.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-7">
|
||||
|
||||
<img src="{@docRoot}design/media/compatibility_physical_buttons.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-6">
|
||||
|
||||
<h4>Aplikasi lama pada ponsel dengan kontrol navigasi virtual</h4>
|
||||
<p>Bila Anda menjalankan aplikasi yang dibuat untuk Android 2.3 atau yang lebih lama pada ponsel
|
||||
dengan kontrol navigasi virtual, sebuah kontrol action-overflow akan muncul di sebelah kanan baris navigasi virtual. Anda
|
||||
dapat menyentuh kontrol itu untuk menampilkan tindakan aplikasi dalam gaya menu Android biasa.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-7">
|
||||
|
||||
<img src="{@docRoot}design/media/compatibility_legacy_apps.png">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,70 @@
|
||||
page.title=Mengonfirmasi & Mengakui
|
||||
page.tags=dialog,toast,notification
|
||||
@jd:body
|
||||
|
||||
<p>Dalam beberapa situasi, bila pengguna memanggil suatu tindakan dalam aplikasi Anda, ada baiknya <em>mengonfirmasi</em> atau <em>mengakui</em> tindakan itu melalui teks.</p>
|
||||
|
||||
<div class="cols">
|
||||
<div class="col-6">
|
||||
<img src="{@docRoot}design/media/confirm_ack_confirming.png">
|
||||
<p><strong>Mengonfirmasi</strong> adalah meminta pengguna untuk memverifikasi bahwa mereka benar-benar ingin melanjutkan tindakan yang baru saja mereka panggil. Dalam beberapa kasus, konfirmasi ditampilkan bersama-sama dengan peringatan atau informasi penting yang terkait dengan tindakan yang perlu mereka pertimbangkan.</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<img src="{@docRoot}design/media/confirm_ack_acknowledge.png">
|
||||
<p><strong>Mengakui</strong> adalah menampilkan teks untuk memberi tahu pengguna bahwa tindakan yang baru mereka panggil sudah dilakukan. Ini menghilangkan ketidakpastian tentang operasi implisit yang dilakukan sistem. Dalam beberapa kasus, pengakuan ditampilkan bersama dengan opsi untuk membatalkan tindakan.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Berkomunikasi pada pengguna dengan cara ini bisa membantu mengurangi ketidakpastian tentang hal-hal yang sudah atau akan terjadi. Mengonfirmasi atau mengakui juga dapat mencegah pengguna melakukan kesalahan yang akan mereka sesali.</p>
|
||||
|
||||
<h2>Kapan Harus Mengonfirmasi atau Mengakui Tindakan Pengguna</h2>
|
||||
<p>Tidak semua tindakan memerlukan konfirmasi atau pengakuan. Gunakan bagan alur ini untuk memandu keputusan desain Anda.</p>
|
||||
<img src="{@docRoot}design/media/confirm_ack_flowchart.png">
|
||||
|
||||
<h2>Mengonfirmasi</h2>
|
||||
<div class="cols">
|
||||
<div class="col-6">
|
||||
<h4>Contoh: Google Play Books</h4>
|
||||
<img src="{@docRoot}design/media/confirm_ack_ex_books.png">
|
||||
<p>Dalam contoh ini, pengguna telah meminta untuk menghapus sebuah buku dari perpustakaan Google Play mereka. Sebuah <a href="{@docRoot}design/building-blocks/dialogs.html#alerts">peringatan</a> muncul untuk mengonfirmasi tindakan ini karena perlu dipahami bahwa buku tersebut tidak akan tersedia lagi dari perangkat apa pun.</p>
|
||||
<p>Saat membuat dialog konfirmasi, buat judul bermakna dengan mencerminkan tindakan yang diminta.</p>
|
||||
</div>
|
||||
<div class="col-7">
|
||||
<h4>Contoh: Android Beam</h4>
|
||||
<img src="{@docRoot}design/media/confirm_ack_ex_beam.png">
|
||||
<p>Konfirmasi tidak harus ditampilkan dalam peringatan dengan dua tombol. Setelah menjalankan Android Beam, pengguna diminta untuk menyentuh konten yang akan dibagikan (dalam contoh ini, sebuah foto). Jika mereka memutuskan untuk tidak melanjutkan, mereka tinggal memindahkan ponsel.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Mengakui</h2>
|
||||
<div class="cols">
|
||||
<div class="col-6">
|
||||
<h4>Contoh: Draf Gmail batal yang disimpan</h4>
|
||||
<img src="{@docRoot}design/media/confirm_ack_ex_draftsave.png">
|
||||
<p>Dalam contoh ini, jika pengguna menyusuri ke belakang atau ke atas dari layar pembuatan email di Gmail, sesuatu yang tak diharapkan bisa terjadi: draf saat itu akan disimpan secara otomatis. Pengakuan dalam bentuk pemberitahuan akan lebih jelas. Ini menghilang setelah beberapa detik.</p>
|
||||
<p>Pembatalan tidak cocok di sini karena penyimpanan dilakukan oleh aplikasi, bukan pengguna. Cepat dan mudah untuk melanjutkan penulisan pesan dengan menyusuri daftar draf.</p>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h4>Contoh: Percakapan Gmail dihapus</h4>
|
||||
<img src="{@docRoot}design/media/confirm_ack_draft_deleted.png">
|
||||
<p>Setelah pengguna menghapus percakapan dari daftar dalam Gmail, sebuah pengakuan muncul tanpa opsi pembatalan. Pengakuan tetap ada sampai pengguna melakukan tindakan yang tidak berkaitan, seperti menggulir daftar.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Tidak ada Konfirmasi atau Pengakuan</h2>
|
||||
<div class="cols">
|
||||
<div class="col-6">
|
||||
<h4>Contoh: memberikan +1</h4>
|
||||
<img style="padding: 33px 0 30px;" src="{@docRoot}design/media/confirm_ack_ex_plus1.png">
|
||||
<p><strong>Konfirmasi tidak diperlukan</strong>. Jika pengguna telah memberikan +1 secara tidak sengaja, tidak masalah. Mereka cukup menyentuh kembali tombol itu untuk membatalkan tindakan.</p>
|
||||
<p><strong>Pengakuan tidak diperlukan</strong>. Pengguna akan melihat tombol +1 memantul dan berubah merah. Itu tanda yang sangat jelas.</p>
|
||||
</div>
|
||||
<div class="col-7">
|
||||
<h4>Contoh: Menghapus aplikasi dari Layar Beranda</h4>
|
||||
<img src="{@docRoot}design/media/confirm_ack_ex_removeapp.png">
|
||||
<p><strong>Konfirmasi tidak diperlukan</strong>. Ini adalah tindakan yang disengaja: pengguna harus menyeret dan meletakkan sebuah item di atas target yang relatif besar dan terpisah. Karena itu, kecil kemungkinan terjadi ketidaksengajaan. Tetapi jika pengguna menyesali keputusan itu, maka hanya perlu beberapa detik untuk mengembalikannya lagi.</p>
|
||||
<p><strong>Pengakuan tidak diperlukan</strong>. Pengguna akan mengetahui bahwa aplikasi itu tidak ada di Layar Beranda karena mereka menghilangkannya dengan cara menyeretnya.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
213
docs/html-intl/intl/id/design/patterns/navigation.jd
Normal file
213
docs/html-intl/intl/id/design/patterns/navigation.jd
Normal file
@@ -0,0 +1,213 @@
|
||||
page.title=Navigasi dengan Back dan Up
|
||||
page.tags="navigation","activity","task","up navigation","back navigation"
|
||||
page.image=/design/media/navigation_between_siblings_gmail.png
|
||||
@jd:body
|
||||
|
||||
<a class="notice-developers" href="{@docRoot}training/implementing-navigation/index.html">
|
||||
<div>
|
||||
<h3>Dokumen Pengembang</h3>
|
||||
<p>Mengimplementasikan Navigasi yang Efektif</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<p itemprop="description">Navigasi yang konsisten merupakan komponen penting dari keseluruhan pengalaman pengguna. Hampir tidak ada yang lebih membingungkan
|
||||
pengguna selain navigasi dasar yang perilakunya tidak konsisten dan tidak sesuai harapan. Android 3.0
|
||||
memperkenalkan perubahan besar dalam perilaku navigasi global. Mengikuti dengan saksama
|
||||
panduan untuk Back dan Up akan membuat navigasi aplikasi Anda dapat diprediksi dan dapat diandalkan pengguna.</p>
|
||||
<p>Android 2.3 dan versi sebelumnya mengandalkan tombol <em>Back</em> sistem untuk mendukung navigasi dalam
|
||||
aplikasi. Dengan diperkenalkannya action-bar dalam Android 3.0, mekanisme navigasi kedua muncul:
|
||||
tombol <em>Up</em>, yang terdiri dari ikon aplikasi dan tanda panah yang menunjuk ke kiri.</p>
|
||||
|
||||
<img src="{@docRoot}design/media/navigation_with_back_and_up.png">
|
||||
|
||||
<h2 id="up-vs-back">Up vs. Back</h2>
|
||||
|
||||
<p>Tombol Up digunakan untuk berpindah dalam aplikasi berdasarkan hubungan hierarki
|
||||
antar layar. Misalnya, jika layar A menampilkan daftar item, dan memilih sebuah item akan membuka
|
||||
layar B (yang menampilkan item tersebut secara lebih detail), maka layar B akan menawarkan tombol Up untuk
|
||||
kembali ke layar A.</p>
|
||||
<p>Jika suatu layar merupakan yang teratas dalam aplikasi (yaitu layar Home aplikasi), maka tidak perlu menampilkan tombol
|
||||
Up.</p>
|
||||
|
||||
<p>Tombol Back sistem digunakan untuk berpindah, dalam urutan kronologis terbalik, melalui riwayat
|
||||
layar yang baru dibuka oleh pengguna. Biasanya ini berdasarkan hubungan sementara
|
||||
antar layar, dan bukan hierarki aplikasi.</p>
|
||||
|
||||
<p>Bila layar yang dilihat sebelumnya juga merupakan induk hierarki dari layar yang sekarang, menekan tombol
|
||||
Back akan sama hasilnya dengan menekan tombol Up—ini adalah kejadian
|
||||
biasa. Akan tetapi, berbeda dengan tombol Up, yang memastikan pengguna tetap berada dalam aplikasi Anda, tombol Back
|
||||
dapat mengembalikan pengguna ke layar Home, atau bahkan ke aplikasi lain.</p>
|
||||
|
||||
<img src="{@docRoot}design/media/navigation_up_vs_back_gmail.png">
|
||||
|
||||
<p>Tombol Back juga mendukung beberapa perilaku yang tidak terkait langsung dengan navigasi antar layar:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Menghilangkan jendela mengambang (dialog, popup)</li>
|
||||
<li>Menghilangkan action-bar kontekstual, dan menghapus sorotan dari item yang dipilih</li>
|
||||
<li>Menyembunyikan keyboard di layar (IME)</li>
|
||||
</ul>
|
||||
<h2 id="within-app">Navigasi Dalam Aplikasi Anda</h2>
|
||||
|
||||
<h4>Berpindah ke layar yang memiliki beberapa titik masuk</h4>
|
||||
<p>Kadang-kadang layar tidak memiliki posisi pasti dalam hierarki aplikasi, dan bisa dimasuki
|
||||
dari berbagai titik masuk—seperti layar pengaturan yang dapat dibuka dari layar lain
|
||||
dalam aplikasi Anda. Dalam hal ini, tombol Up akan memilih untuk kembali ke layar pengarah, yang cara kerjanya
|
||||
sama dengan tombol Back.</p>
|
||||
<h4>Mengubah tampilan dalam layar</h4>
|
||||
<p>Mengubah opsi tampilan untuk layar tidak mengubah perilaku Up atau Back: layar tetap
|
||||
berada di tempat yang sama dalam hierarki aplikasi, dan tidak dibuat riwayat navigasi yang baru.</p>
|
||||
<p>Contoh perubahan tampilan tersebut adalah:</p>
|
||||
<ul>
|
||||
<li>Mengganti tampilan menggunakan tab dan/atau geser kiri dan kanan</li>
|
||||
<li>Mengubah tampilan menggunakan tarik-turun (alias tab turun)</li>
|
||||
<li>Memfilter daftar</li>
|
||||
<li>Menyortir daftar</li>
|
||||
<li>Mengubah karakteristik tampilan (seperti zoom)</li>
|
||||
</ul>
|
||||
<h4>Berpindah antar layar yang seinduk</h4>
|
||||
<p>Bila aplikasi Anda mendukung navigasi dari daftar item ke tampilan detail salah satu item tersebut, aplikasi
|
||||
juga sering diharapkan mendukung navigasi langsung dari item itu ke item sebelumnya atau
|
||||
sesudahnya dalam daftar. Misalnya, dalam Gmail, begitu mudah untuk bergeser ke kiri atau kanan dari sebuah percakapan
|
||||
untuk melihat percakapan yang lebih baru atau lebih lama dalam Inbox yang sama. Sama seperti saat mengubah tampilan dalam layar, navigasi
|
||||
ini tidak mengubah perilaku Up atau Back.</p>
|
||||
|
||||
<img src="{@docRoot}design/media/navigation_between_siblings_gmail.png">
|
||||
|
||||
<p>Akan tetapi, pengecualian khusus terhadap hal ini terjadi saat menjelajah di antara tampilan detail terkait yang tidak disatukan
|
||||
oleh daftar yang merujuknya—misalnya, saat menjelajahi Play Store di antara aplikasi dari
|
||||
pengembang yang sama, atau album dari artis yang sama. Dalam hal ini, mengikuti setiap tautan akan membuat
|
||||
riwayat, sehingga tombol Back akan menyusuri setiap layar yang dilihat sebelumnya. Tombol Up akan terus
|
||||
melewatkan semua layar terkait ini dan berpindah ke layar kontainer yang terakhir dilihat.</p>
|
||||
|
||||
<img src="{@docRoot}design/media/navigation_between_siblings_market1.png">
|
||||
|
||||
<p>Anda dapat menjadikan perilaku tombol Up lebih cerdas lagi berdasarkan pengetahuan Anda tentang tampilan
|
||||
detail. Dengan memperluas contoh Play Store dari atas, bayangkan pengguna yang telah berpindah dari Buku
|
||||
terakhir yang dilihat ke detail untuk adaptasi Film. Dalam hal itu, tombol Up dapat kembali ke kontainer
|
||||
(Movies) yang sebelumnya belum dilalui pengguna.</p>
|
||||
|
||||
<img src="{@docRoot}design/media/navigation_between_siblings_market2.png">
|
||||
|
||||
<h2 id="into-your-app">Navigasi ke Aplikasi Anda melalui Widget dan Pemberitahuan Layar Home</h2>
|
||||
|
||||
<p>Anda bisa menggunakan widget atau pemberitahuan layar Home untuk membantu pengguna berpindah langsung ke layar
|
||||
jauh dalam hierarki aplikasi Anda. Misalnya, widget Inbox dan pemberitahuan pesan baru di Gmail dapat
|
||||
melewatkan layar Inbox, dan membawa pengguna langsung ke tampilan percakapan.</p>
|
||||
|
||||
<p>Untuk kedua kasus ini, tangani tombol Up sebagai berikut:</p>
|
||||
|
||||
<ul>
|
||||
<li><em>Jika layar tujuan biasanya dicapai dari satu layar tertentu dalam aplikasi
|
||||
Anda</em>, tombol Up akan mengarahkannya ke layar itu.</li>
|
||||
<li><em>Jika tidak</em>, tombol Up akan mengarahkan ke layar teratas ("Home") dari aplikasi Anda.</li>
|
||||
</ul>
|
||||
|
||||
<p>Dalam hal tombol Back, Anda harus membuat navigasi lebih bisa diprediksi dengan menyisipkan ke dalam
|
||||
back-stack tugas path navigasi naik lengkap menuju layar teratas aplikasi. Ini memungkinkan pengguna
|
||||
yang lupa cara masuk ke aplikasi Anda untuk berpindah ke layar teratas aplikasi sebelum
|
||||
keluar.</p>
|
||||
|
||||
<p>Sebagai contoh, widget layar Home di Gmail memiliki tombol untuk menuju langsung ke layar
|
||||
Compose. Tombol Up atau Back dari layar Compose akan membawa pengguna ke Inbox, dan dari sana tombol
|
||||
Back berlanjut ke Home.</p>
|
||||
|
||||
<img src="{@docRoot}design/media/navigation_from_outside_back.png">
|
||||
|
||||
<h4>Pemberitahuan tidak langsung</h4>
|
||||
|
||||
<p>Jika aplikasi Anda perlu menampilkan informasi tentang beberapa kejadian sekaligus, aplikasi dapat menggunakan
|
||||
pemberitahuan tunggal yang mengarahkan pengguna ke layar antara. Layar ini merangkum semua
|
||||
kejadian tersebut, dan menyediakan path bagi pengguna untuk menjelajah ke dalam aplikasi. Pemberitahuan dengan gaya seperti ini
|
||||
disebut <em>pemberitahuan tidak langsung</em>.</p>
|
||||
|
||||
<p>Berbeda dengan pemberitahuan standar (langsung), menekan tombol Back dari
|
||||
layar antara pada pemberitahuan tidak langsung akan mengembalikan pengguna ke titik pemicu pemberitahuan tersebut—tidak ada
|
||||
layar tambahan yang disisipkan ke dalam back-stack. Setelah pengguna melanjutkan ke dalam aplikasi dari
|
||||
layar antara, tombol Up dan Back akan berperilaku seperti pada pemberitahuan standar, sebagaimana dijelaskan di atas:
|
||||
menyusuri ke dalam aplikasi dan bukan kembali ke layar antara.</p>
|
||||
|
||||
<p>Misalnya, anggaplah seorang pengguna di Gmail menerima pemberitahuan tidak langsung dari Kalender. Menyentuh
|
||||
pemberitahuan ini akan membuka layar antara, yang menampilkan pengingat beberapa macam
|
||||
kejadian. Menyentuh Back dari layar antara akan mengembalikan pengguna ke Gmail. Menyentuh kejadian
|
||||
tertentu akan membawa pengguna dari layar antara ke aplikasi Kalender lengkap untuk menampilkan detail
|
||||
kejadian. Dari detail kejadian, tombol Up dan Back akan mengarahkan ke tampilan Kalender tingkat atas.</p>
|
||||
|
||||
<img src="{@docRoot}design/media/navigation_indirect_notification.png">
|
||||
|
||||
<h4>Pemberitahuan pop-up</h4>
|
||||
|
||||
<p><em>Pemberitahuan pop-up</em> akan melewatkan laci pemberitahuan, bukan muncul secara langsung di
|
||||
hadapan pengguna. Ini jarang digunakan, dan <strong>harus dicadangkan untuk peristiwa yang memerlukan respons tepat waktu
|
||||
dan diperlukan interupsi dari konteks pengguna</strong>. Misalnya,
|
||||
Talk menggunakan gaya ini untuk memberi tahu pengguna tentang ajakan dari teman untuk bergabung dalam chatting video, karena
|
||||
ajakan ini akan kedaluwarsa secara otomatis setelah beberapa detik.</p>
|
||||
|
||||
<p>Dalam hal perilaku navigasi, pemberitahuan pop-up sangat mirip perilaku pemberitahuan
|
||||
tidak langsung pada layar antara. Tombol Back akan menghilangkan pemberitahuan pop-up. Jika pengguna berpindah
|
||||
dari pop-up ke aplikasi yang memberi tahu, tombol Up dan Back akan mengikuti aturan pemberitahuan standar,
|
||||
berpindah dalam aplikasi.</p>
|
||||
|
||||
<img src="{@docRoot}design/media/navigation_popup_notification.png">
|
||||
|
||||
<h2 id="between-apps">Navigasi Antar Aplikasi</h2>
|
||||
|
||||
<p>Salah satu kekuatan dasar sistem Android adalah kemampuan aplikasi untuk saling
|
||||
mengaktifkan, sehingga pengguna dapat berpindah langsung dari satu aplikasi ke aplikasi lainnya. Misalnya, sebuah
|
||||
aplikasi yang perlu mengambil foto dapat mengaktifkan aplikasi Kamera, yang akan mengembalikan foto
|
||||
ke aplikasi perujuk. Ini sangat menguntungkan pengembang, yang bisa dengan mudah memanfaatkan
|
||||
kode dari aplikasi lain, maupun pengguna, yang menikmati pengalaman konsisten untuk tindakan yang biasa
|
||||
dilakukan.</p>
|
||||
|
||||
<p>Untuk memahami navigasi antar aplikasi, maka perlu memahami perilaku kerangka kerja Android
|
||||
yang akan dibahas di bawah ini.</p>
|
||||
|
||||
<h4>Aktivitas, tugas, dan intent</h4>
|
||||
|
||||
<p>Dalam Android, <strong>aktivitas</strong> adalah komponen aplikasi yang mendefinisikan layar
|
||||
informasi dan semua tindakan terkait yang dapat dilakukan pengguna. Aplikasi Anda adalah kumpulan
|
||||
aktivitas, yang terdiri dari aktivitas yang Anda buat dan aktivitas yang Anda gunakan ulang dari aplikasi lain.</p>
|
||||
|
||||
<p><strong>Tugas</strong> adalah urutan aktivitas yang diikuti pengguna untuk mencapai tujuan.
|
||||
Tugas tunggal dapat memanfaatkan aktivitas dari satu aplikasi saja, atau dapat memanfaatkan aktivitas dari sejumlah
|
||||
aplikasi berbeda.</p>
|
||||
|
||||
<p><strong>Intent</strong> adalah mekanisme bagi satu aplikasi untuk memberi isyarat minta bantuan
|
||||
aplikasi lain dalam menjalankan suatu tindakan. Aktivitas aplikasi dapat menunjukkan intent
|
||||
apa saja yang dapat diresponsnya. Untuk intent umum seperti "Share", pengguna mungkin telah menginstal beberapa aplikasi
|
||||
yang dapat memenuhi permintaan itu.</p>
|
||||
|
||||
<h4>Contoh: berpindah antar aplikasi untuk mendukung berbagi</h4>
|
||||
|
||||
<p>Untuk memahami cara kerja sama aktivitas, tugas, dan intent, perhatikan bagaimana sebuah aplikasi memungkinkan pengguna
|
||||
untuk berbagi konten dengan menggunakan aplikasi lain. Misalnya, membuka aplikasi Play Store dari Home akan memulai
|
||||
Task A baru (lihat gambar di bawah). Setelah menyusuri Play Store dan menyentuh buku yang dipromosikan
|
||||
untuk melihat detailnya, pengguna tetap berada dalam tugas yang sama, memperluasnya dengan menambahkan aktivitas. Memicu
|
||||
tindakan Share akan memberi tahu pengguna dengan dialog berisi daftar aktivitas (dari aplikasi berbeda)
|
||||
yang telah terdaftar untuk menangani intent Share.</p>
|
||||
|
||||
<img src="{@docRoot}design/media/navigation_between_apps_inward.png">
|
||||
|
||||
<p>Bila pengguna memilih untuk berbagi melalui Gmail, aktivitas penulisan di Gmail akan ditambahkan sebagai kelanjutan dari
|
||||
Task A—tidak ada tugas baru yang dibuat. Jika Gmail sedang menjalankan tugasnya di latar belakang, maka
|
||||
tidak akan terpengaruh.</p>
|
||||
|
||||
<p>Dari aktivitas penulisan, mengirim pesan atau menyentuh tombol Back akan mengembalikan pengguna ke
|
||||
aktivitas detail buku tersebut. Penyentuhan tombol Back berikutnya akan terus mengarahkan kembali melalui Play
|
||||
Store, sampai akhirnya tiba di Home.</p>
|
||||
|
||||
<img src="{@docRoot}design/media/navigation_between_apps_back.png">
|
||||
|
||||
<p>Akan tetapi, dengan menyentuh tombol Up dari aktivitas penulisan, pengguna menunjukkan keinginan untuk tetap berada di
|
||||
Gmail. Aktivitas daftar percakapan Gmail muncul, Task B yang baru akan dibuat untuk itu. Tugas baru
|
||||
selalu terkait ke Home, maka menyentuh tombol Back dari daftar percakapan akan mengembalikan ke sana.</p>
|
||||
|
||||
<img src="{@docRoot}design/media/navigation_between_apps_up.png">
|
||||
|
||||
<p>Task A tetap berjalan di latar belakang, dan pengguna nanti dapat kembali ke sana (misalnya, melalui layar
|
||||
Recents). Jika Gmail sedang menjalankan tugasnya di latar belakang, maka itu akan digantikan
|
||||
dengan Task B—konteks sebelumnya akan diabaikan demi tujuan baru pengguna.</p>
|
||||
|
||||
<p>Jika register aplikasi Anda menangani intent dengan aktivitas yang jauh di dalam hierarki aplikasi,
|
||||
lihat <a href="#into-your-app">Navigasi Aplikasi Anda melalui Widget Layar Home dan
|
||||
Pemberitahuan</a> untuk panduan mengenai cara menetapkan navigasi Up.</p>
|
||||
756
docs/html-intl/intl/id/guide/components/activities.jd
Normal file
756
docs/html-intl/intl/id/guide/components/activities.jd
Normal file
@@ -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>
|
||||
-->
|
||||
658
docs/html-intl/intl/id/guide/components/bound-services.jd
Normal file
658
docs/html-intl/intl/id/guide/components/bound-services.jd
Normal file
@@ -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>
|
||||
|
||||
|
||||
|
||||
|
||||
812
docs/html-intl/intl/id/guide/components/fragments.jd
Normal file
812
docs/html-intl/intl/id/guide/components/fragments.jd
Normal file
@@ -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>
|
||||
|
||||
|
||||
480
docs/html-intl/intl/id/guide/components/fundamentals.jd
Normal file
480
docs/html-intl/intl/id/guide/components/fundamentals.jd
Normal file
@@ -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>
|
||||
|
||||
57
docs/html-intl/intl/id/guide/components/index.jd
Normal file
57
docs/html-intl/intl/id/guide/components/index.jd
Normal file
@@ -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>
|
||||
899
docs/html-intl/intl/id/guide/components/intents-filters.jd
Normal file
899
docs/html-intl/intl/id/guide/components/intents-filters.jd
Normal file
@@ -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>
|
||||
|
||||
|
||||
|
||||
|
||||
494
docs/html-intl/intl/id/guide/components/loaders.jd
Normal file
494
docs/html-intl/intl/id/guide/components/loaders.jd
Normal file
@@ -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>
|
||||
|
||||
411
docs/html-intl/intl/id/guide/components/processes-and-threads.jd
Normal file
411
docs/html-intl/intl/id/guide/components/processes-and-threads.jd
Normal file
@@ -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>
|
||||
-->
|
||||
256
docs/html-intl/intl/id/guide/components/recents.jd
Normal file
256
docs/html-intl/intl/id/guide/components/recents.jd
Normal file
@@ -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>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
813
docs/html-intl/intl/id/guide/components/services.jd
Normal file
813
docs/html-intl/intl/id/guide/components/services.jd
Normal file
@@ -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>
|
||||
-->
|
||||
578
docs/html-intl/intl/id/guide/components/tasks-and-back-stack.jd
Normal file
578
docs/html-intl/intl/id/guide/components/tasks-and-back-stack.jd
Normal file
@@ -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>
|
||||
-->
|
||||
74
docs/html-intl/intl/id/guide/index.jd
Normal file
74
docs/html-intl/intl/id/guide/index.jd
Normal file
@@ -0,0 +1,74 @@
|
||||
page.title=Pengantar Android
|
||||
|
||||
@jd:body
|
||||
|
||||
|
||||
<div class="sidebox" style="width:220px"><!-- width to match col-4 below -->
|
||||
<p>Untuk mempelajari cara kerja aplikasi, mulailah dengan
|
||||
<a href="{@docRoot}guide/components/fundamentals.html">Dasar-Dasar Aplikasi</a>.</p>
|
||||
<p>Untuk langsung memulai pemrograman, bacalah <a href="{@docRoot}training/basics/firstapp/index.html">Membangun Aplikasi Pertama Anda.</a></p>
|
||||
</div>
|
||||
|
||||
<p>Android menyediakan kerangka kerja aplikasi yang kaya dan memungkinkan Anda membangun aplikasi dan permainan
|
||||
inovatif untuk perangkat seluler di lingkungan bahasa pemrograman Java. Dokumen yang tercantum di navigasi
|
||||
sebelah kiri menyediakan detail tentang cara membangun aplikasi menggunakan berbagai API Android.</p>
|
||||
|
||||
<p>Jika Anda masih baru dengan pengembangan Android, Anda perlu memahami
|
||||
konsep dasar berikut mengenai kerangka kerja aplikasi Android:</p>
|
||||
|
||||
|
||||
<div class="landing-banner">
|
||||
|
||||
<div class="col-6">
|
||||
|
||||
<h4>Aplikasi menyediakan beberapa titik masuk</h4>
|
||||
|
||||
<p>Aplikasi Android dibangun sebagai kombinasi beragam komponen yang bisa dipanggil
|
||||
satu per satu. Misalnya, satu <em>aktivitas</em> individual menyediakan satu
|
||||
layar untuk antarmuka pengguna, dan <em>layanan</em> yang secara terpisah melakukan
|
||||
tugas di latar belakang.</p>
|
||||
|
||||
<p>Dari satu komponen Anda dapat memulai komponen lainnya menggunakan <em>intent</em>. Anda bahkan dapat memulai
|
||||
satu komponen dalam aplikasi berbeda, seperti aktivitas dalam aplikasi peta untuk menampilkan alamat. Model ini
|
||||
menyediakan beberapa titik masuk untuk aplikasi tunggal dan memungkinkan setiap aplikasi untuk berfungsi sebagai "default"
|
||||
pengguna bagi tindakan yang dapat dipanggil aplikasi lain.</p>
|
||||
|
||||
|
||||
<p><b>Ketahui selengkapnya:</b></p>
|
||||
<ul class="nolist">
|
||||
<li><a href="{@docRoot}guide/components/fundamentals.html">Dasar-Dasar Aplikasi</a>
|
||||
<li><a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>
|
||||
<li><a href="{@docRoot}guide/components/activities.html">Aktivitas</a>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-6">
|
||||
|
||||
<h4>Aplikasi beradaptasi dengan perangkat berbeda</h4>
|
||||
|
||||
<p>Android menyediakan kerangka kerja aplikasi adaptif yang memungkinkan Anda menyediakan sumber daya unik
|
||||
bagi konfigurasi perangkat yang berbeda-beda. Misalnya, Anda bisa membuat berbagai file layout
|
||||
XML untuk ukuran layar yang berbeda-beda dan sistem akan menentukan
|
||||
layout yang akan diterapkan berdasarkan ukuran layar perangkat yang ada saat ini.</p>
|
||||
|
||||
<p>Anda dapat melakukan query ketersediaan fitur perangkat saat dijalankan (runtime) jika ada fitur aplikasi yang memerlukan
|
||||
perangkat keras spesifik seperti kamera. Jika diperlukan, Anda juga bisa mendeklarasikan fitur yang dibutuhkan aplikasi
|
||||
agar pasar aplikasi seperti Google Play Store tidak mengizinkan instalasi pada perangkat yang tidak
|
||||
mendukung fitur itu.</p>
|
||||
|
||||
|
||||
<p><b>Ketahui selengkapnya:</b></p>
|
||||
<ul class="nolist">
|
||||
<li><a href="{@docRoot}guide/practices/compatibility.html">Kompatibilitas Perangkat</a>
|
||||
<li><a href="{@docRoot}guide/topics/resources/overview.html">Ikhtisar Sumber Daya</a>
|
||||
<li><a href="{@docRoot}guide/topics/ui/overview.html">Ikhtisar Antarmuka Pengguna</a>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div><!-- end landing-banner -->
|
||||
|
||||
|
||||
|
||||
197
docs/html-intl/intl/id/guide/platform/j8-jack.jd
Normal file
197
docs/html-intl/intl/id/guide/platform/j8-jack.jd
Normal file
@@ -0,0 +1,197 @@
|
||||
page.title=Fitur Bahasa Java 8
|
||||
page.keywords="android N", "Java 8", "Jack"
|
||||
@jd:body
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
<ol>
|
||||
<li>
|
||||
<a href="#supported-features">API dan Fitur Bahasa Java 8 yang didukung</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#configuration">Mengaktifkan Fitur Java 8 dan Jack Toolchain</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Android N memperkenalkan dukungan untuk fitur bahasa Java 8
|
||||
yang bisa Anda gunakan saat mengembangkan aplikasi yang menargetkan Android N.
|
||||
Halaman ini menjelaskan fitur bahasa baru yang didukung dalam Android N
|
||||
Preview, cara menyiapkan proyek Anda dengan benar untuk menggunakannya, dan setiap masalah
|
||||
yang diketahui yang mungkin Anda temui.
|
||||
</p>
|
||||
|
||||
<p>Untuk mulai menggunakan fitur-fitur ini, Anda perlu mengunduh dan menyiapkan Android
|
||||
Studio 2.1 dan Android N Preview SDK, yang menyertakan
|
||||
Jack toolchain yang diperlukan dan Plugin Android untuk Gradle yang telah diperbarui. Jika Anda belum
|
||||
memasang Android N Preview SDK, lihat <a href="{@docRoot}preview/setup-sdk.html">Menyiapkan Pengembangan untuk Android N</a>.</p>
|
||||
|
||||
|
||||
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Menggunakan fitur bahasa Java 8 yang baru bukanlah
|
||||
persyaratan untuk mengembangkan aplikasi yang menargetkan platform Android N. Jika Anda
|
||||
tidak ingin menulis kode dengan fitur bahasa Java 8, Anda bisa membiarkan nilai kompatibilitas
|
||||
sumber dan target proyek disetel ke Java 7, namun Anda tetap harus
|
||||
mengompilasi dengan JDK 8 untuk membangun pada platform Android N.
|
||||
</p>
|
||||
|
||||
<h2 id="supported-features">
|
||||
API dan Fitur Bahasa Java 8 yang Didukung
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Saat ini tidak semua fitur bahasa Java 8 didukung Android. Akan tetapi,
|
||||
fitur berikut sekarang tersedia saat mengembangkan aplikasi yang menargetkan
|
||||
Android N Preview:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html">Metode
|
||||
antarmuka default dan statis</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html">
|
||||
Ekspresi Lambda</a> (juga tersedia pada API level 23 dan yang lebih rendah)
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html">Anotasi
|
||||
yang bisa diulang</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html">
|
||||
Referensi Metode</a> (juga tersedia pada API level 23 dan yang lebih rendah)
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Untuk menguji ekspresi lambda dan referensi metode pada
|
||||
Android versi sebelumnya, bukalah file {@code build.gradle}
|
||||
Anda, serta setel {@code compileSdkVersion} dan {@code targetSdkVersion} ke 23 atau
|
||||
yang lebih rendah. Anda tetap perlu <a href="#configuration">mengaktifkan Jack
|
||||
toolchain</a> untuk menggunakan fitur Java 8 ini.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Selain itu, API fitur bahasa Java 8 berikut ini sekarang tersedia:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Reflection API dan API terkait bahasa:
|
||||
<ul>
|
||||
<li>
|
||||
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html">
|
||||
{@code java.lang.FunctionalInterface}</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/Repeatable.html">
|
||||
{@code java.lang.annotation.Repeatable}</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#isDefault--">
|
||||
{@code java.lang.reflect.Method.isDefault()}</a>
|
||||
</li>
|
||||
|
||||
<li>dan Reflection API yang terkait dengan anotasi yang bisa diulang, seperti
|
||||
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotationsByType-java.lang.Class-">
|
||||
{@code AnnotatedElement.getAnnotationsByType(Class)}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>Utility API:
|
||||
<ul>
|
||||
<li>
|
||||
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html">
|
||||
{@code java.util.function}</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html">
|
||||
{@code java.util.stream}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="configuration">
|
||||
Mengaktifkan Fitur Java 8 dan Jack Toolchain
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Agar dapat menggunakan fitur bahasa Java 8 yang baru, Anda juga perlu menggunakan
|
||||
<a class="external-link" href="https://source.android.com/source/jack.html">Jack toolchain</a> yang baru. Toolchain Android
|
||||
yang baru ini mengompilasi sumber bahasa Java menjadi dex
|
||||
bytecode yang bisa dibaca Android, memiliki format pustaka {@code .jack} sendiri, dan menyediakan sebagian besar fitur toolchain
|
||||
sebagai bagian dari alat bantu tunggal: pengemasan ulang, penciutan, pengaburan, dan
|
||||
multidex.
|
||||
</p>
|
||||
|
||||
<p>Inilah perbandingan dua toolchain yang digunakan untuk membangun file Android DEX:</p>
|
||||
<ul>
|
||||
<li>Toolchain javac lawas:<br>
|
||||
<b>javac</b> ({@code .java} --> {@code .class}) --> <b>dx</b> ({@code
|
||||
.class} --> {@code .dex})
|
||||
</li>
|
||||
|
||||
<li>Jack Toolchain baru:<br>
|
||||
<b>Jack</b> ({@code .java} --> {@code .jack} --> {@code .dex})
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>
|
||||
Mengonfigurasi Gradle
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
Untuk mengaktifkan fitur bahasa Java 8 dan Jack bagi proyek Anda, masukkan
|
||||
yang berikut dalam file {@code build.gradle} level modul Anda:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
android {
|
||||
...
|
||||
defaultConfig {
|
||||
...
|
||||
jackOptions {
|
||||
enabled true
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3 id="known-issues">
|
||||
Masalah yang Diketahui
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
<a href="{@docRoot}tools/building/building-studio.html#instant-run">Instant
|
||||
Run</a> saat ini tidak berfungsi pada Jack dan akan dinonaktifkan saat menggunakan
|
||||
toolchain baru.
|
||||
</p>
|
||||
|
||||
<p>Karena Jack tidak menghasilkan file kelas antara saat mengompilasi sebuah
|
||||
aplikasi, alat yang bergantung pada file-file ini sekarang tidak berfungsi pada Jack. Beberapa
|
||||
contoh alat ini adalah:</p>
|
||||
|
||||
<ul>
|
||||
<li>Pendeteksi lint yang beroperasi pada file kelas
|
||||
</li>
|
||||
|
||||
<li>Alat dan pustaka yang mewajibkan file kelas aplikasi (misalnya
|
||||
pengujian instrumentasi dengan JaCoCo)
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Jika Anda menemukan masalah lain saat menggunakan Jack, <a href="http://tools.android.com/filing-bugs">laporkan bug</a>.</p>
|
||||
517
docs/html-intl/intl/id/guide/topics/manifest/manifest-intro.jd
Normal file
517
docs/html-intl/intl/id/guide/topics/manifest/manifest-intro.jd
Normal file
@@ -0,0 +1,517 @@
|
||||
page.title=Manifes Aplikasi
|
||||
@jd:body
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#filestruct">Struktur File Manifes</a></li>
|
||||
<li><a href="#filec">Konvensi File</a>
|
||||
<li><a href="#filef">Fitur File</a>
|
||||
<ol>
|
||||
<li><a href="#ifs">Filter Intent</a></li>
|
||||
<li><a href="#iconlabel">Ikon dan Label</a></li>
|
||||
<li><a href="#perms">Izin</a></li>
|
||||
<li><a href="#libs">Pustaka</a></li>
|
||||
</ol></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Setiap aplikasi harus memiliki file AndroidManifest.xml (bernama persis seperti ini) di direktori akar.
|
||||
<span itemprop="description">File manifes
|
||||
menyediakan informasi penting tentang aplikasi ke sistem Android,
|
||||
informasi yang harus dimiliki sistem agar bisa menjalankan setiap kode
|
||||
aplikasi.</span> Di antaranya, manifes melakukan hal berikut ini:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Menamai paket Java untuk aplikasi.
|
||||
Nama paket berfungsi sebagai identifier unik untuk aplikasi.</li>
|
||||
|
||||
<li>Menjelaskan berbagai komponen aplikasi—aktivitas,
|
||||
layanan, penerima siaran, dan penyedia konten
|
||||
yang membentuk aplikasi. Menamai kelas yang mengimplementasikan setiap komponen dan
|
||||
mempublikasikan kemampuannya (misalnya, pesan {@link android.content.Intent
|
||||
Intent} mana yang bisa ditanganinya). Deklarasi ini memberi tahu sistem Android mengenai
|
||||
komponennya dan dalam kondisi apa bisa diluncurkan.</li>
|
||||
|
||||
<li>Menentukan proses yang akan menjadi host komponen aplikasi.</li>
|
||||
|
||||
<li>Mendeklarasikan izin aplikasi mana yang harus dimiliki untuk
|
||||
mengakses bagian yang dilindungi pada API dan berinteraksi dengan aplikasi lain.</li>
|
||||
|
||||
<li>Juga mendeklarasikan izin lain yang harus dimiliki untuk
|
||||
untuk berinteraksi dengan komponen aplikasi.</li>
|
||||
|
||||
<li>Mencantumkan daftar kelas {@link android.app.Instrumentation} yang memberikan
|
||||
profil dan informasi lain saat aplikasi berjalan. Deklarasi ini
|
||||
hanya ada di manifes saat aplikasi dibuat dan diuji;
|
||||
deklarasi dihapus sebelum aplikasi dipublikasikan.</li>
|
||||
|
||||
<li>Mendeklarasikan tingkat minimum API Android yang diperlukan
|
||||
aplikasi.</li>
|
||||
|
||||
<li>Mencantumkan daftar pustaka yang harus ditautkan aplikasi.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2 id="filestruct">Struktur File Manifes</h2>
|
||||
|
||||
<p>
|
||||
Diagram di bawah ini menampilkan struktur umum file manifes dan setiap
|
||||
elemen yang bisa ditampungnya. Setiap elemen, bersama
|
||||
atributnya, didokumentasikan secara lengkap dalam file terpisah. Untuk melihat
|
||||
informasi terperinci tentang setiap elemen, klik nama elemen dalam diagram,
|
||||
dalam daftar abjad elemen yang mengikuti diagram, atau penyebutan nama
|
||||
elemen lainnya.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a>
|
||||
|
||||
<a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/permission-element.html"><permission /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/permission-tree-element.html"><permission-tree /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/permission-group-element.html"><permission-group /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/instrumentation-element.html"><instrumentation /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><uses-sdk /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html"><uses-configuration /></a> <!-- ##api level 3## -->
|
||||
<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-feature /></a> <!-- ##api level 4## -->
|
||||
<a href="{@docRoot}guide/topics/manifest/supports-screens-element.html"><supports-screens /></a> <!-- ##api level 4## -->
|
||||
<a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html"><compatible-screens /></a> <!-- ##api level 9## -->
|
||||
<a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html"><supports-gl-texture /></a> <!-- ##api level 11## -->
|
||||
|
||||
<a href="{@docRoot}guide/topics/manifest/application-element.html"><application></a>
|
||||
|
||||
<a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"><intent-filter></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/action-element.html"><action /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/category-element.html"><category /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/data-element.html"><data /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"></intent-filter></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html"><meta-data /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/activity-element.html"></activity></a>
|
||||
|
||||
<a href="{@docRoot}guide/topics/manifest/activity-alias-element.html"><activity-alias></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"><intent-filter></a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"></intent-filter></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html"><meta-data /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/activity-alias-element.html"></activity-alias></a>
|
||||
|
||||
<a href="{@docRoot}guide/topics/manifest/service-element.html"><service></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"><intent-filter></a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"></intent-filter></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html"><meta-data/></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/service-element.html"></service></a>
|
||||
|
||||
<a href="{@docRoot}guide/topics/manifest/receiver-element.html"><receiver></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"><intent-filter></a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"></intent-filter></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html"><meta-data /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/receiver-element.html"></receiver></a>
|
||||
|
||||
<a href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html"><grant-uri-permission /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html"><meta-data /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/path-permission-element.html"><path-permission /></a>
|
||||
<a href="{@docRoot}guide/topics/manifest/provider-element.html"></provider></a>
|
||||
|
||||
<a href="{@docRoot}guide/topics/manifest/uses-library-element.html"><uses-library /></a>
|
||||
|
||||
<a href="{@docRoot}guide/topics/manifest/application-element.html"></application></a>
|
||||
|
||||
<a href="{@docRoot}guide/topics/manifest/manifest-element.html"></manifest></a>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Semua elemen yang bisa muncul dalam file manifes tercantum di bawah ini
|
||||
dalam urutan abjad. Ini adalah satu-satunya elemen legal; Anda tidak bisa
|
||||
menambahkan elemen atau atribut sendiri.
|
||||
</p>
|
||||
|
||||
<p style="margin-left: 2em">
|
||||
<code><a href="{@docRoot}guide/topics/manifest/action-element.html"><action></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html"><activity-alias></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/application-element.html"><application></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/category-element.html"><category></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/data-element.html"><data></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html"><grant-uri-permission></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/instrumentation-element.html"><instrumentation></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"><intent-filter></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html"><meta-data></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-element.html"><permission></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html"><permission-group></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html"><permission-tree></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/receiver-element.html"><receiver></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/service-element.html"><service></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html"><supports-screens></a></code> <!-- ##api level 4## -->
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html"><uses-configuration></a></code> <!-- ##api level 3## -->
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-feature></a></code> <!-- ##api level 4## -->
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html"><uses-library></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a></code>
|
||||
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><uses-sdk></a></code>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="filec">Konvensi File</h2>
|
||||
|
||||
<p>
|
||||
Sebagian konvensi dan aturan berlaku secara umum untuk semua elemen
|
||||
dan atribut di manifes:
|
||||
</p>
|
||||
|
||||
<dl>
|
||||
<dt><b>Elemen</b></dt>
|
||||
<dd>Hanya elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code> dan
|
||||
<code><a href="{@docRoot}guide/topics/manifest/application-element.html"><application></a></code>
|
||||
yang diwajibkan, masing-masing harus ada dan hanya boleh terjadi sekali.
|
||||
Umumnya elemen lain bisa terjadi berkali-kali atau sama sekali tidak terjadi — meskipun
|
||||
setidaknya sebagian dari elemen itu harus ada untuk agar manifes mencapai sesuatu yang
|
||||
berarti.
|
||||
|
||||
<p>
|
||||
Jika elemen tidak berisi apa pun, berarti elemen itu berisi elemen lain.
|
||||
Semua nilai diatur melalui atribut, bukan sebagai data karakter dalam elemen.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Elemen yang sama tingkatan umumnya tidak diurutkan. Misalnya, elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>,
|
||||
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a></code>, dan
|
||||
<code><a href="{@docRoot}guide/topics/manifest/service-element.html"><service></a></code>
|
||||
bisa dicampur dalam urutan apa pun. (Elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html"><activity-alias></a></code>
|
||||
merupakan eksepsi untuk aturan ini: Elemen ini harus mengikuti
|
||||
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>
|
||||
ini aliasnya.)
|
||||
</p></dd>
|
||||
|
||||
<dt><b>Atribut</b></dt>
|
||||
<dd>Secara formal, semua atribut opsional. Akan tetapi, ada sebagian
|
||||
yang harus ditetapkan agar elemen bisa mencapai tujuannya. Gunakan
|
||||
dokumentasi sebagai panduan. Bagi atribut yang benar-benar opsional, ini menyebutkan
|
||||
nilai default atau menyatakan apa yang terjadi jika tidak ada spesifikasi.
|
||||
|
||||
<p>Selain untuk beberapa atribut elemen akar
|
||||
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code>,
|
||||
semua nama atribut dimulai dengan awalan {@code android:} —
|
||||
misalnya, {@code android:alwaysRetainTaskState}. Karena awalan ini universal, dokumentasi umumnya meniadakannya saat mengacu atribut
|
||||
dengan nama.
|
||||
</p></dd>
|
||||
|
||||
<dt><b>Mendeklarasikan nama kelas</b></dt>
|
||||
<dd>Banyak elemen berhubungan dengan objek Java, termasuk elemen
|
||||
aplikasi itu sendiri (elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/application-element.html"><application></a></code>
|
||||
) dan aktivitas komponen — utamanya
|
||||
(<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>),
|
||||
layanan
|
||||
(<code><a href="{@docRoot}guide/topics/manifest/service-element.html"><service></a></code>),
|
||||
penerima siaran
|
||||
(<code><a href="{@docRoot}guide/topics/manifest/receiver-element.html"><receiver></a></code>),
|
||||
dan penyedia konten
|
||||
(<code><a href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a></code>).
|
||||
|
||||
<p>
|
||||
Jika mendefinisikan subkelas, seperti yang selalu Anda definisikan untuk kelas komponen
|
||||
({@link android.app.Activity}, {@link android.app.Service},
|
||||
{@link android.content.BroadcastReceiver}, dan {@link android.content.ContentProvider}),
|
||||
subkelas dideklarasikan melalui atribut {@code name}. Nama harus menyertakan tujuan
|
||||
paket lengkap.
|
||||
Misalnya, subkelas {@link android.app.Service} mungkin dideklarasikan sebagai berikut:
|
||||
</p>
|
||||
|
||||
<pre><manifest . . . >
|
||||
<application . . . >
|
||||
<service android:name="com.example.project.SecretService" . . . >
|
||||
. . .
|
||||
</service>
|
||||
. . .
|
||||
</application>
|
||||
</manifest></pre>
|
||||
|
||||
<p>
|
||||
Akan tetapi, sebagai shorthand, jika karakter pertama string adalah titik,
|
||||
string akan ditambahkan ke nama paket aplikasi (seperti yang ditetapkan dalam elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code>
|
||||
melalui atribut
|
||||
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html#package">package</a></code>
|
||||
). Penetapan berikut sama dengan di atas:
|
||||
</p>
|
||||
|
||||
<pre><manifest package="com.example.project" . . . >
|
||||
<application . . . >
|
||||
<service android:name=".SecretService" . . . >
|
||||
. . .
|
||||
</service>
|
||||
. . .
|
||||
</application>
|
||||
</manifest></pre>
|
||||
|
||||
<p>
|
||||
Saat memulai komponen, Android akan membuat instance subkelas yang diberi nama.
|
||||
Jika subkelas tidak ditetapkan, maka akak dibuat instance kelas dasar.
|
||||
</p></dd>
|
||||
|
||||
<dt><b>Banyak nilai</b></dt>
|
||||
<dd>Jika lebih dari satu nilai yang dapat ditetapkan, elemen ini hampir selalu
|
||||
diulangi, bukan menampilkan daftar banyak nilai dalam satu elemen.
|
||||
Misalnya, filter intent dapat mencantumkan beberapa tindakan:
|
||||
|
||||
<pre><intent-filter . . . >
|
||||
<action android:name="android.intent.action.EDIT" />
|
||||
<action android:name="android.intent.action.INSERT" />
|
||||
<action android:name="android.intent.action.DELETE" />
|
||||
. . .
|
||||
</intent-filter></pre></dd>
|
||||
|
||||
<dt><b>Nilai sumber daya</b></dt>
|
||||
<dd>Beberapa atribut memiliki nilai yang bisa ditampilkan kepada pengguna — misalnya
|
||||
, label dan ikon aktivitas. Nilai atribut ini
|
||||
harus dilokalkan dan karenanya ditetapkan dari sumber daya atau tema. Nilai sumber
|
||||
daya dinyatakan dalam format berikut,</p>
|
||||
|
||||
<p style="margin-left: 2em">{@code @[<i>package</i>:]<i>type</i>:<i>name</i>}</p>
|
||||
|
||||
<p>
|
||||
dalam hal ini nama <i>package</i> boleh dihilangkan jika sumber daya ada dalam paket yang sama dengan
|
||||
dengan aplikasi, <i>type</i> adalah tipe sumber daya — seperti "string" atau
|
||||
"drawable" — dan <i>name</i> adalah nama yang mengidentifikasi sumber daya tertentu.
|
||||
Misalnya:
|
||||
</p>
|
||||
|
||||
<pre><activity android:icon="@drawable/smallPic" . . . ></pre>
|
||||
|
||||
<p>
|
||||
Nilai tema diekspresikan dengan cara yang sama, namun dengan awal '{@code ?}'
|
||||
dan bukan '{@code @}':
|
||||
</p>
|
||||
|
||||
<p style="margin-left: 2em">{@code ?[<i>package</i>:]<i>type</i>:<i>name</i>}
|
||||
</p></dd>
|
||||
|
||||
<dt><b>Nilai-nilai string</b></dt>
|
||||
<dd>Bila nilai atribut adalah string, dua garis miring kiri ('{@code \\}')
|
||||
harus digunakan untuk meninggalkan karakter — misalnya, '{@code \\n}' untuk
|
||||
baris baru atau '{@code \\uxxxx}' untuk karakter Unicode.</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
<h2 id="filef">Fitur File</h2>
|
||||
|
||||
<p>
|
||||
Bagian berikut menjelaskan cara menerapkan sebagian fitur Android
|
||||
dalam file manifest.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="ifs">Filter Intent</h3>
|
||||
|
||||
<p>
|
||||
Komponen inti dari aplikasi (aktivitasnya, layanannya, dan penerima
|
||||
siaran) diaktifkan oleh <i>intent</i>. Intent adalah
|
||||
sekumpulan informasi (objek {@link android.content.Intent}) yang menjelaskan
|
||||
tindakan yang diinginkan — termasuk data yang akan ditindaklanjuti, kategori
|
||||
komponen yang harus melakukan tindakan, dan petunjuk terkait lainnya.
|
||||
Android mencari komponen yang sesuai untuk merespons intent, meluncurkan
|
||||
instance komponen baru jika diperlukan, dan meneruskannya ke
|
||||
objek Intent.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Komponen mengiklankan kemampuannya — jenis intent yang bisa diresponsnya
|
||||
— melalui <i>filter intent</i>. Karena sistem Android
|
||||
harus mempelajari intent yang dapat ditangani komponen sebelum meluncurkan komponen,
|
||||
filter intent ditetapkan dalam manifes sebagai elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"><intent-filter></a></code>
|
||||
. Sebuah komponen dapat memiliki filter dalam jumlah berapa saja, masing-masing menjelaskan
|
||||
kemampuan yang berbeda.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Intent yang secara eksplisit menamai komponen target akan mengaktifkan komponen itu;
|
||||
filter tidak berperan. Namun intent yang tidak menetapkan target
|
||||
dengan nama dapat mengaktifkan komponen hanya jika dapat melewati salah satu filter
|
||||
komponen.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Untuk informasi tentang cara objek Intent diuji terhadap filter intent,
|
||||
lihat dokumen terpisah,
|
||||
<a href="{@docRoot}guide/components/intents-filters.html">Intent
|
||||
dan Filter Intent</a>.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="iconlabel">Ikon dan Label</h3>
|
||||
|
||||
<p>
|
||||
Sejumlah elemen memiliki atribut {@code icon} dan {@code label} untuk
|
||||
ikon kecil dan label teks yang bisa ditampilkan kepada pengguna. Sebagian ada juga yang memiliki atribut
|
||||
{@code description}untuk teks penjelasan yang lebih panjang yang juga bisa
|
||||
ditampilkan pada layar. Misalnya, elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html"><permission></a></code>
|
||||
memiliki ketiga atribut ini, jadi saat pengguna ditanya apakah akan
|
||||
memberi izin bagi aplikasi yang memintanya, ikon yang mewakili
|
||||
izin, nama izin, dan keterangan yang
|
||||
mengikutinya bisa ditampilkan kepada pengguna.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Dalam setiap kasus, ikon dan label yang ditetapkan dalam elemen yang memuatnya menjadi
|
||||
{@code icon} default dan pengaturan {@code label} untuk semua subelemen kontainer ini.
|
||||
Karena itu, ikon dan label yang ditetapkan dalam elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/application-element.html"><application></a></code>
|
||||
adalah ikon dan label default untuk setiap komponen aplikasi.
|
||||
Demikian pula, ikon dan label yang ditetapkan untuk komponen — misalnya, elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>
|
||||
— adalah pengaturan default untuk setiap elemen komponen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"><intent-filter></a></code>
|
||||
. Jika elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/application-element.html"><application></a></code>
|
||||
menetapkan label, namun suatu aktivitas dan filter intent-nya tidak menetapkan label,
|
||||
maka label aplikasi akan dianggap sama-sama sebagai label aktvitas dan
|
||||
filter intent.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Ikon dan label yang ditetapkan untuk filter intent digunakan untuk mewakili komponen
|
||||
kapan saja komponen ditampilkan kepada pengguna saat memenuhi fungsi yang
|
||||
diiklankan oleh filter. Misalnya, filter dengan pengaturan
|
||||
"{@code android.intent.action.MAIN}" dan
|
||||
"{@code android.intent.category.LAUNCHER}" mengiklankan aktivitas
|
||||
sebagai aktivitas yang memulai aplikasi—, yaitu
|
||||
sebagai salah satu aktivitas yang harus ditampilkan dalam launcher aplikasi. Ikon dan label yang
|
||||
diatur dalam filter karenanya adalah ikon dan label yang ditampilkan dalam launcher.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="perms">Izin</h3>
|
||||
|
||||
<p>
|
||||
Sebuah <i>izin</i> adalah pembatasan yang membatasi akses ke bagian
|
||||
kode atau ke data pada perangkat. Pembatasan diberlakukan untuk melindungi data dan kode
|
||||
penting yang bisa disalahgunakan untuk mengganggu atau merusak pengalaman pengguna.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Setiap izin diidentifikasi melalui label yang unik. Sering kali, label menunjukkan
|
||||
tindakan yang dibatasi. Misalnya, berikut ini adalah beberapa izin yang didefinisikan
|
||||
oleh Android:
|
||||
</p>
|
||||
|
||||
<p style="margin-left: 2em">{@code android.permission.CALL_EMERGENCY_NUMBERS}
|
||||
<br/>{@code android.permission.READ_OWNER_DATA}
|
||||
<br/>{@code android.permission.SET_WALLPAPER}
|
||||
<br/>{@code android.permission.DEVICE_POWER}</p>
|
||||
|
||||
<p>
|
||||
Sebuah fitur bisa dilindungi paling banyak oleh satu izin.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Jika aplikasi memerlukan akses ke fitur yang dilindungi oleh izin,
|
||||
aplikasi harus mendeklarasikan bahwa aplikasi memerlukan izin itu dengan elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a></code>
|
||||
dalam manifes. Kemudian, bila aplikasi telah diinstal pada
|
||||
perangkat, installer akan menentukan apakah izin yang diminta akan diberikan atau tidak
|
||||
dengan memeriksa otoritas yang menandatangani
|
||||
sertifikat aplikasi dan, dalam beberapa kasus, bertanya pada pengguna.
|
||||
Jika izin diberikan, aplikasi tersebut bisa menggunakan
|
||||
fitur yang dilindungi. Jika tidak, upaya aplikasi untuk mengakses fitur tersebut akan gagal
|
||||
tanpa ada pemberitahuan apa pun kepada pengguna.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Aplikasi juga bisa melindungi komponennya sendiri (aktivitas, layanan,
|
||||
penerima siaran, dan penyedia konten) dengan izin. Aplikasi bisa menerapkan
|
||||
izin mana pun yang didefinisikan oleh Android (tercantum dalam
|
||||
{@link android.Manifest.permission android.Manifest.permission}) atau dideklarasikan
|
||||
oleh aplikasi lain. Atau aplikasi bisa mendefinisikannya sendiri. Izin baru dideklarasikan
|
||||
dengan elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html"><permission></a></code>
|
||||
. Misalnya, aktivitas dapat dilindungi sebagai berikut:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<manifest . . . >
|
||||
<permission android:name="com.example.project.DEBIT_ACCT" . . . />
|
||||
<uses-permission android:name="com.example.project.DEBIT_ACCT" />
|
||||
. . .
|
||||
<application . . .>
|
||||
<activity android:name="com.example.project.FreneticActivity"
|
||||
android:permission="com.example.project.DEBIT_ACCT"
|
||||
. . . >
|
||||
. . .
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Perhatikan, dalam contoh ini izin {@code DEBIT_ACCT} tidak hanya
|
||||
dideklarasikan dengan elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html"><permission></a></code>
|
||||
, penggunaannya juga diminta dengan elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a></code>
|
||||
. Penggunaannya harus diminta agar komponen
|
||||
aplikasi lainnya bisa menjalankan aktivitas yang dilindungi, meskipun perlindungan itu
|
||||
diberlakukan oleh aplikasi itu sendiri.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Dalam contoh yang sama, jika atribut {@code permission} ditetapkan
|
||||
untuk izin yang dideklarasikan di tempat lain
|
||||
lain (seperti {@code android.permission.CALL_EMERGENCY_NUMBERS}, maka atribut
|
||||
tidak perlu mendeklarasikannya lagi dengan elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html"><permission></a></code>
|
||||
. Akan tetapi, penggunaannya masih perlu dengan
|
||||
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a></code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html"><permission-tree></a></code>
|
||||
mendeklarasikan namespace untuk grup izin yang akan didefinisikan dalam
|
||||
kode. Dan
|
||||
<code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html"><permission-group></a></code>
|
||||
mendefinisikan label untuk seperangkat izin (yang sama-sama dideklarasikan dalam manifes dengan elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html"><permission></a></code>
|
||||
dan yang dideklarasikan di tempat lain). Ini hanya memengaruhi cara izin
|
||||
dikelompokkan saat ditampilkan kepada pengguna. Elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html"><permission-group></a></code>
|
||||
tidak menetapkan izin mana dimiliki grup;
|
||||
elemen hanya memberi nama grup. Izin ditempatkan dalam grup
|
||||
dengan memberikan nama grup ke elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html"><permission></a></code>
|
||||
melalui atribut
|
||||
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html#pgroup">permissionGroup</a></code>
|
||||
.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="libs">Pustaka</h3>
|
||||
|
||||
<p>
|
||||
Setiap aplikasi ditautkan dengan pustaka default Android, yang
|
||||
menyertakan paket dasar untuk membangun aplikasi (dengan kelas umum
|
||||
seperti Activity, Service, Intent, View, Button, Application, ContentProvider,
|
||||
dan sebagainya).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Akan tetapi, sebagian paket berada dalam pustakanya sendiri. Jika aplikasi Anda
|
||||
menggunakan kode salah satu paket ini, aplikasi secara eksplisit meminta untuk ditautkan dengan
|
||||
paket tersebut. Manifes harus berisi elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html"><uses-library></a></code> yang
|
||||
terpisah untuk menamai setiap pustaka. (Nama pustaka bisa ditemukan
|
||||
dalam dokumentasi paket.)
|
||||
</p>
|
||||
1184
docs/html-intl/intl/id/guide/topics/providers/calendar-provider.jd
Normal file
1184
docs/html-intl/intl/id/guide/topics/providers/calendar-provider.jd
Normal file
File diff suppressed because it is too large
Load Diff
2356
docs/html-intl/intl/id/guide/topics/providers/contacts-provider.jd
Normal file
2356
docs/html-intl/intl/id/guide/topics/providers/contacts-provider.jd
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,108 @@
|
||||
page.title=Penyedia konten
|
||||
@jd:body
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
|
||||
|
||||
<!-- In this document -->
|
||||
<h2>Topik</h2>
|
||||
<ol>
|
||||
<li>
|
||||
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
|
||||
Dasar-Dasar Penyedia Konten</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{@docRoot}guide/topics/providers/content-provider-creating.html">
|
||||
Membuat Penyedia Konten</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{@docRoot}guide/topics/providers/calendar-provider.html">Penyedia Kalender</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{@docRoot}guide/topics/providers/contacts-provider.html">Penyedia Kontak</a>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<!-- Related Samples -->
|
||||
<h2>Contoh-Contoh Terkait</h2>
|
||||
<ol>
|
||||
<li>
|
||||
<a href="{@docRoot}resources/samples/ContactManager/index.html">
|
||||
Aplikasi Contact Manager</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List2.html">
|
||||
"Kursor (Orang)"
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List7.html">
|
||||
"Kursor (Telepon)"</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">
|
||||
Contoh Adaptor Sinkronisasi</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
Penyedia konten mengelola akses ke set data terstruktur. Penyedia ini membungkus
|
||||
data, dan menyediakan mekanisme untuk mendefinisikan keamanan data. Penyedia konten adalah antarmuka
|
||||
standar yang menghubungkan data dalam satu proses dengan kode yang berjalan dalam proses lain.
|
||||
</p>
|
||||
<p>
|
||||
Bila Anda ingin mengakses data di penyedia konten, Anda menggunakan
|
||||
{@link android.content.ContentResolver} objek dalam
|
||||
{@link android.content.Context} aplikasi untuk berkomunikasi dengan penyedia sebagai klien.
|
||||
Objek {@link android.content.ContentResolver} berkomunikasi dengan objek penyedia, yakni
|
||||
instance kelas yang mengimplementasikan {@link android.content.ContentProvider}. Objek penyedia
|
||||
menerima permintaan data dari klien, melakukan tindakan yang diminta, dan
|
||||
mengembalikan hasilnya.
|
||||
</p>
|
||||
<p>
|
||||
Anda tidak perlu mengembangkan penyedia sendiri jika tidak bermaksud untuk berbagi data dengan
|
||||
aplikasi lain. Akan tetapi, Anda memerlukan penyedia buatan sendiri untuk menyediakan saran pencarian custom
|
||||
dalam aplikasi Anda sendiri. Anda juga memerlukan penyedia sendiri jika ingin menyalin dan
|
||||
menempelkan data atau file yang kompleks dari aplikasi Anda ke aplikasi lain.
|
||||
</p>
|
||||
<p>
|
||||
Android sendiri berisi penyedia konten yang mengelola data seperti informasi audio, video, gambar, dan
|
||||
kontak pribadi. Anda bisa melihat sebagian informasi ini tercantum dalam dokumentasi
|
||||
acuan untuk paket
|
||||
<code><a href="{@docRoot}reference/android/provider/package-summary.html">android.provider</a>
|
||||
</code>. Dengan beberapa batasan, semua penyedia ini bisa diakses oleh aplikasi Android
|
||||
apa saja.
|
||||
</p><p>
|
||||
Topik-topik berikut menjelaskan penyedia konten secara lebih detail:
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<strong><a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
|
||||
Dasar-Dasar Penyedia Konten</a></strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Cara mengakses data di penyedia konten bila data disusun dalam tabel.
|
||||
</dd>
|
||||
<dt>
|
||||
<strong><a href="{@docRoot}guide/topics/providers/content-provider-creating.html">
|
||||
Membuat Penyedia Konten</a></strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Cara membuat penyedia konten sendiri.
|
||||
</dd>
|
||||
<dt>
|
||||
<strong><a href="{@docRoot}guide/topics/providers/calendar-provider.html">
|
||||
Penyedia Kalender</a></strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Cara mengakses Penyedia Kalender yang merupakan bagian dari platform Android.
|
||||
</dd>
|
||||
<dt>
|
||||
<strong><a href="{@docRoot}guide/topics/providers/contacts-provider.html">
|
||||
Penyedia Kontak</a></strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Cara mengakses Penyedia Kontak yang merupakan bagian dari platform Android.
|
||||
</dd>
|
||||
</dl>
|
||||
@@ -0,0 +1,916 @@
|
||||
page.title=Storage Access Framework
|
||||
@jd:body
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
|
||||
<h2>Dalam dokumen ini
|
||||
<a href="#" onclick="hideNestedItems('#toc44',this);return false;" class="header-toggle">
|
||||
<span class="more">tampilkan maksimal</span>
|
||||
<span class="less" style="display:none">tampilkan minimal</span></a></h2>
|
||||
<ol id="toc44" class="hide-nested">
|
||||
<li>
|
||||
<a href="#overview">Ikhtisar</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#flow">Arus Kontrol</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#client">Menulis Aplikasi Klien</a>
|
||||
<ol>
|
||||
<li><a href="#search">Mencari dokumen</a></li>
|
||||
<li><a href="#process">Memproses hasil</a></li>
|
||||
<li><a href="#metadata">Memeriksa metadata dokumen</a></li>
|
||||
<li><a href="#open">Membuka dokumen</a></li>
|
||||
<li><a href="#create">Membuat dokumen baru</a></li>
|
||||
<li><a href="#delete">Menghapus dokumen</a></li>
|
||||
<li><a href="#edit">Mengedit dokumen</a></li>
|
||||
<li><a href="#permissions">Mempertahankan izin</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#custom">Menulis Penyedia Dokumen Custom</a>
|
||||
<ol>
|
||||
<li><a href="#manifest">Manifes</a></li>
|
||||
<li><a href="#contract">Kontrak</a></li>
|
||||
<li><a href="#subclass">Subkelas DocumentsProvider</a></li>
|
||||
<li><a href="#security">Keamanan</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
|
||||
</ol>
|
||||
<h2>Kelas-kelas utama</h2>
|
||||
<ol>
|
||||
<li>{@link android.provider.DocumentsProvider}</li>
|
||||
<li>{@link android.provider.DocumentsContract}</li>
|
||||
</ol>
|
||||
|
||||
<h2>Video</h2>
|
||||
|
||||
<ol>
|
||||
<li><a href="http://www.youtube.com/watch?v=zxHVeXbK1P4">
|
||||
DevBytes: Android 4.4 Storage Access Framework: Penyedia</a></li>
|
||||
<li><a href="http://www.youtube.com/watch?v=UFj9AEz0DHQ">
|
||||
DevBytes: Android 4.4 Storage Access Framework: Klien</a></li>
|
||||
</ol>
|
||||
|
||||
|
||||
<h2>Contoh Kode</h2>
|
||||
|
||||
<ol>
|
||||
<li><a href="{@docRoot}samples/StorageProvider/index.html">
|
||||
Penyedia Penyimpanan</a></li>
|
||||
<li><a href="{@docRoot}samples/StorageClient/index.html">
|
||||
Klien Penyimpanan</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>Lihat Juga</h2>
|
||||
<ol>
|
||||
<li>
|
||||
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
|
||||
Dasar-Dasar Penyedia Konten
|
||||
</a>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Android 4.4 (API level 19) memperkenalkan Storage Access Framework (SAF, Kerangka Kerja Akses Penyimpanan). SAF
|
||||
memudahkan pengguna menyusuri dan membuka dokumen, gambar, dan file lainnya
|
||||
di semua penyedia penyimpanan dokumen pilihannya. UI standar yang mudah digunakan
|
||||
memungkinkan pengguna menyusuri file dan mengakses yang terbaru dengan cara konsisten di antara berbagai aplikasi dan penyedia.</p>
|
||||
|
||||
<p>Layanan penyimpanan cloud atau lokal bisa dilibatkan dalam ekosistem ini dengan mengimplementasikan sebuah
|
||||
{@link android.provider.DocumentsProvider} yang membungkus layanannya. Aplikasi klien
|
||||
yang memerlukan akses ke dokumen sebuah penyedia bisa berintegrasi dengan SAF cukup dengan beberapa
|
||||
baris kode.</p>
|
||||
|
||||
<p>SAF terdiri dari berikut ini:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong>Penyedia dokumen</strong>—Penyedia konten yang memungkinkan
|
||||
layanan penyimpanan (seperti Google Drive) untuk menampilkan file yang dikelolanya. Penyedia dokumen
|
||||
diimplementasikan sebagai subkelas dari kelas {@link android.provider.DocumentsProvider}.
|
||||
Skema penyedia dokumen berdasarkan hierarki file biasa,
|
||||
walaupun cara penyedia dokumen Anda secara fisik menyimpan data adalah terserah Anda.
|
||||
Platform Android terdiri dari beberapa penyedia dokumen bawaan, seperti
|
||||
Downloads, Images, dan Videos.</li>
|
||||
|
||||
<li><strong>Aplikasi klien</strong>—Aplikasi custom yang memanggil intent
|
||||
{@link android.content.Intent#ACTION_OPEN_DOCUMENT} dan/atau
|
||||
{@link android.content.Intent#ACTION_CREATE_DOCUMENT} dan menerima
|
||||
file yang dihasilkan penyedia dokumen.</li>
|
||||
|
||||
<li><strong>Picker</strong>—UI sistem yang memungkinkan pengguna mengakses dokumen dari semua
|
||||
penyedia dokumen yang memenuhi kriteria pencarian aplikasi klien.</li>
|
||||
</ul>
|
||||
|
||||
<p>Beberapa fitur yang disediakan oleh SAF adalah sebagai berikut:</p>
|
||||
<ul>
|
||||
<li>Memungkinkan pengguna menyusuri konten dari semua penyedia dokumen, bukan hanya satu aplikasi.</li>
|
||||
<li>Memungkinkan aplikasi Anda memiliki akses jangka panjang dan tetap ke
|
||||
dokumen yang dimiliki oleh penyedia dokumen. Melalui akses ini pengguna bisa menambah, mengedit,
|
||||
menyimpan, dan menghapus file pada penyedia.</li>
|
||||
<li>Mendukung banyak akun pengguna dan akar jangka pendek seperti penyedia penyimpanan
|
||||
USB, yang hanya muncul jika drive itu dipasang. </li>
|
||||
</ul>
|
||||
|
||||
<h2 id ="overview">Ikhtisar</h2>
|
||||
|
||||
<p>SAF berpusat di seputar penyedia konten yang merupakan
|
||||
subkelas dari kelas {@link android.provider.DocumentsProvider}. Dalam <em>penyedia dokumen</em>, data
|
||||
distrukturkan sebagai hierarki file biasa:</p>
|
||||
<p><img src="{@docRoot}images/providers/storage_datamodel.png" alt="data model" /></p>
|
||||
<p class="img-caption"><strong>Gambar 1.</strong> Model data penyedia dokumen. Root menunjuk ke satu Document,
|
||||
yang nanti memulai pemekaran seluruh pohon.</p>
|
||||
|
||||
<p>Perhatikan yang berikut ini:</p>
|
||||
<ul>
|
||||
|
||||
<li>Setiap penyedia dokumen melaporkan satu atau beberapa
|
||||
"akar" yang merupakan titik awal penyusuran pohon dokumen.
|
||||
Masing-masing akar memiliki sebuah {@link android.provider.DocumentsContract.Root#COLUMN_ROOT_ID} yang unik,
|
||||
dan menunjuk ke satu dokumen (satu direktori)
|
||||
yang mewakili konten di bawah akar itu.
|
||||
Akar sengaja dibuat dinamis untuk mendukung kasus penggunaan seperti multiakun,
|
||||
perangkat penyimpanan USB jangka pendek, atau masuk/keluar pengguna.</li>
|
||||
|
||||
<li>Di bawah tiap akar terdapat satu dokumen. Dokumen itu menunjuk ke dokumen-dokumen 1-ke-<em>N</em>,
|
||||
yang nanti masing-masing bisa menunjuk ke dokumen 1-ke-<em>N</em>. </li>
|
||||
|
||||
<li>Tiap backend penyimpanan memunculkan
|
||||
masing-masing file dan direktori dengan mengacunya lewat sebuah
|
||||
{@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID} yang unik.
|
||||
ID dokumen harus unik dan tidak berubah setelah dibuat, karena ID ini digunakan untuk
|
||||
URI persisten yang diberikan pada saat reboot perangkat.</li>
|
||||
|
||||
|
||||
<li>Dokumen bisa berupa file yang bisa dibuka (dengan tipe MIME tertentu), atau
|
||||
direktori yang berisi dokumen tambahan (dengan tipe MIME
|
||||
{@link android.provider.DocumentsContract.Document#MIME_TYPE_DIR}).</li>
|
||||
|
||||
<li>Tiap dokumen bisa mempunyai kemampuan berbeda, sebagaimana yang dijelaskan oleh
|
||||
{@link android.provider.DocumentsContract.Document#COLUMN_FLAGS COLUMN_FLAGS}.
|
||||
Misalnya, {@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_WRITE},
|
||||
{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE}, dan
|
||||
{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_THUMBNAIL}.
|
||||
{@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID} yang sama bisa
|
||||
dimasukkan dalam beberapa direktori.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="flow">Arus Kontrol</h2>
|
||||
<p>Seperti dinyatakan di atas, model data penyedia dokumen dibuat berdasarkan hierarki file
|
||||
biasa. Akan tetapi, Anda bisa menyimpan secara fisik data dengan cara apa pun yang disukai,
|
||||
selama data bisa diakses melalui API {@link android.provider.DocumentsProvider}. Misalnya, Anda
|
||||
bisa menggunakan penyimpanan cloud berbasis tag untuk data Anda.</p>
|
||||
|
||||
<p>Gambar 2 menampilkan contoh cara aplikasi foto bisa menggunakan SAF
|
||||
untuk mengakses data tersimpan:</p>
|
||||
<p><img src="{@docRoot}images/providers/storage_dataflow.png" alt="app" /></p>
|
||||
|
||||
<p class="img-caption"><strong>Gambar 2.</strong> Arus Storage Access Framework</p>
|
||||
|
||||
<p>Perhatikan yang berikut ini:</p>
|
||||
<ul>
|
||||
|
||||
<li>Di SAF, penyedia dan klien tidak berinteraksi
|
||||
secara langsung. Klien meminta izin untuk berinteraksi
|
||||
dengan file (yakni, membaca, mengedit, membuat, atau menghapus file).</li>
|
||||
|
||||
<li>Interaksi dimulai bila sebuah aplikasi (dalam contoh ini adalah aplikasi foto) mengeluarkan intent
|
||||
{@link android.content.Intent#ACTION_OPEN_DOCUMENT} atau {@link android.content.Intent#ACTION_CREATE_DOCUMENT}. Intent bisa berisi filter
|
||||
untuk mempersempit kriteria—misalnya, "beri saya semua file yang bisa dibuka
|
||||
yang memiliki tipe MIME 'gambar'".</li>
|
||||
|
||||
<li>Setelah intent dibuat, picker sistem akan pergi ke setiap penyedia yang terdaftar
|
||||
dan menunjukkan kepada pengguna akar konten yang cocok.</li>
|
||||
|
||||
<li>Picker memberi pengguna antarmuka standar untuk mengakses dokumen,
|
||||
walaupun penyedia dokumen dasar bisa sangat berbeda. Misalnya, gambar 2
|
||||
menunjukkan penyedia Google Drive, penyedia USB, dan penyedia cloud.</li>
|
||||
</ul>
|
||||
|
||||
<p>Gambar 3 menunjukkan picker yang di digunakan pengguna mencari gambar telah memilih
|
||||
akun Google Drive:</p>
|
||||
|
||||
<p><img src="{@docRoot}images/providers/storage_picker.png" width="340" alt="picker" style="border:2px solid #ddd" /></p>
|
||||
|
||||
<p class="img-caption"><strong>Gambar 3.</strong> Picker</p>
|
||||
|
||||
<p>Bila pengguna memilih Google Drive, gambar-gambar akan ditampilkan, seperti yang ditampilkan dalam
|
||||
gambar 4. Dari titik itu, pengguna bisa berinteraksi dengan gambar dengan cara apa pun
|
||||
yang didukung oleh penyedia dan aplikasi klien.
|
||||
|
||||
<p><img src="{@docRoot}images/providers/storage_photos.png" width="340" alt="picker" style="border:2px solid #ddd" /></p>
|
||||
|
||||
<p class="img-caption"><strong>Gambar 4.</strong> Gambar</p>
|
||||
|
||||
<h2 id="client">Menulis Aplikasi Klien</h2>
|
||||
|
||||
<p>Pada Android 4.3 dan yang lebih rendah, jika Anda ingin aplikasi mengambil file dari
|
||||
aplikasi lain, aplikasi Anda harus memanggil intent seperti {@link android.content.Intent#ACTION_PICK}
|
||||
atau {@link android.content.Intent#ACTION_GET_CONTENT}. Pengguna nanti harus memilih
|
||||
satu aplikasi yang akan digunakan untuk mengambil file dan aplikasi yang dipilih harus menyediakan antarmuka pengguna
|
||||
bagi untuk menyusuri dan mengambil dari file yang tersedia. </p>
|
||||
|
||||
<p>Pada Android 4.4 dan yang lebih tinggi, Anda mempunyai opsi tambahan dalam menggunakan intent
|
||||
{@link android.content.Intent#ACTION_OPEN_DOCUMENT},
|
||||
yang menampilkan UI picker yang dikontrol oleh sistem yang memungkinkan pengguna
|
||||
menyusuri semua file yang disediakan aplikasi lain. Dari satu UI ini, pengguna
|
||||
bisa mengambil file dari aplikasi apa saja yang didukung.</p>
|
||||
|
||||
<p>{@link android.content.Intent#ACTION_OPEN_DOCUMENT}
|
||||
tidak dimaksudkan untuk menjadi pengganti {@link android.content.Intent#ACTION_GET_CONTENT}.
|
||||
Yang harus Anda gunakan bergantung pada kebutuhan aplikasi:</p>
|
||||
|
||||
<ul>
|
||||
<li>Gunakan {@link android.content.Intent#ACTION_GET_CONTENT} jika Anda ingin aplikasi
|
||||
cuma membaca/mengimpor data. Dengan pendekatan ini, aplikasi akan mengimpor salinan data,
|
||||
misalnya file gambar.</li>
|
||||
|
||||
<li>Gunakan {@link android.content.Intent#ACTION_OPEN_DOCUMENT} jika Anda ingin aplikasi
|
||||
memiliki akses jangka panjang dan jangka pendek ke dokumen yang dimiliki oleh penyedia
|
||||
dokumen. Contohnya adalah aplikasi pengeditan foto yang memungkinkan pengguna mengedit
|
||||
gambar yang tersimpan dalam penyedia dokumen. </li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<p>Bagian ini menjelaskan cara menulis aplikasi klien berdasarkan
|
||||
{@link android.content.Intent#ACTION_OPEN_DOCUMENT} dan
|
||||
intent {@link android.content.Intent#ACTION_CREATE_DOCUMENT}.</p>
|
||||
|
||||
|
||||
<h3 id="search">Mencari dokumen</h3>
|
||||
|
||||
<p>
|
||||
Cuplikan berikut menggunakan {@link android.content.Intent#ACTION_OPEN_DOCUMENT}
|
||||
untuk mencari penyedia dokumen yang
|
||||
berisi file gambar:</p>
|
||||
|
||||
<pre>private static final int READ_REQUEST_CODE = 42;
|
||||
...
|
||||
/**
|
||||
* Fires an intent to spin up the "file chooser" UI and select an image.
|
||||
*/
|
||||
public void performFileSearch() {
|
||||
|
||||
// ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file
|
||||
// browser.
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
|
||||
// Filter to only show results that can be "opened", such as a
|
||||
// file (as opposed to a list of contacts or timezones)
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
|
||||
// Filter to show only images, using the image MIME data type.
|
||||
// If one wanted to search for ogg vorbis files, the type would be "audio/ogg".
|
||||
// To search for all documents available via installed storage providers,
|
||||
// it would be "*/*".
|
||||
intent.setType("image/*");
|
||||
|
||||
startActivityForResult(intent, READ_REQUEST_CODE);
|
||||
}</pre>
|
||||
|
||||
<p>Perhatikan yang berikut ini:</p>
|
||||
<ul>
|
||||
<li>Saat aplikasi mengeluarkan intent {@link android.content.Intent#ACTION_OPEN_DOCUMENT}
|
||||
, aplikasi akan menjalankan picker yang menampilkan semua penyedia dokumen yang cocok.</li>
|
||||
|
||||
<li>Menambahkan kategori {@link android.content.Intent#CATEGORY_OPENABLE} ke
|
||||
intent akan menyaring hasil agar hanya menampilkan dokumen yang bisa dibuka, seperti file gambar.</li>
|
||||
|
||||
<li>Pernyataan {@code intent.setType("image/*")} menyaring lebih jauh agar hanya
|
||||
menampilkan dokumen yang memiliki tipe data MIME gambar.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="results">Memproses Hasil</h3>
|
||||
|
||||
<p>Setelah pengguna memilih dokumen di picker,
|
||||
{@link android.app.Activity#onActivityResult onActivityResult()} akan dipanggil.
|
||||
URI yang menunjuk ke dokumen yang dipilih dimasukkan dalam parameter {@code resultData}
|
||||
. Ekstrak URI dengan {@link android.content.Intent#getData getData()}.
|
||||
Setelah mendapatkannya, Anda bisa menggunakannya untuk mengambil dokumen yang diinginkan pengguna. Misalnya
|
||||
:</p>
|
||||
|
||||
<pre>@Override
|
||||
public void onActivityResult(int requestCode, int resultCode,
|
||||
Intent resultData) {
|
||||
|
||||
// The ACTION_OPEN_DOCUMENT intent was sent with the request code
|
||||
// READ_REQUEST_CODE. If the request code seen here doesn't match, it's the
|
||||
// response to some other intent, and the code below shouldn't run at all.
|
||||
|
||||
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
|
||||
// The document selected by the user won't be returned in the intent.
|
||||
// Instead, a URI to that document will be contained in the return intent
|
||||
// provided to this method as a parameter.
|
||||
// Pull that URI using resultData.getData().
|
||||
Uri uri = null;
|
||||
if (resultData != null) {
|
||||
uri = resultData.getData();
|
||||
Log.i(TAG, "Uri: " + uri.toString());
|
||||
showImage(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3 id="metadata">Memeriksa metadata dokumen</h3>
|
||||
|
||||
<p>Setelah Anda memiliki URI untuk dokumen, Anda akan mendapatkan akses ke metadatanya. Cuplikan
|
||||
ini memegang metadata sebuah dokumen yang disebutkan oleh URI, dan mencatatnya:</p>
|
||||
|
||||
<pre>public void dumpImageMetaData(Uri uri) {
|
||||
|
||||
// The query, since it only applies to a single document, will only return
|
||||
// one row. There's no need to filter, sort, or select fields, since we want
|
||||
// all fields for one document.
|
||||
Cursor cursor = getActivity().getContentResolver()
|
||||
.query(uri, null, null, null, null, null);
|
||||
|
||||
try {
|
||||
// moveToFirst() returns false if the cursor has 0 rows. Very handy for
|
||||
// "if there's anything to look at, look at it" conditionals.
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
|
||||
// Note it's called "Display Name". This is
|
||||
// provider-specific, and might not necessarily be the file name.
|
||||
String displayName = cursor.getString(
|
||||
cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
|
||||
Log.i(TAG, "Display Name: " + displayName);
|
||||
|
||||
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
|
||||
// If the size is unknown, the value stored is null. But since an
|
||||
// int can't be null in Java, the behavior is implementation-specific,
|
||||
// which is just a fancy term for "unpredictable". So as
|
||||
// a rule, check if it's null before assigning to an int. This will
|
||||
// happen often: The storage API allows for remote files, whose
|
||||
// size might not be locally known.
|
||||
String size = null;
|
||||
if (!cursor.isNull(sizeIndex)) {
|
||||
// Technically the column stores an int, but cursor.getString()
|
||||
// will do the conversion automatically.
|
||||
size = cursor.getString(sizeIndex);
|
||||
} else {
|
||||
size = "Unknown";
|
||||
}
|
||||
Log.i(TAG, "Size: " + size);
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3 id="open-client">Membuka dokumen</h3>
|
||||
|
||||
<p>Setelah mendapatkan URI dokumen, Anda bisa membuka dokumen atau melakukan apa saja
|
||||
yang diinginkan padanya.</p>
|
||||
|
||||
<h4>Bitmap</h4>
|
||||
|
||||
<p>Berikut ini adalah contoh cara membuka {@link android.graphics.Bitmap}:</p>
|
||||
|
||||
<pre>private Bitmap getBitmapFromUri(Uri uri) throws IOException {
|
||||
ParcelFileDescriptor parcelFileDescriptor =
|
||||
getContentResolver().openFileDescriptor(uri, "r");
|
||||
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
|
||||
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
|
||||
parcelFileDescriptor.close();
|
||||
return image;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Perhatikan bahwa Anda tidak boleh melakukan operasi ini pada thread UI. Lakukan hal ini di latar belakang
|
||||
, dengan menggunakan {@link android.os.AsyncTask}. Setelah membuka bitmap, Anda
|
||||
bisa menampilkannya dalam {@link android.widget.ImageView}.
|
||||
</p>
|
||||
|
||||
<h4>Mendapatkan InputStream</h4>
|
||||
|
||||
<p>Berikut ini adalah contoh cara mendapatkan {@link java.io.InputStream} dari URI. Dalam cuplikan ini
|
||||
, baris-baris file dibaca ke dalam sebuah string:</p>
|
||||
|
||||
<pre>private String readTextFromUri(Uri uri) throws IOException {
|
||||
InputStream inputStream = getContentResolver().openInputStream(uri);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||
inputStream));
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
stringBuilder.append(line);
|
||||
}
|
||||
fileInputStream.close();
|
||||
parcelFileDescriptor.close();
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3 id="create">Membuat dokumen baru</h3>
|
||||
|
||||
<p>Aplikasi Anda bisa membuat dokumen baru dalam penyedia dokumen dengan menggunakan intent
|
||||
{@link android.content.Intent#ACTION_CREATE_DOCUMENT}
|
||||
. Untuk membuat file, Anda memberikan satu tipe MIME dan satu nama file pada intent, dan
|
||||
menjalankannya dengan kode permintaan yang unik. Selebihnya akan diurus untuk Anda:</p>
|
||||
|
||||
|
||||
<pre>
|
||||
// Here are some examples of how you might call this method.
|
||||
// The first parameter is the MIME type, and the second parameter is the name
|
||||
// of the file you are creating:
|
||||
//
|
||||
// createFile("text/plain", "foobar.txt");
|
||||
// createFile("image/png", "mypicture.png");
|
||||
|
||||
// Unique request code.
|
||||
private static final int WRITE_REQUEST_CODE = 43;
|
||||
...
|
||||
private void createFile(String mimeType, String fileName) {
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
|
||||
// Filter to only show results that can be "opened", such as
|
||||
// a file (as opposed to a list of contacts or timezones).
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
|
||||
// Create a file with the requested MIME type.
|
||||
intent.setType(mimeType);
|
||||
intent.putExtra(Intent.EXTRA_TITLE, fileName);
|
||||
startActivityForResult(intent, WRITE_REQUEST_CODE);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Setelah membuat dokumen baru, Anda bisa mendapatkan URI-nya dalam
|
||||
{@link android.app.Activity#onActivityResult onActivityResult()}, sehingga Anda
|
||||
bisa terus menulis ke dokumen itu.</p>
|
||||
|
||||
<h3 id="delete">Menghapus dokumen</h3>
|
||||
|
||||
<p>Jika Anda memiliki URI dokumen dan
|
||||
{@link android.provider.DocumentsContract.Document#COLUMN_FLAGS Document.COLUMN_FLAGS}
|
||||
dokumen berisi
|
||||
{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE SUPPORTS_DELETE},
|
||||
Anda bisa menghapus dokumen tersebut. Misalnya:</p>
|
||||
|
||||
<pre>
|
||||
DocumentsContract.deleteDocument(getContentResolver(), uri);
|
||||
</pre>
|
||||
|
||||
<h3 id="edit">Mengedit dokumen</h3>
|
||||
|
||||
<p>Anda bisa menggunakan SAF untuk mengedit dokumen teks langsung di tempatnya.
|
||||
Cuplikan ini memicu
|
||||
intent {@link android.content.Intent#ACTION_OPEN_DOCUMENT} dan menggunakan
|
||||
kategori {@link android.content.Intent#CATEGORY_OPENABLE} untuk menampilkan
|
||||
dokumen yang bisa dibuka saja. Ini akan menyaring lebih jauh untuk menampilkan file teks saja:</p>
|
||||
|
||||
<pre>
|
||||
private static final int EDIT_REQUEST_CODE = 44;
|
||||
/**
|
||||
* Open a file for writing and append some text to it.
|
||||
*/
|
||||
private void editDocument() {
|
||||
// ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's
|
||||
// file browser.
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
|
||||
// Filter to only show results that can be "opened", such as a
|
||||
// file (as opposed to a list of contacts or timezones).
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
|
||||
// Filter to show only text files.
|
||||
intent.setType("text/plain");
|
||||
|
||||
startActivityForResult(intent, EDIT_REQUEST_CODE);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Berikutnya, dari {@link android.app.Activity#onActivityResult onActivityResult()}
|
||||
(lihat <a href="#results">Memproses hasil</a>) Anda bisa memanggil kode untuk mengedit.
|
||||
Cuplikan berikut mendapatkan {@link java.io.FileOutputStream}
|
||||
dari {@link android.content.ContentResolver}. Secara default, snipet menggunakan mode “tulis”.
|
||||
Inilah praktik terbaik untuk meminta jumlah akses minimum yang Anda perlukan, jadi jangan meminta
|
||||
baca/tulis jika yang Anda perlukan hanyalah tulis:</p>
|
||||
|
||||
<pre>private void alterDocument(Uri uri) {
|
||||
try {
|
||||
ParcelFileDescriptor pfd = getActivity().getContentResolver().
|
||||
openFileDescriptor(uri, "w");
|
||||
FileOutputStream fileOutputStream =
|
||||
new FileOutputStream(pfd.getFileDescriptor());
|
||||
fileOutputStream.write(("Overwritten by MyCloud at " +
|
||||
System.currentTimeMillis() + "\n").getBytes());
|
||||
// Let the document provider know you're done by closing the stream.
|
||||
fileOutputStream.close();
|
||||
pfd.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}</pre>
|
||||
|
||||
<h3 id="permissions">Mempertahankan izin</h3>
|
||||
|
||||
<p>Bila aplikasi Anda membuka file untuk membaca atau menulis, sistem akan memberi
|
||||
aplikasi Anda izin URI untuk file itu. Pemberian ini berlaku hingga perangkat pengguna di-restart.
|
||||
Namun anggaplah aplikasi Anda adalah aplikasi pengeditan gambar, dan Anda ingin pengguna bisa
|
||||
mengakses 5 gambar terakhir yang dieditnya, langsung dari aplikasi Anda. Jika perangkat pengguna telah
|
||||
di-restart, maka Anda harus mengirim pengguna kembali ke picker sistem untuk menemukan
|
||||
file, hal ini jelas tidak ideal.</p>
|
||||
|
||||
<p>Untuk mencegah terjadinya hal ini, Anda bisa mempertahankan izin yang diberikan
|
||||
sistem ke aplikasi Anda. Secara efektif, aplikasi Anda akan "mengambil" pemberian izin URI yang bisa dipertahankan
|
||||
yang ditawarkan oleh sistem. Hal ini memberi pengguna akses kontinu ke file
|
||||
melalui aplikasi Anda, sekalipun perangkat telah di-restart:</p>
|
||||
|
||||
|
||||
<pre>final int takeFlags = intent.getFlags()
|
||||
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
// Check for the freshest data.
|
||||
getContentResolver().takePersistableUriPermission(uri, takeFlags);</pre>
|
||||
|
||||
<p>Ada satu langkah akhir. Anda mungkin telah menyimpan
|
||||
URI terbaru yang diakses aplikasi, namun URI itu mungkin tidak lagi valid,—aplikasi lain
|
||||
mungkin telah menghapus atau memodifikasi dokumen. Karena itu, Anda harus selalu memanggil
|
||||
{@code getContentResolver().takePersistableUriPermission()} untuk memeriksa
|
||||
data terbaru.</p>
|
||||
|
||||
<h2 id="custom">Menulis Penyedia Dokumen Custom</h2>
|
||||
|
||||
<p>
|
||||
Jika Anda sedang mengembangkan aplikasi yang menyediakan layanan penyimpanan untuk file (misalnya
|
||||
layanan penyimpanan cloud), Anda bisa menyediakan file melalui
|
||||
SAF dengan menulis penyedia dokumen custom. Bagian ini menjelaskan
|
||||
caranya.</p>
|
||||
|
||||
|
||||
<h3 id="manifest">Manifes</h3>
|
||||
|
||||
<p>Untuk mengimplementasikan penyedia dokumen custom, tambahkan yang berikut ini ke manifes aplikasi
|
||||
Anda:</p>
|
||||
<ul>
|
||||
|
||||
<li>Target berupa API level 19 atau yang lebih tinggi.</li>
|
||||
|
||||
<li>Elemen <code><provider></code> yang mendeklarasikan penyedia penyimpanan custom
|
||||
Anda. </li>
|
||||
|
||||
<li>Nama penyedia Anda, yaitu nama kelasnya, termasuk nama paket.
|
||||
Misalnya: <code>com.example.android.storageprovider.MyCloudProvider</code>.</li>
|
||||
|
||||
<li>Nama otoritas Anda, yaitu nama paket Anda (dalam contoh ini,
|
||||
<code>com.example.android.storageprovider</code>) plus tipe penyedia konten
|
||||
(<code>documents</code>). Misalnya, {@code com.example.android.storageprovider.documents}.</li>
|
||||
|
||||
<li>Atribut <code>android:exported</code> yang diatur ke <code>"true"</code>.
|
||||
Anda harus mengekspor penyedia sehingga aplikasi lain bisa membacanya.</li>
|
||||
|
||||
<li>Atribut <code>android:grantUriPermissions</code> yang diatur ke
|
||||
<code>"true"</code>. Pengaturan ini memungkinkan sistem memberi aplikasi lain akses
|
||||
ke konten dalam penyedia Anda. Untuk pembahasan cara mempertahankan pemberian bagi
|
||||
dokumen tertentu, lihat <a href="#permissions">Mempertahankan izin</a>.</li>
|
||||
|
||||
<li>Izin {@code MANAGE_DOCUMENTS}. Secara default, penyedia tersedia
|
||||
bagi siapa saja. Menambahkan izin ini akan membatasi penyedia Anda pada sistem.
|
||||
Pembatasan ini penting untuk keamanan.</li>
|
||||
|
||||
<li>Atribut {@code android:enabled} yang diatur ke nilai boolean didefinisikan dalam file
|
||||
sumber daya. Tujuan atribut ini adalah menonaktifkan penyedia pada perangkat yang menjalankan Android 4.3 atau yang lebih rendah.
|
||||
Misalnya, {@code android:enabled="@bool/atLeastKitKat"}. Selain
|
||||
memasukkan atribut ini dalam manifes, Anda perlu melakukan hal-hal berikut:
|
||||
<ul>
|
||||
<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values/}, tambahkan
|
||||
baris ini: <pre><bool name="atLeastKitKat">false</bool></pre></li>
|
||||
|
||||
<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values-v19/}, tambahkan
|
||||
baris ini: <pre><bool name="atLeastKitKat">true</bool></pre></li>
|
||||
</ul></li>
|
||||
|
||||
<li>Sebuah filter intent berisi tindakan
|
||||
{@code android.content.action.DOCUMENTS_PROVIDER}, agar penyedia Anda
|
||||
muncul dalam picker saat sistem mencari penyedia.</li>
|
||||
|
||||
</ul>
|
||||
<p>Berikut ini adalah kutipan contoh manifes berisi penyedia yang:</p>
|
||||
|
||||
<pre><manifest... >
|
||||
...
|
||||
<uses-sdk
|
||||
android:minSdkVersion="19"
|
||||
android:targetSdkVersion="19" />
|
||||
....
|
||||
<provider
|
||||
android:name="com.example.android.storageprovider.MyCloudProvider"
|
||||
android:authorities="com.example.android.storageprovider.documents"
|
||||
android:grantUriPermissions="true"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.MANAGE_DOCUMENTS"
|
||||
android:enabled="@bool/atLeastKitKat">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
|
||||
</intent-filter>
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest></pre>
|
||||
|
||||
<h4 id="43">Mendukung perangkat yang menjalankan Android 4.3 dan yang lebih rendah</h4>
|
||||
|
||||
<p>Intent
|
||||
{@link android.content.Intent#ACTION_OPEN_DOCUMENT} hanya tersedia
|
||||
pada perangkat yang menjalankan Android 4.4 dan yang lebih tinggi.
|
||||
Jika ingin aplikasi Anda mendukung {@link android.content.Intent#ACTION_GET_CONTENT}
|
||||
untuk mengakomodasi perangkat yang menjalankan Android 4.3 dan yang lebih rendah, Anda harus
|
||||
menonaktifkan filter inten {@link android.content.Intent#ACTION_GET_CONTENT} dalam
|
||||
manifes untuk perangkat yang menjalankan Android 4.4 atau yang lebih tinggi. Penyedia
|
||||
dokumen dan {@link android.content.Intent#ACTION_GET_CONTENT} harus dianggap
|
||||
saling eksklusif. Jika Anda mendukung keduanya sekaligus, aplikasi Anda akan
|
||||
muncul dua kali dalam UI picker sistem, yang menawarkan dua cara mengakses
|
||||
data tersimpan Anda. Hal ini akan membingungkan pengguna.</p>
|
||||
|
||||
<p>Berikut ini adalah cara yang disarankan untuk menonaktifkan
|
||||
filter intent {@link android.content.Intent#ACTION_GET_CONTENT} untuk perangkat
|
||||
yang menjalankan Android versi 4.4 atau yang lebih tinggi:</p>
|
||||
|
||||
<ol>
|
||||
<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values/}, tambahkan
|
||||
baris ini: <pre><bool name="atMostJellyBeanMR2">true</bool></pre></li>
|
||||
|
||||
<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values-v19/}, tambahkan
|
||||
baris ini: <pre><bool name="atMostJellyBeanMR2">false</bool></pre></li>
|
||||
|
||||
<li>Tambahkan
|
||||
<a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">alias
|
||||
aktivitas</a> untuk menonaktifkan filter intent {@link android.content.Intent#ACTION_GET_CONTENT}
|
||||
bagi versi 4.4 (API level 19) dan yang lebih tinggi. Misalnya:
|
||||
|
||||
<pre>
|
||||
<!-- This activity alias is added so that GET_CONTENT intent-filter
|
||||
can be disabled for builds on API level 19 and higher. -->
|
||||
<activity-alias android:name="com.android.example.app.MyPicker"
|
||||
android:targetActivity="com.android.example.app.MyActivity"
|
||||
...
|
||||
android:enabled="@bool/atMostJellyBeanMR2">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.GET_CONTENT" />
|
||||
<category android:name="android.intent.category.OPENABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="image/*" />
|
||||
<data android:mimeType="video/*" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
</pre>
|
||||
</li>
|
||||
</ol>
|
||||
<h3 id="contract">Kontrak</h3>
|
||||
|
||||
<p>Biasanya bila Anda menulis penyedia konten custom, salah satu tugas adalah
|
||||
mengimplementasikan kelas kontrak, seperti dijelaskan dalam panduan pengembang
|
||||
<a href="{@docRoot}guide/topics/providers/content-provider-creating.html#ContractClass">
|
||||
Penyedia Konten</a>. Kelas kontrak adalah kelas {@code public final}
|
||||
yang berisi definisi konstanta untuk URI, nama kolom, tipe MIME, dan
|
||||
metadata lain yang berkenaan dengan penyedia. SAF
|
||||
menyediakan kelas-kelas kontrak ini untuk Anda, jadi Anda tidak perlu menulisnya
|
||||
sendiri:</p>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.provider.DocumentsContract.Document}</li>
|
||||
<li>{@link android.provider.DocumentsContract.Root}</li>
|
||||
</ul>
|
||||
|
||||
<p>Misalnya, berikut ini adalah kolom-kolom yang bisa Anda hasilkan di kursor bila
|
||||
penyedia dokumen Anda membuat query dokumen atau akar:</p>
|
||||
|
||||
<pre>private static final String[] DEFAULT_ROOT_PROJECTION =
|
||||
new String[]{Root.COLUMN_ROOT_ID, Root.COLUMN_MIME_TYPES,
|
||||
Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE,
|
||||
Root.COLUMN_SUMMARY, Root.COLUMN_DOCUMENT_ID,
|
||||
Root.COLUMN_AVAILABLE_BYTES,};
|
||||
private static final String[] DEFAULT_DOCUMENT_PROJECTION = new
|
||||
String[]{Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE,
|
||||
Document.COLUMN_DISPLAY_NAME, Document.COLUMN_LAST_MODIFIED,
|
||||
Document.COLUMN_FLAGS, Document.COLUMN_SIZE,};
|
||||
</pre>
|
||||
|
||||
<h3 id="subclass">Subkelas DocumentsProvider</h3>
|
||||
|
||||
<p>Langkah berikutnya dalam menulis penyedia dokumen custom adalah menjadikan
|
||||
kelas abstrak sebagai subkelas {@link android.provider.DocumentsProvider}. Setidaknya, Anda perlu
|
||||
mengimplementasikan metode berikut:</p>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.provider.DocumentsProvider#queryRoots queryRoots()}</li>
|
||||
|
||||
<li>{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()}</li>
|
||||
|
||||
<li>{@link android.provider.DocumentsProvider#queryDocument queryDocument()}</li>
|
||||
|
||||
<li>{@link android.provider.DocumentsProvider#openDocument openDocument()}</li>
|
||||
</ul>
|
||||
|
||||
<p>Hanya inilah metode yang diwajibkan kepada Anda secara ketat untuk diimplementasikan, namun ada
|
||||
banyak lagi yang mungkin Anda inginkan. Lihat {@link android.provider.DocumentsProvider}
|
||||
untuk detailnya.</p>
|
||||
|
||||
<h4 id="queryRoots">Mengimplementasikan queryRoots</h4>
|
||||
|
||||
<p>Implementasi {@link android.provider.DocumentsProvider#queryRoots
|
||||
queryRoots()} oleh Anda harus menghasilkan {@link android.database.Cursor} yang menunjuk ke semua
|
||||
direktori akar penyedia dokumen, dengan menggunakan kolom-kolom yang didefinisikan dalam
|
||||
{@link android.provider.DocumentsContract.Root}.</p>
|
||||
|
||||
<p>Dalam cuplikan berikut, parameter {@code projection} mewakili bidang-bidang
|
||||
tertentu yang ingin didapatkan kembali oleh pemanggil. Cuplikan ini membuat kursor baru
|
||||
dan menambahkan satu baris ke satu akar— kursor, satu direktori level atas, seperti
|
||||
Downloads atau Images. Kebanyakan penyedia hanya mempunyai satu akar. Anda bisa mempunyai lebih dari satu,
|
||||
misalnya, jika ada banyak akun pengguna. Dalam hal itu, cukup tambahkan sebuah
|
||||
baris kedua ke kursor.</p>
|
||||
|
||||
<pre>
|
||||
@Override
|
||||
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
|
||||
|
||||
// Create a cursor with either the requested fields, or the default
|
||||
// projection if "projection" is null.
|
||||
final MatrixCursor result =
|
||||
new MatrixCursor(resolveRootProjection(projection));
|
||||
|
||||
// If user is not logged in, return an empty root cursor. This removes our
|
||||
// provider from the list entirely.
|
||||
if (!isUserLoggedIn()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// It's possible to have multiple roots (e.g. for multiple accounts in the
|
||||
// same app) -- just add multiple cursor rows.
|
||||
// Construct one row for a root called "MyCloud".
|
||||
final MatrixCursor.RowBuilder row = result.newRow();
|
||||
row.add(Root.COLUMN_ROOT_ID, ROOT);
|
||||
row.add(Root.COLUMN_SUMMARY, getContext().getString(R.string.root_summary));
|
||||
|
||||
// FLAG_SUPPORTS_CREATE means at least one directory under the root supports
|
||||
// creating documents. FLAG_SUPPORTS_RECENTS means your application's most
|
||||
// recently used documents will show up in the "Recents" category.
|
||||
// FLAG_SUPPORTS_SEARCH allows users to search all documents the application
|
||||
// shares.
|
||||
row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE |
|
||||
Root.FLAG_SUPPORTS_RECENTS |
|
||||
Root.FLAG_SUPPORTS_SEARCH);
|
||||
|
||||
// COLUMN_TITLE is the root title (e.g. Gallery, Drive).
|
||||
row.add(Root.COLUMN_TITLE, getContext().getString(R.string.title));
|
||||
|
||||
// This document id cannot change once it's shared.
|
||||
row.add(Root.COLUMN_DOCUMENT_ID, getDocIdForFile(mBaseDir));
|
||||
|
||||
// The child MIME types are used to filter the roots and only present to the
|
||||
// user roots that contain the desired type somewhere in their file hierarchy.
|
||||
row.add(Root.COLUMN_MIME_TYPES, getChildMimeTypes(mBaseDir));
|
||||
row.add(Root.COLUMN_AVAILABLE_BYTES, mBaseDir.getFreeSpace());
|
||||
row.add(Root.COLUMN_ICON, R.drawable.ic_launcher);
|
||||
|
||||
return result;
|
||||
}</pre>
|
||||
|
||||
<h4 id="queryChildDocuments">Mengimplementasikan queryChildDocuments</h4>
|
||||
|
||||
<p>Implementasi
|
||||
{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()}
|
||||
oleh Anda harus menghasilkan {@link android.database.Cursor} yang menunjuk ke semua file dalam
|
||||
direktori yang ditentukan, dengan menggunakan kolom-kolom yang didefinisikan dalam
|
||||
{@link android.provider.DocumentsContract.Document}.</p>
|
||||
|
||||
<p>Metode ini akan dipanggil bila Anda memilih akar aplikasi dalam picker UI.
|
||||
Metode mengambil dokumen anak dari direktori di bawah akar. Metode ini bisa dipanggil pada level apa saja dalam
|
||||
hierarki file, bukan hanya akar. Cuplikan ini
|
||||
membuat kursor baru dengan kolom-kolom yang diminta, lalu menambahkan informasi tentang
|
||||
setiap anak langsung dalam direktori induk ke kursor.
|
||||
Satu anak bisa berupa gambar, direktori lain—file apa saja:</p>
|
||||
|
||||
<pre>@Override
|
||||
public Cursor queryChildDocuments(String parentDocumentId, String[] projection,
|
||||
String sortOrder) throws FileNotFoundException {
|
||||
|
||||
final MatrixCursor result = new
|
||||
MatrixCursor(resolveDocumentProjection(projection));
|
||||
final File parent = getFileForDocId(parentDocumentId);
|
||||
for (File file : parent.listFiles()) {
|
||||
// Adds the file's display name, MIME type, size, and so on.
|
||||
includeFile(result, null, file);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h4 id="queryDocument">Mengimplementasikan queryDocument</h4>
|
||||
|
||||
<p>Implementasi
|
||||
{@link android.provider.DocumentsProvider#queryDocument queryDocument()}
|
||||
oleh Anda harus menghasilkan {@link android.database.Cursor} yang menunjuk ke file yang disebutkan,
|
||||
dengan menggunakan kolom-kolom yang didefinisikan dalam {@link android.provider.DocumentsContract.Document}.
|
||||
</p>
|
||||
|
||||
<p>Metode {@link android.provider.DocumentsProvider#queryDocument queryDocument()}
|
||||
menghasilkan informasi yang sama yang diteruskan dalam
|
||||
{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()},
|
||||
namun untuk file tertentu:</p>
|
||||
|
||||
|
||||
<pre>@Override
|
||||
public Cursor queryDocument(String documentId, String[] projection) throws
|
||||
FileNotFoundException {
|
||||
|
||||
// Create a cursor with the requested projection, or the default projection.
|
||||
final MatrixCursor result = new
|
||||
MatrixCursor(resolveDocumentProjection(projection));
|
||||
includeFile(result, documentId, null);
|
||||
return result;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h4 id="openDocument">Mengimplementasikan openDocument</h4>
|
||||
|
||||
<p>Anda harus mengimplementasikan {@link android.provider.DocumentsProvider#openDocument
|
||||
openDocument()} untuk menghasilkan {@link android.os.ParcelFileDescriptor} yang mewakili
|
||||
file yang disebutkan. Aplikasi lain bisa menggunakan {@link android.os.ParcelFileDescriptor}
|
||||
yang dihasilkan untuk mengalirkan data. Sistem memanggil metode ini setelah pengguna memilih file
|
||||
dan aplikasi klien meminta akses ke file itu dengan memanggil
|
||||
{@link android.content.ContentResolver#openFileDescriptor openFileDescriptor()}.
|
||||
Misalnya:</p>
|
||||
|
||||
<pre>@Override
|
||||
public ParcelFileDescriptor openDocument(final String documentId,
|
||||
final String mode,
|
||||
CancellationSignal signal) throws
|
||||
FileNotFoundException {
|
||||
Log.v(TAG, "openDocument, mode: " + mode);
|
||||
// It's OK to do network operations in this method to download the document,
|
||||
// as long as you periodically check the CancellationSignal. If you have an
|
||||
// extremely large file to transfer from the network, a better solution may
|
||||
// be pipes or sockets (see ParcelFileDescriptor for helper methods).
|
||||
|
||||
final File file = getFileForDocId(documentId);
|
||||
|
||||
final boolean isWrite = (mode.indexOf('w') != -1);
|
||||
if(isWrite) {
|
||||
// Attach a close listener if the document is opened in write mode.
|
||||
try {
|
||||
Handler handler = new Handler(getContext().getMainLooper());
|
||||
return ParcelFileDescriptor.open(file, accessMode, handler,
|
||||
new ParcelFileDescriptor.OnCloseListener() {
|
||||
@Override
|
||||
public void onClose(IOException e) {
|
||||
|
||||
// Update the file with the cloud server. The client is done
|
||||
// writing.
|
||||
Log.i(TAG, "A file with id " +
|
||||
documentId + " has been closed!
|
||||
Time to " +
|
||||
"update the server.");
|
||||
}
|
||||
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new FileNotFoundException("Failed to open document with id "
|
||||
+ documentId + " and mode " + mode);
|
||||
}
|
||||
} else {
|
||||
return ParcelFileDescriptor.open(file, accessMode);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3 id="security">Keamanan</h3>
|
||||
|
||||
<p>Anggaplah penyedia dokumen Anda sebuah layanan penyimpanan cloud yang dilindungi kata sandi
|
||||
dan Anda ingin memastikan bahwa pengguna sudah login sebelum Anda mulai berbagi file mereka.
|
||||
Apakah yang harus dilakukan aplikasi Anda jika pengguna tidak login? Solusinya adalah menghasilkan
|
||||
akar nol dalam implementasi {@link android.provider.DocumentsProvider#queryRoots
|
||||
queryRoots()} Anda. Yakni, sebuah kursor akar kosong:</p>
|
||||
|
||||
<pre>
|
||||
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
|
||||
...
|
||||
// If user is not logged in, return an empty root cursor. This removes our
|
||||
// provider from the list entirely.
|
||||
if (!isUserLoggedIn()) {
|
||||
return result;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Langkah lainnya adalah memanggil {@code getContentResolver().notifyChange()}.
|
||||
Ingat {@link android.provider.DocumentsContract}? Kita menggunakannya untuk membuat
|
||||
URI ini. Cuplikan berikut memberi tahu sistem untuk membuat query akar penyedia dokumen Anda
|
||||
kapan saja status login pengguna berubah. Jika pengguna tidak
|
||||
login, panggilan ke {@link android.provider.DocumentsProvider#queryRoots queryRoots()} akan menghasilkan
|
||||
kursor kosong, seperti yang ditampilkan di atas. Cara ini akan memastikan bahwa dokumen penyedia hanya
|
||||
tersedia jika pengguna login ke penyedia itu.</p>
|
||||
|
||||
<pre>private void onLoginButtonClick() {
|
||||
loginOrLogout();
|
||||
getContentResolver().notifyChange(DocumentsContract
|
||||
.buildRootsUri(AUTHORITY), null);
|
||||
}
|
||||
</pre>
|
||||
@@ -0,0 +1,337 @@
|
||||
page.title=Mengakses Sumber Daya
|
||||
parent.title=Sumber Daya Aplikasi
|
||||
parent.link=index.html
|
||||
@jd:body
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
<h2>Tampilan Cepat</h2>
|
||||
<ul>
|
||||
<li>Sumber daya bisa diacu dari kode dengan menggunakan integer dari {@code R.java}, seperti
|
||||
{@code R.drawable.myimage}</li>
|
||||
<li>Sumber daya bisa diacu dari sumber daya dengan menggunakan sintaks XML khusus, seperti {@code
|
||||
@drawable/myimage}</li>
|
||||
<li>Anda juga bisa mengakses sumber daya aplikasi Anda dengan berbagai metode di
|
||||
{@link android.content.res.Resources}</li>
|
||||
</ul>
|
||||
|
||||
<h2>Kelas-Kelas Utama</h2>
|
||||
<ol>
|
||||
<li>{@link android.content.res.Resources}</li>
|
||||
</ol>
|
||||
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#ResourcesFromCode">Mengakses Sumber Daya dari Kode</a></li>
|
||||
<li><a href="#ResourcesFromXml">Mengakses Sumber Daya dari XML</a>
|
||||
<ol>
|
||||
<li><a href="#ReferencesToThemeAttributes">Mengacu atribut gaya</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#PlatformResources">Mengakses Sumber Daya Platform</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>Lihat juga</h2>
|
||||
<ol>
|
||||
<li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li>
|
||||
<li><a href="available-resources.html">Tipe Sumber Daya</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<p>Setelah Anda menyediakan sumber daya dalam aplikasi Anda (yang dibicarakan di <a href="providing-resources.html">Menyediakan Sumber Daya</a>), Anda bisa menerapkannya dengan
|
||||
mengacu ID sumber dayanya. Semua ID sumber daya didefinisikan di kelas {@code R} proyek Anda, yang
|
||||
dihasilkan oleh alat {@code aapt} secara otomatis.</p>
|
||||
|
||||
<p>Bila aplikasi Anda dikompilasi, {@code aapt} akan membuat kelas {@code R}, yang berisi
|
||||
ID sumber daya untuk semua sumber daya dalam direktori {@code
|
||||
res/} Anda. Untuk masing-masing tipe sumber daya, ada subkelas {@code R} (misalnya,
|
||||
{@code R.drawable} untuk semua sumber daya yang bisa ditarik), dan untuk masing-masing sumber daya dari tipe itu, ada satu integer statis
|
||||
(misalnya, {@code R.drawable.icon}). Integer ini adalah ID sumber daya yang bisa Anda gunakan
|
||||
untuk mengambil sumber daya Anda.</p>
|
||||
|
||||
<p>Walaupun kelas {@code R} adalah tempat menyebutkan ID sumber daya, Anda tidak perlu
|
||||
melihat ke sana untuk menemukan ID sumber daya. ID sumber daya selalu terdiri dari:</p>
|
||||
<ul>
|
||||
<li><em>Tipe sumber daya</em>: Masing-masing sumber daya dikelompokkan menjadi "tipe", misalnya {@code
|
||||
string}, {@code drawable}, dan {@code layout}. Untuk mengetahui selengkapnya tentang berbagai tipe, lihat <a href="available-resources.html">Tipe Sumber Daya</a>.
|
||||
</li>
|
||||
<li><em>Nama sumber daya</em>, bisa berupa: nama file,
|
||||
tidak termasuk ekstensi; atau nilai dalam atribut {@code android:name} XML, jika
|
||||
sumber daya itu sebuah nilai sederhana (misalnya sebuah string).</li>
|
||||
</ul>
|
||||
|
||||
<p>Ada dua cara untuk mengakses sumber daya:</p>
|
||||
<ul>
|
||||
<li><strong>Dalam kode:</strong> Menggunakan integer statis dari subkelas dari kelas {@code R}
|
||||
, misalnya:
|
||||
<pre class="classic no-pretty-print">R.string.hello</pre>
|
||||
<p>{@code string} adalah tipe sumber daya dan {@code hello} adalah nama sumber daya. Ada banyak
|
||||
API Android yang bisa mengakses sumber daya Anda bila Anda menyediakan ID sumber daya dengan format ini. Lihat
|
||||
<a href="#ResourcesFromCode">Mengakses Sumber Daya dalam Kode</a>.</p>
|
||||
</li>
|
||||
<li><strong>Dalam XML:</strong> Menggunakan sebuah sintaks XML khusus yang juga berkaitan dengan
|
||||
ID sumber daya yang didefinisikan dalam kelas {@code R}, misalnya:
|
||||
<pre class="classic no-pretty-print">@string/hello</pre>
|
||||
<p>{@code string} adalah tipe sumber daya dan {@code hello} adalah nama sumber daya. Anda bisa menggunakan
|
||||
sintaks ini dalam sumber daya XML di mana saja Anda ingin menyediakan sebuah nilai dalam sebuah sumber daya. Lihat <a href="#ResourcesFromXml">Mengakses Sumber Daya dari XML</a>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<h2 id="ResourcesFromCode">Mengakses Sumber Daya dalam Kode </h2>
|
||||
|
||||
<p>Anda bisa menggunakan sumber daya dalam kode dengan menyalurkan ID sumber daya sebagai sebuah parameter metode. Misalnya,
|
||||
Anda bisa mengatur sebuah {@link android.widget.ImageView} agar menggunakan sumber daya{@code res/drawable/myimage.png}
|
||||
dengan menggunakan {@link android.widget.ImageView#setImageResource(int) setImageResource()}:</p>
|
||||
<pre>
|
||||
ImageView imageView = (ImageView) findViewById(R.id.myimageview);
|
||||
imageView.setImageResource(<strong>R.drawable.myimage</strong>);
|
||||
</pre>
|
||||
|
||||
<p>Anda juga bisa mengambil tiap sumber daya dengan menggunakan berbagai metode di {@link
|
||||
android.content.res.Resources}, di mana Anda bisa mendapatkan instance
|
||||
{@link android.content.Context#getResources()}.</p>
|
||||
|
||||
<div class="sidebox-wrapper">
|
||||
<div class="sidebox">
|
||||
<h2>Akses ke File Asli</h2>
|
||||
|
||||
<p>Walaupun tidak lazim, Anda mungkin perlu mengakses file dan direktori asli Anda. Jika demikian, maka
|
||||
menyimpan file Anda di {@code res/} tidak akan berhasil, karena satu-satunya cara untuk membaca sebuah sumber daya dari
|
||||
{@code res/} adalah dengan ID sumber daya. Sebagai gantinya, Anda bisa menyimpan sumber daya dalam direktori
|
||||
{@code assets/}.</p>
|
||||
<p>File yang tersimpan di direktori {@code assets/} <em>tidak</em> diberi ID
|
||||
sumber daya, sehingga Anda tidak bisa mengacunya melalui kelas {@code R} atau dari sumber daya XML. Sebagai gantinya, Anda bisa melakukan
|
||||
query file di direktori {@code assets/} seperti sebuah sistem file biasa dan membaca data mentah dengan menggunakan
|
||||
{@link android.content.res.AssetManager}.</p>
|
||||
<p>Akan tetapi, jika yang Anda butuhkan hanya kemampuan membaca data mentah (misalnya sebuah file video atau audio),
|
||||
maka simpanlah file itu di direktori {@code res/raw/} dan baca aliran byte dengan menggunakan {@link
|
||||
android.content.res.Resources#openRawResource(int) openRawResource()}.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h3>Sintaks</h3>
|
||||
|
||||
<p>Inilah sintaks untuk mengacu sumber daya dalam kode:</p>
|
||||
|
||||
<pre class="classic no-pretty-print">
|
||||
[<em><package_name></em>.]R.<em><resource_type></em>.<em><resource_name></em>
|
||||
</pre>
|
||||
|
||||
<ul>
|
||||
<li><em> {@code <package_name>}</em>adalah nama paket yang di dalamnya terdapat sumber daya (tidak
|
||||
dibutuhkan bila mengacu sumber daya dari paket Anda sendiri).</li>
|
||||
<li><em>{@code <resource_type>}</em> adalah subkelas {@code R} untuk tipe sumber daya.</li>
|
||||
<li><em>{@code <resource_name>}</em> bisa berupa nama file sumber daya
|
||||
tanpa ekstensi atau nilai atribut {@code android:name} dalam elemen XML (untuk nilai
|
||||
sederhana).</li>
|
||||
</ul>
|
||||
<p>Lihat <a href="available-resources.html">Tipe Sumber Daya</a> untuk
|
||||
informasi selengkapnya tentang masing-masing tipe sumber daya dan cara mengacunya.</p>
|
||||
|
||||
|
||||
<h3>Kasus penggunaan</h3>
|
||||
|
||||
<p>Ada banyak metode yang menerima parameter ID sumber daya dan Anda bisa mengambil sumber daya dengan menggunakan
|
||||
metode di {@link android.content.res.Resources}. Anda bisa mengambil instance {@link
|
||||
android.content.res.Resources} dengan {@link android.content.Context#getResources
|
||||
Context.getResources()}.</p>
|
||||
|
||||
|
||||
<p>Berikut adalah beberapa contoh cara mengakses sumber daya dalam kode:</p>
|
||||
|
||||
<pre>
|
||||
// Load a background for the current screen from a drawable resource
|
||||
{@link android.app.Activity#getWindow()}.{@link
|
||||
android.view.Window#setBackgroundDrawableResource(int)
|
||||
setBackgroundDrawableResource}(<strong>R.drawable.my_background_image</strong>) ;
|
||||
|
||||
// Set the Activity title by getting a string from the Resources object, because
|
||||
// this method requires a CharSequence rather than a resource ID
|
||||
{@link android.app.Activity#getWindow()}.{@link android.view.Window#setTitle(CharSequence)
|
||||
setTitle}(getResources().{@link android.content.res.Resources#getText(int)
|
||||
getText}(<strong>R.string.main_title</strong>));
|
||||
|
||||
// Load a custom layout for the current screen
|
||||
{@link android.app.Activity#setContentView(int)
|
||||
setContentView}(<strong>R.layout.main_screen</strong>);
|
||||
|
||||
// Set a slide in animation by getting an Animation from the Resources object
|
||||
mFlipper.{@link android.widget.ViewAnimator#setInAnimation(Animation)
|
||||
setInAnimation}(AnimationUtils.loadAnimation(this,
|
||||
<strong>R.anim.hyperspace_in</strong>));
|
||||
|
||||
// Set the text on a TextView object using a resource ID
|
||||
TextView msgTextView = (TextView) findViewById(<strong>R.id.msg</strong>);
|
||||
msgTextView.{@link android.widget.TextView#setText(int)
|
||||
setText}(<strong>R.string.hello_message</strong>);
|
||||
</pre>
|
||||
|
||||
|
||||
<p class="caution"><strong>Perhatian:</strong> Anda tidak boleh memodifikasi file {@code
|
||||
R.java} secara manual—, ini dihasilkan oleh alat {@code aapt} bila proyek Anda telah
|
||||
dikompilasi. Perubahan apa pun akan ditimpa bila nanti Anda mengompilasi.</p>
|
||||
|
||||
|
||||
|
||||
<h2 id="ResourcesFromXml">Mengakses Sumber Daya dari XML</h2>
|
||||
|
||||
<p>Anda bisa mendefinisikan nilai untuk beberapa atribut dan elemen XML dengan menggunakan
|
||||
acuan ke sumber daya yang ada. Anda akan sering melakukannya saat membuat file layout, untuk
|
||||
memasok string dan gambar bagi widget Anda.</p>
|
||||
|
||||
<p>Misalnya, jika Anda menambahkan sebuah {@link android.widget.Button} ke layout, Anda harus menggunakan
|
||||
sebuah <a href="string-resource.html">sumber daya string</a> bagi teks tombolnya:</p>
|
||||
|
||||
<pre>
|
||||
<Button
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="<strong>@string/submit</strong>" />
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Sintaks</h3>
|
||||
|
||||
<p>Berikut adalah sintaks untuk mengacu sumber daya di sumber daya XML:</p>
|
||||
|
||||
<pre class="classic no-pretty-print">
|
||||
@[<em><package_name></em>:]<em><resource_type></em>/<em><resource_name></em>
|
||||
</pre>
|
||||
|
||||
<ul>
|
||||
<li>{@code <package_name>} adalah nama paket yang di dalamnya terdapat sumber daya (tidak
|
||||
dibutuhkan bila mengacu sumber daya dari paket yang sama)</li>
|
||||
<li>{@code <resource_type>} adalah subkelas
|
||||
{@code R} untuk tipe sumber daya</li>
|
||||
<li>{@code <resource_name>} bisa berupa nama file sumber daya
|
||||
tanpa ekstensi atau nilai atribut {@code android:name} dalam elemen XML (untuk nilai
|
||||
sederhana).</li>
|
||||
</ul>
|
||||
|
||||
<p>Lihat <a href="available-resources.html">Tipe Sumber Daya</a> untuk
|
||||
informasi selengkapnya tentang masing-masing tipe sumber daya dan cara mengacunya.</p>
|
||||
|
||||
|
||||
<h3>Kasus penggunaan</h3>
|
||||
|
||||
<p>Dalam beberapa kasus, Anda harus menggunakan sumber daya untuk suatu nilai dalam XML (misalnya, untuk menerapkan gambar yang bisa ditarik
|
||||
pada widget), namun Anda juga bisa menggunakan sumber daya di XML mana saja yang menerima nilai sederhana. Misalnya, jika
|
||||
Anda mempunyai file sumber daya berikut yang berisi <a href="more-resources.html#Color">sumber daya warna</a> dan <a href="string-resource.html">sumber daya string</a>:</p>
|
||||
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="opaque_red">#f00</color>
|
||||
<string name="hello">Hello!</string>
|
||||
</resources>
|
||||
</pre>
|
||||
|
||||
<p>Anda bisa menggunakan sumber daya ini dalam file layout berikut untuk mengatur warna teks dan
|
||||
string teks:</p>
|
||||
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:textColor="<strong>@color/opaque_red</strong>"
|
||||
android:text="<strong>@string/hello</strong>" />
|
||||
</pre>
|
||||
|
||||
<p>Dalam hal ini, Anda tidak perlu menyebutkan nama paket dalam sumber daya acuan karena
|
||||
sumber daya berasal dari paket Anda sendiri. Untuk
|
||||
mengacu sumber daya sistem, Anda perlu memasukkan nama paketnya. Misalnya:</p>
|
||||
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:textColor="<strong>@android:color/secondary_text_dark</strong>"
|
||||
android:text="@string/hello" />
|
||||
</pre>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> Anda harus menggunakan sumber daya string sepanjang
|
||||
waktu, sehingga aplikasi Anda bisa dilokalkan untuk bahasa lain.
|
||||
Untuk informasi tentang cara menciptakan
|
||||
sumber daya alternatif (seperti string lokal), lihat <a href="providing-resources.html#AlternativeResources">Menyediakan Sumber Daya Alternatif
|
||||
</a>. Untuk panduan lengkap melokalkan aplikasi Anda ke bahasa lain,
|
||||
lihat <a href="localization.html">Pelokalan</a>.</p>
|
||||
|
||||
<p>Anda bahkan bisa menggunakan sumber daya dalam XML untuk membuat alias. Misalnya, Anda bisa membuat
|
||||
sumber daya yang bisa ditarik yang merupakan alias bagi sumber daya yang bisa ditarik lainnya:</p>
|
||||
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:src="@drawable/other_drawable" />
|
||||
</pre>
|
||||
|
||||
<p>Hal ini terdengar berlebihan, namun bisa sangat berguna saat menggunakan sumber daya alternatif. Baca selengkapnya tentang
|
||||
<a href="providing-resources.html#AliasResources">Membuat sumber daya alias</a>.</p>
|
||||
|
||||
|
||||
|
||||
<h3 id="ReferencesToThemeAttributes">Mengacu atribut gaya</h3>
|
||||
|
||||
<p>Sumber daya atribut gaya memungkinkan Anda mengacu nilai
|
||||
suatu atribut dalam tema yang diterapkan saat ini. Dengan mengacu sebuah atribut gaya memungkinkan Anda
|
||||
menyesuaikan tampilan elemen UI dengan mengatur gayanya agar cocok dengan beragam variasi standar yang dipasok oleh
|
||||
tema saat ini, sebagai ganti memasok nilai yang ditanamkan (hard-coded). Mengacu sebuah atribut gaya
|
||||
pada dasarnya adalah "gunakan gaya yang didefinisikan oleh atribut ini, dalam tema saat ini".</p>
|
||||
|
||||
<p>Untuk mengacu sebuah atribut gaya, sintaks namanya hampir sama dengan format sumber daya normal
|
||||
, namun sebagai ganti simbol @ ({@code @}), gunakan sebuah tanda tanya ({@code ?}), dan
|
||||
porsi tipe sumber daya bersifat opsional. Sebagai contoh:</p>
|
||||
|
||||
<pre class="classic">
|
||||
?[<em><package_name></em>:][<em><resource_type></em>/]<em><resource_name></em>
|
||||
</pre>
|
||||
|
||||
<p>Misalnya, begini cara Anda mengacu suatu atribut untuk mengatur warna teks agar cocok dengan
|
||||
warna teks "utama" tema sistem:</p>
|
||||
|
||||
<pre>
|
||||
<EditText id="text"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="<strong>?android:textColorSecondary</strong>"
|
||||
android:text="@string/hello_world" />
|
||||
</pre>
|
||||
|
||||
<p>Di sini, atribut {@code android:textColor} menyebutkan nama atribut gaya
|
||||
dalam tema saat ini. Android kini menggunakan nilai yang diterapkan pada atribut gaya {@code android:textColorSecondary}
|
||||
sebagai nilai untuk {@code android:textColor} dalam widget ini. Karena alat sumber daya
|
||||
mengetahui bahwa atribut sumber daya diharapkan dalam konteks ini,
|
||||
maka Anda tidak perlu menyatakan tipenyanya secara eksplisit (yang akan berupa
|
||||
<code>?android:attr/textColorSecondary</code>)—Anda bisa mengecualikan tipe {@code attr}.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="PlatformResources">Mengakses Sumber Daya Platform</h2>
|
||||
|
||||
<p>Android berisi sejumlah sumber daya standar, seperti gaya, tema, dan layout. Untuk
|
||||
mengakses semua sumber daya ini, tetapkan acuan sumber daya Anda dengan nama paket
|
||||
<code>android</code>. Misalnya, Android menyediakan sumber daya layout yang bisa Anda gunakan untuk
|
||||
item daftar dalam{@link android.widget.ListAdapter}:</p>
|
||||
|
||||
<pre>
|
||||
{@link android.app.ListActivity#setListAdapter(ListAdapter)
|
||||
setListAdapter}(new {@link
|
||||
android.widget.ArrayAdapter}<String>(this, <strong>android.R.layout.simple_list_item_1</strong>, myarray));
|
||||
</pre>
|
||||
|
||||
<p>Dalam contoh ini, {@link android.R.layout#simple_list_item_1} adalah sumber daya layout yang didefinisikan oleh
|
||||
platform untuk item di {@link android.widget.ListView}. Anda bisa menggunakannya sebagai ganti menciptakan
|
||||
layout sendiri untuk item daftar. Untuk informasi selengkapnya, lihat panduan pengembang
|
||||
<a href="{@docRoot}guide/topics/ui/layout/listview.html">List View</a>.</p>
|
||||
|
||||
103
docs/html-intl/intl/id/guide/topics/resources/overview.jd
Normal file
103
docs/html-intl/intl/id/guide/topics/resources/overview.jd
Normal file
@@ -0,0 +1,103 @@
|
||||
page.title=Ikhtisar Sumber Daya
|
||||
@jd:body
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
<h2>Topik</h2>
|
||||
<ol>
|
||||
<li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li>
|
||||
<li><a href="accessing-resources.html">Mengakses Sumber Daya</a></li>
|
||||
<li><a href="runtime-changes.html">Menangani Perubahan Runtime</a></li>
|
||||
<li><a href="localization.html">Pelokalan</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>Acuan</h2>
|
||||
<ol>
|
||||
<li><a href="available-resources.html">Tipe Sumber Daya</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Anda harus selalu mengeksternalkan sumber daya seperti gambar dan string dari kode
|
||||
aplikasi, agar Anda bisa memeliharanya secara independen. Mengeksternalkan
|
||||
sumber daya juga membuat Anda dapat menyediakan sumber daya alternatif yang mendukung konfigurasi
|
||||
perangkat tertentu seperti bahasa atau ukuran layar yang berbeda, yang semakin penting
|
||||
seiring semakin banyak tersedianya perangkat berbasis Android dengan konfigurasi berbeda. Untuk
|
||||
memberikan kompatibilitas dengan konfigurasi berbeda, Anda harus menata sumber daya dalam
|
||||
direktori {@code res/} proyek Anda, menggunakan berbagai subdirektori yang mengelompokkan sumber daya menurut tipe
|
||||
dan konfigurasinya.</p>
|
||||
|
||||
<div class="figure" style="width:429px">
|
||||
<img src="{@docRoot}images/resources/resource_devices_diagram1.png" height="167" alt="" />
|
||||
<p class="img-caption">
|
||||
<strong>Gambar 1.</strong> Dua perangkat berbeda, masing-masing menggunakan layout default
|
||||
(aplikasi tidak menyediakan layout alternatif).</p>
|
||||
</div>
|
||||
|
||||
<div class="figure" style="width:429px">
|
||||
<img src="{@docRoot}images/resources/resource_devices_diagram2.png" height="167" alt="" />
|
||||
<p class="img-caption">
|
||||
<strong>Gambar 2.</strong> Dua perangkat berbeda, masing-masing menggunakan layout berbeda yang tersedia untuk
|
||||
ukuran layar berbeda.</p>
|
||||
</div>
|
||||
|
||||
<p>Bagi setiap tipe sumber daya, Anda bisa menetapkan sumber daya <em>default</em> dan sumber daya
|
||||
<em>alternatif</em> untuk aplikasi Anda:</p>
|
||||
<ul>
|
||||
<li>Sumber daya default adalah sumber daya yang harus digunakan apa pun
|
||||
konfigurasi perangkatnya atau jika tidak ada sumber daya alternatif yang sesuai
|
||||
dengan konfigurasi saat ini.</li>
|
||||
<li>Sumber daya alternatif adalah sumber daya yang Anda desain untuk digunakan dengan
|
||||
konfigurasi tertentu. Untuk menetapkan bahwa satu kelompok sumber daya ditujukan bagi konfigurasi tertentu,
|
||||
tambahkan qualifier konfigurasi yang sesuai ke nama direktori.</li>
|
||||
</ul>
|
||||
|
||||
<p>Misalnya, walaupun layout
|
||||
UI default Anda disimpan dalam direktori {@code res/layout/}, Anda dapat menetapkan layout berbeda
|
||||
untuk digunakan saat layar dalam orientasi lanskap, dengan menyimpannya dalam direktori {@code res/layout-land/}
|
||||
. Android secara otomatis memberlakukan sumber daya yang sesuai dengan mencocokkan konfigurasi perangkat
|
||||
saat ini dengan nama direktori sumber daya.</p>
|
||||
|
||||
<p>Gambar 1 mengilustrasikan cara sistem memberlakukan layout yang sama untuk
|
||||
dua perangkat berbeda saat sumber daya alternatif tidak tersedia. Gambar 2 menunjukkan
|
||||
aplikasi yang sama saat menambahkan sumber daya layout alternatif untuk layar yang lebih besar.</p>
|
||||
|
||||
<p>Dokumen-dokumen berikut berisi panduan lengkap mengenai cara menata sumber daya aplikasi,
|
||||
menetapkan sumber daya alternatif, mengaksesnya dalam aplikasi, dan banyak lagi:</p>
|
||||
|
||||
<dl>
|
||||
<dt><strong><a href="providing-resources.html">Menyediakan Sumber Daya</a></strong></dt>
|
||||
<dd>Jenis sumber daya yang dapat Anda sediakan dalam aplikasi, tempat menyimpannya, dan cara membuat sumber daya
|
||||
alternatif untuk konfigurasi perangkat tertentu.</dd>
|
||||
<dt><strong><a href="accessing-resources.html">Mengakses Sumber Daya</a></strong></dt>
|
||||
<dd>Cara menggunakan sumber daya yang telah Anda sediakan, baik dengan mengacunya dari kode
|
||||
aplikasi Anda atau dari sumber daya XML lainnya.</dd>
|
||||
<dt><strong><a href="runtime-changes.html">Menangani Perubahan Runtime</a></strong></dt>
|
||||
<dd>Cara mengelola perubahan konfigurasi yang terjadi saat Aktivitas Anda berjalan.</dd>
|
||||
<dt><strong><a href="localization.html">Pelokalan</a></strong></dt>
|
||||
<dd>Panduan dari pengalaman untuk melokalkan aplikasi menggunakan sumber daya alternatif. Walaupun ini
|
||||
hanya satu penggunaan tertentu dari sumber daya alternatif, hal ini sangat penting dalam meraih pengguna lebih
|
||||
banyak.</dd>
|
||||
<dt><strong><a href="available-resources.html">Tipe Sumber Daya</a></strong></dt>
|
||||
<dd>Acuan dari berbagai tipe sumber daya yang dapat Anda sediakan, menjelaskan elemen-elemen XML,
|
||||
atribut, dan sintaksnya. Misalnya, acuan ini menunjukkan kepada Anda cara membuat sumber daya untuk
|
||||
menu aplikasi, drawable, animasi, dan lainnya.</dd>
|
||||
</dl>
|
||||
|
||||
<!--
|
||||
<h2>Raw Assets</h2>
|
||||
|
||||
<p>An alternative to saving files in {@code res/} is to save files in the {@code
|
||||
assets/} directory. This should only be necessary if you need direct access to original files and
|
||||
directories by name. Files saved in the {@code assets/} directory will not be given a resource
|
||||
ID, so you can't reference them through the {@code R} class or from XML resources. Instead, you can
|
||||
query data in the {@code assets/} directory like an ordinary file system, search through the
|
||||
directory and
|
||||
read raw data using {@link android.content.res.AssetManager}. For example, this can be more useful
|
||||
when dealing with textures for a game. However, if you only need to read raw data from a file
|
||||
(such as a video or audio file), then you should save files into the {@code res/raw/} directory and
|
||||
then read a stream of bytes using {@link android.content.res.Resources#openRawResource(int)}. This
|
||||
is uncommon, but if you need direct access to original files in {@code assets/}, refer to the {@link
|
||||
android.content.res.AssetManager} documentation.</p>
|
||||
-->
|
||||
1094
docs/html-intl/intl/id/guide/topics/resources/providing-resources.jd
Normal file
1094
docs/html-intl/intl/id/guide/topics/resources/providing-resources.jd
Normal file
File diff suppressed because it is too large
Load Diff
281
docs/html-intl/intl/id/guide/topics/resources/runtime-changes.jd
Normal file
281
docs/html-intl/intl/id/guide/topics/resources/runtime-changes.jd
Normal file
@@ -0,0 +1,281 @@
|
||||
page.title=Menangani Perubahan Runtime
|
||||
page.tags=aktivitas,daur hidup
|
||||
@jd:body
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#RetainingAnObject">Mempertahankan Objek Selama Perubahan Konfigurasi</a></li>
|
||||
<li><a href="#HandlingTheChange">Menangani Sendiri Perubahan Konfigurasi</a>
|
||||
</ol>
|
||||
|
||||
<h2>Lihat juga</h2>
|
||||
<ol>
|
||||
<li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li>
|
||||
<li><a href="accessing-resources.html">Mengakses Sumber Daya</a></li>
|
||||
<li><a href="http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html">Perubahan
|
||||
Orientasi Layar yang Lebih Cepat</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Sebagian konfigurasi perangkat bisa berubah selama runtime
|
||||
(seperti orientasi layar, ketersediaan keyboard, dan bahasa). Saat perubahan demikian terjadi,
|
||||
Android akan me-restart
|
||||
{@link android.app.Activity} yang berjalan ({@link android.app.Activity#onDestroy()} dipanggil, diikuti oleh {@link
|
||||
android.app.Activity#onCreate(Bundle) onCreate()}). Perilaku restart didesain untuk membantu
|
||||
aplikasi Anda beradaptasi dengan konfigurasi baru melalui pemuatan kembali aplikasi Anda secara otomatis dengan
|
||||
sumber daya alternatif sumber yang sesuai dengan konfigurasi perangkat baru.</p>
|
||||
|
||||
<p>Untuk menangani restart dengan benar, aktivitas Anda harus mengembalikan
|
||||
statusnya seperti semula melalui <a href="{@docRoot}guide/components/activities.html#Lifecycle">Daur hidup
|
||||
aktivitas</a> normal, dalam hal ini Android akan memanggil
|
||||
{@link android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} sebelum menghentikan
|
||||
aktivitas Anda sehingga Anda dapat menyimpan data mengenai status aplikasi. Selanjutnya Anda bisa mengembalikan status
|
||||
selama {@link android.app.Activity#onCreate(Bundle) onCreate()} atau {@link
|
||||
android.app.Activity#onRestoreInstanceState(Bundle) onRestoreInstanceState()}.</p>
|
||||
|
||||
<p>Untuk menguji bahwa aplikasi me-restart sendiri dengan status tak berubah, Anda harus
|
||||
memanggil perubahan konfigurasi (seperti mengubah orientasi layar) saat melakukan berbagai
|
||||
tugas dalam aplikasi. Aplikasi Anda harus dapat me-restart setiap saat tanpa kehilangan
|
||||
data pengguna atau status untuk menangani kejadian seperti perubahan konfigurasi atau bila pengguna menerima panggilan telepon
|
||||
masuk lalu kembali ke aplikasi setelah proses
|
||||
aplikasi Anda dimusnahkan. Untuk mengetahui cara mengembalikan status aktivitas, bacalah tentang <a href="{@docRoot}guide/components/activities.html#Lifecycle">Daur hidup aktivitas</a>.</p>
|
||||
|
||||
<p>Akan tetapi, Anda mungkin menemui situasi ketika me-restart aplikasi dan
|
||||
mengembalikan data dalam jumlah besar malah menjadi mahal dan menghasilkan pengalaman pengguna yang buruk. Dalam situasi
|
||||
demikian, Anda memiliki dua opsi lain:</p>
|
||||
|
||||
<ol type="a">
|
||||
<li><a href="#RetainingAnObject">Mempertahankan objek selama perubahan konfigurasi</a>
|
||||
<p>Izinkan aktivitas Anda me-restart saat konfigurasi berubah, namun bawa objek
|
||||
berstatus (stateful) ke instance baru aktivitas Anda.</p>
|
||||
|
||||
</li>
|
||||
<li><a href="#HandlingTheChange">Menangani sendiri perubahan konfigurasi</a>
|
||||
<p>Cegah sistem me-restart aktivitas selama perubahan konfigurasi
|
||||
tertentu, namun terima callback saat konfigurasi benar-benar berubah, agar Anda bisa memperbarui
|
||||
aktivitas secara manual bila diperlukan.</p>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
|
||||
<h2 id="RetainingAnObject">Mempertahankan Objek Selama Perubahan Konfigurasi</h2>
|
||||
|
||||
<p>Jika me-restart aktivitas mengharuskan pemulihan seperangkat data dalam jumlah besar, menghubungkan kembali koneksi
|
||||
jaringan, atau melakukan operasi intensif lainnya, maka restart penuh karena perubahan konfigurasi mungkin
|
||||
menjadi pengalaman pengguna yang lambat. Selain itu, Anda mungkin tidak bisa sepenuhnya mengembalikan status
|
||||
aktivitas dengan {@link android.os.Bundle} yang disimpan sistem untuk Anda dengan callback {@link
|
||||
android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()}—itu tidaklah
|
||||
didesain untuk membawa objek besar (seperti bitmap) dan data di dalamnya harus diserialkan kemudian
|
||||
dinon-serialkan, yang bisa menghabiskan banyak memori dan membuat perubahan konfigurasi menjadi lambat. Dalam situasi
|
||||
demikian, Anda bisa meringankan beban memulai kembali aktivitas Anda dengan mempertahankan {@link
|
||||
android.app.Fragment} saat aktivitas Anda di-restart karena perubahan konfigurasi. Fragmen ini
|
||||
bisa berisi acuan ke objek stateful yang ingin Anda pertahankan.</p>
|
||||
|
||||
<p>Bila sistem Android menghentikan aktivitas Anda karena perubahan konfigurasi, fragmen
|
||||
aktivitas yang telah ditandai untuk dipertahankan tidak akan dimusnahkan. Anda dapat menambahkan fragmen tersebut ke
|
||||
aktivitas untuk mempertahankan objek stateful.</p>
|
||||
|
||||
<p>Untuk mempertahankan objek stateful dalam fragmen selama perubahan konfigurasi runtime:</p>
|
||||
|
||||
<ol>
|
||||
<li>Perluas kelas {@link android.app.Fragment} dan deklarasikan referensi ke objek stateful
|
||||
Anda.</li>
|
||||
<li>Panggil {@link android.app.Fragment#setRetainInstance(boolean)} saat fragmen dibuat.
|
||||
</li>
|
||||
<li>Tambahkan fragmen ke aktivitas.</li>
|
||||
<li>Gunakan {@link android.app.FragmentManager} untuk mengambil fragmen saat aktivitas
|
||||
di-restart.</li>
|
||||
</ol>
|
||||
|
||||
<p>Misalnya, definisikan fragmen sebagai berikut:</p>
|
||||
|
||||
<pre>
|
||||
public class RetainedFragment extends Fragment {
|
||||
|
||||
// data object we want to retain
|
||||
private MyDataObject data;
|
||||
|
||||
// this method is only called once for this fragment
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// retain this fragment
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
public void setData(MyDataObject data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public MyDataObject getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p class="caution"><strong>Perhatian:</strong> Meskipun bisa menyimpan objek apa saja, Anda
|
||||
sama sekali tidak boleh meneruskan objek yang terkait dengan {@link android.app.Activity}, seperti {@link
|
||||
android.graphics.drawable.Drawable}, {@link android.widget.Adapter}, {@link android.view.View}
|
||||
atau objek lainnya mana pun yang terkait dengan {@link android.content.Context}. Jika Anda melakukannya, hal tersebut akan
|
||||
membocorkan semua tampilan dan sumber daya instance aktivitas semula. (Sumber daya yang bocor
|
||||
berarti bahwa aplikasi Anda tetap menyimpannya dan tidak bisa dijadikan kumpulan sampah, sehingga bisa banyak
|
||||
memori yang hilang.)</p>
|
||||
|
||||
<p>Selanjutnya gunakan {@link android.app.FragmentManager} untuk menambahkan fragmen ke aktivitas.
|
||||
Anda bisa memperoleh objek data dari fragmen saat aktivitas memulai kembali selama perubahan
|
||||
konfigurasi runtime. Misalnya, definisikan aktivitas Anda sebagai berikut:</p>
|
||||
|
||||
<pre>
|
||||
public class MyActivity extends Activity {
|
||||
|
||||
private RetainedFragment dataFragment;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
// find the retained fragment on activity restarts
|
||||
FragmentManager fm = getFragmentManager();
|
||||
dataFragment = (DataFragment) fm.findFragmentByTag(“data”);
|
||||
|
||||
// create the fragment and data the first time
|
||||
if (dataFragment == null) {
|
||||
// add the fragment
|
||||
dataFragment = new DataFragment();
|
||||
fm.beginTransaction().add(dataFragment, “data”).commit();
|
||||
// load the data from the web
|
||||
dataFragment.setData(loadMyData());
|
||||
}
|
||||
|
||||
// the data is available in dataFragment.getData()
|
||||
...
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
// store the data in the fragment
|
||||
dataFragment.setData(collectMyLoadedData());
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Dalam contoh ini, {@link android.app.Activity#onCreate(Bundle) onCreate()} menambahkan fragmen
|
||||
atau mengembalikan referensinya. {@link android.app.Activity#onCreate(Bundle) onCreate()} juga
|
||||
menyimpan objek stateful dalam instance fragmen.
|
||||
{@link android.app.Activity#onDestroy() onDestroy()} akan memperbarui objek stateful dalam
|
||||
instance fragmen yang dipertahankan.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="HandlingTheChange">Menangani Sendiri Perubahan Konfigurasi</h2>
|
||||
|
||||
<p>Jika aplikasi Anda tidak memerlukan pembaruan sumber daya selama perubahan konfigurasi
|
||||
tertentu <em>dan</em> Anda memiliki keterbatasan kinerja yang mengharuskan Anda untuk
|
||||
menghindari restart aktivitas, maka Anda bisa mendeklarasikan agar aktivitas Anda menangani sendiri perubahan
|
||||
konfigurasinya, sehingga mencegah sistem me-restart aktivitas.</p>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> Menangani sendiri perubahan konfigurasi bisa jauh lebih
|
||||
mempersulit penggunaan sumber daya alternatif, karena sistem tidak menerapkannya secara otomatis
|
||||
untuk Anda. Teknik ini harus dianggap sebagai usaha terakhir bila Anda harus menghindari restart
|
||||
karena perubahan konfigurasi dan tidak disarankan untuk sebagian besar aplikasi.</p>
|
||||
|
||||
<p>Untuk mendeklarasikan agar aktivitas Anda menangani perubahan konfigurasi, edit elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> yang sesuai
|
||||
dalam file manifes Anda agar menyertakan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
|
||||
android:configChanges}</a> dengan nilai yang mewakili konfigurasi yang ingin
|
||||
ditangani. Nilai yang memungkinkan tercantum dalam dokumentasi untuk atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
|
||||
android:configChanges}</a> (nilai paling sering digunakan adalah {@code "orientation"} untuk
|
||||
mencegah restart saat orientasi layar berubah dan {@code "keyboardHidden"} untuk mencegah
|
||||
restart saat ketersediaan keyboard berubah). Anda dapat mendeklarasikan beberapa nilai konfigurasi
|
||||
dalam atribut dengan memisahkannya menggunakan karakter pipa {@code |}.</p>
|
||||
|
||||
<p>Misalnya, kode manifes berikut menyatakan aktivitas yang menangani
|
||||
perubahan orientasi layar maupun perubahan ketersediaan keyboard:</p>
|
||||
|
||||
<pre>
|
||||
<activity android:name=".MyActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:label="@string/app_name">
|
||||
</pre>
|
||||
|
||||
<p>Sekarang, bila salah satu konfigurasi ini berubah, {@code MyActivity} tidak akan me-restart.
|
||||
Sebagai gantinya, {@code MyActivity} akan menerima panggilan ke {@link
|
||||
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. Metode ini
|
||||
meneruskan objek {@link android.content.res.Configuration} yang menetapkan
|
||||
konfigurasi perangkat baru. Dengan membaca bidang-bidang dalam {@link android.content.res.Configuration},
|
||||
Anda dapat menentukan konfigurasi baru dan membuat perubahan yang sesuai dengan memperbarui
|
||||
sumber daya yang digunakan dalam antarmuka. Pada saat
|
||||
metode ini dipanggil, objek {@link android.content.res.Resources} aktivitas Anda akan diperbarui untuk
|
||||
mengembalikan sumber daya berdasarkan konfigurasi baru, jadi Anda bisa dengan mudah
|
||||
me-reset elemen UI tanpa membuat sistem me-restart aktivitas Anda.</p>
|
||||
|
||||
<p class="caution"><strong>Perhatian:</strong> Mulai Android 3.2 (API level 13), <strong>
|
||||
"ukuran layar" juga berubah</strong> bila perangkat beralih orientasi antara potret
|
||||
dan lanskap. Jadi jika Anda tidak ingin runtime di-restart karena perubahan orientasi saat mengembangkan
|
||||
API level 13 atau yang lebih tinggi (sebagaimana dideklarasikan oleh atribut <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> dan <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a>
|
||||
), Anda harus menyertakan nilai {@code "screenSize"} selain nilai {@code
|
||||
"orientation"}. Yaitu Anda harus mendeklarasikan {@code
|
||||
android:configChanges="orientation|screenSize"}. Akan tetapi, jika aplikasi Anda menargetkan API level
|
||||
12 atau yang lebih rendah, maka aktivitas Anda akan selalu menangani sendiri perubahan konfigurasi ini (perubahan
|
||||
konfigurasi ini tidak me-restart aktivitas Anda, bahkan saat berjalan pada perangkat Android 3.2 atau yang lebih tinggi).</p>
|
||||
|
||||
<p>Misalnya, implementasi {@link
|
||||
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()} berikut akan
|
||||
memeriksa orientasi perangkat saat ini:</p>
|
||||
|
||||
<pre>
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
||||
// Checks the orientation of the screen
|
||||
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
|
||||
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
|
||||
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Objek {@link android.content.res.Configuration} mewakili semua konfigurasi
|
||||
saat ini, tidak hanya konfigurasi yang telah berubah. Seringkali Anda tidak perlu memperhatikan dengan persis bagaimana
|
||||
konfigurasi berubah dan cukup menetapkan kembali semua sumber daya yang memberikan alternatif untuk
|
||||
konfigurasi sedang ditangani. Misalnya, karena objek {@link
|
||||
android.content.res.Resources} sekarang diperbarui, Anda dapat me-reset
|
||||
setiap {@link android.widget.ImageView} dengan {@link android.widget.ImageView#setImageResource(int)
|
||||
setImageResource()}
|
||||
dan sumber daya yang sesuai untuk konfigurasi baru yang digunakan (seperti dijelaskan dalam <a href="providing-resources.html#AlternateResources">Menyediakan Sumber Daya</a>).</p>
|
||||
|
||||
<p>Perhatikan bahwa nilai-nilai dari bidang {@link
|
||||
android.content.res.Configuration} adalah integer yang sesuai dengan konstanta spesifik
|
||||
dari kelas {@link android.content.res.Configuration}. Untuk dokumentasi tentang konstanta
|
||||
yang harus digunakan di setiap bidang, lihat bidang yang sesuai dalam referensi {@link
|
||||
android.content.res.Configuration}.</p>
|
||||
|
||||
<p class="note"><strong>Ingatlah:</strong> Saat mendeklarasikan aktivitas untuk menangani perubahan
|
||||
konfigurasi, Anda bertanggung jawab untuk me-reset setiap elemen yang alternatifnya Anda berikan. Jika Anda
|
||||
mendeklarasikan aktivitas untuk menangani perubahan orientasi dan memiliki gambar yang harus berubah
|
||||
antara lanskap dan potret, Anda harus menetapkan kembali setiap sumber daya elemen selama {@link
|
||||
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}.</p>
|
||||
|
||||
<p>Jika Anda tidak perlu memperbarui aplikasi berdasarkan perubahan
|
||||
konfigurasi ini, sebagai gantinya Anda bisa saja <em>tidak</em> mengimplementasikan {@link
|
||||
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. Dalam
|
||||
hal ini, semua sumber daya yang digunakan sebelum perubahan konfigurasi akan tetap digunakan
|
||||
dan Anda hanya menghindari restart aktivitas. Akan tetapi, aplikasi Anda harus selalu
|
||||
bisa dimatikan dan di-restart dengan status sebelumnya tetap utuh, sehingga Anda jangan menganggap teknik
|
||||
ini sebagai jalan keluar untuk mempertahankan status selama daur hidup aktivitas normal. Tidak hanya
|
||||
karena ada perubahan konfigurasi lainnya yang tidak bisa Anda cegah untuk me-restart aplikasi, namun
|
||||
juga karena Anda harus menangani kejadian seperti saat pengguna meninggalkan aplikasi dan
|
||||
dimusnahkan sebelum pengguna kembali ke aplikasi.</p>
|
||||
|
||||
<p>Untuk informasi selengkapnya tentang perubahan konfigurasi yang bisa Anda tangani dalam aktivitas, lihat dokumentasi <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
|
||||
android:configChanges}</a> dan kelas {@link android.content.res.Configuration}
|
||||
.</p>
|
||||
90
docs/html-intl/intl/id/guide/topics/ui/controls.jd
Normal file
90
docs/html-intl/intl/id/guide/topics/ui/controls.jd
Normal file
@@ -0,0 +1,90 @@
|
||||
page.title=Kontrol Input
|
||||
parent.title=Antarmuka Pengguna
|
||||
parent.link=index.html
|
||||
@jd:body
|
||||
|
||||
<div class="figure" style="margin:0">
|
||||
<img src="{@docRoot}images/ui/ui-controls.png" alt="" style="margin:0" />
|
||||
</div>
|
||||
|
||||
<p>Kontrol input adalah komponen interaktif dalam antarmuka pengguna aplikasi Anda. Android menyediakan
|
||||
aneka ragam kontrol yang bisa Anda gunakan dalam UI, seperti tombol, bidang teks, bilah pencarian,
|
||||
kotak cek, tombol zoom, tombol toggle, dan masih banyak lagi.</p>
|
||||
|
||||
<p>Menambahkan sebuah kontrol input ke UI adalah semudah menambahkan satu elemen XML ke <a href="{@docRoot}guide/topics/ui/declaring-layout.html">layout XML</a>. Misalnya, inilah sebuah
|
||||
layout dengan satu bidang teks dan satu tombol:</p>
|
||||
|
||||
<pre style="clear:right">
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="horizontal">
|
||||
<EditText android:id="@+id/edit_message"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/edit_message" />
|
||||
<Button android:id="@+id/button_send"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/button_send"
|
||||
android:onClick="sendMessage" />
|
||||
</LinearLayout>
|
||||
</pre>
|
||||
|
||||
<p>Tiap kontrol input mendukung satu set kejadian input sehingga Anda bisa menangani berbagai kejadian seperti saat
|
||||
pengguna memasukkan teks atau menyentuh tombol.</p>
|
||||
|
||||
|
||||
<h2 id="CommonControls">Kontrol Umum</h2>
|
||||
<p>Berikut adalah daftar beberapa kontrol umum yang bisa Anda gunakan dalam aplikasi. Ikuti tautan ini untuk mengetahui
|
||||
selengkapnya tentang penggunaannya masing-masing.</p>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> Android menyediakan beberapa kontrol lain yang tidak tercantum
|
||||
di sini. Telusuri paket {@link android.widget} untuk mengetahui selengkapnya. Jika aplikasi Anda memerlukan
|
||||
semacam kontrol input tertentu, Anda bisa membangun <a href="{@docRoot}guide/topics/ui/custom-components.html">komponen custom</a> sendiri.</p>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th scope="col">Tipe Kontrol</th>
|
||||
<th scope="col">Keterangan</th>
|
||||
<th scope="col">Kelas Terkait</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="controls/button.html">Tombol</a></td>
|
||||
<td>Tombol tekan yang bisa ditekan, atau diklik, oleh pengguna untuk melakukan suatu tindakan.</td>
|
||||
<td>{@link android.widget.Button Button} </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="controls/text.html">Bidang teks</a></td>
|
||||
<td>Bidang teks yang bisa diedit. Anda bisa menggunakan widget <code>AutoCompleteTextView</code> untuk membuat widget entri teks yang menyediakan saran pelengkapan otomatis</td>
|
||||
<td>{@link android.widget.EditText EditText}, {@link android.widget.AutoCompleteTextView}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="controls/checkbox.html">Kotak cek</a></td>
|
||||
<td>Switch aktif/nonaktif yang bisa diubah oleh pengguna. Anda harus menggunakan kotak cek saat menampilkan sekumpulan opsi yang bisa dipilih pengguna dan bila keduanya mungkin terjadi bersamaan.</td>
|
||||
<td>{@link android.widget.CheckBox CheckBox} </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="controls/radiobutton.html">Tombol radio</a></td>
|
||||
<td>Mirip dengan kotak cek, hanya saja cuma satu opsi yang bisa dipilih dalam kumpulan tersebut.</td>
|
||||
<td>{@link android.widget.RadioGroup RadioGroup}
|
||||
<br>{@link android.widget.RadioButton RadioButton} </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="controls/togglebutton.html" style="white-space:nowrap">Tombol toggle</a></td>
|
||||
<td>Tombol aktif/nonaktif dengan indikator cahaya.</td>
|
||||
<td>{@link android.widget.ToggleButton ToggleButton} </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="controls/spinner.html">Spinner</a></td>
|
||||
<td>Daftar tarik-turun yang memungkinkan pengguna memilih salah satu dari serangkaian nilai.</td>
|
||||
<td>{@link android.widget.Spinner Spinner} </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="controls/pickers.html">Picker</a></td>
|
||||
<td>Dialog bagi pengguna untuk memilih satu nilai dari satu kumpulan dengan menggunakan tombol naik/turun atau dengan gerakan mengusap. Gunakan widget <code>DatePicker</code>code> untuk memasukkan nilai tanggal (bulan, hari, tahun) atau widget <code>TimePicker</code> untuk memasukkan nilai waktu (jam, menit, AM/PM), yang akan diformat secara otomatis untuk lokasi pengguna tersebut.</td>
|
||||
<td>{@link android.widget.DatePicker}, {@link android.widget.TimePicker}</td>
|
||||
</tr>
|
||||
</table>
|
||||
492
docs/html-intl/intl/id/guide/topics/ui/declaring-layout.jd
Normal file
492
docs/html-intl/intl/id/guide/topics/ui/declaring-layout.jd
Normal file
@@ -0,0 +1,492 @@
|
||||
page.title=Layout
|
||||
page.tags=view,viewgroup
|
||||
@jd:body
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#write">Tulis XML</a></li>
|
||||
<li><a href="#load">Muat Sumber Daya XML</a></li>
|
||||
<li><a href="#attributes">Atribut</a>
|
||||
<ol>
|
||||
<li><a href="#id">ID</a></li>
|
||||
<li><a href="#layout-params">Parameter Layout</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#Position">Posisi Layout</a></li>
|
||||
<li><a href="#SizePaddingMargins">Ukuran, Pengisi, dan Margin</a></li>
|
||||
<li><a href="#CommonLayouts">Layout Umum</a></li>
|
||||
<li><a href="#AdapterViews">Membangun Layout dengan Adaptor</a>
|
||||
<ol>
|
||||
<li><a href="#FillingTheLayout">Mengisi tampilan adaptor dengan data</a></li>
|
||||
<li><a href="#HandlingUserSelections">Menangani kejadian klik</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h2>Kelas-kelas utama</h2>
|
||||
<ol>
|
||||
<li>{@link android.view.View}</li>
|
||||
<li>{@link android.view.ViewGroup}</li>
|
||||
<li>{@link android.view.ViewGroup.LayoutParams}</li>
|
||||
</ol>
|
||||
|
||||
<h2>Lihat juga</h2>
|
||||
<ol>
|
||||
<li><a href="{@docRoot}training/basics/firstapp/building-ui.html">Membangun Antarmuka Pengguna
|
||||
Sederhana</a></li> </div>
|
||||
</div>
|
||||
|
||||
<p>Layout mendefinisikan struktur visual untuk antarmuka pengguna, seperti UI sebuah <a href="{@docRoot}guide/components/activities.html">aktivitas</a> atau <a href="{@docRoot}guide/topics/appwidgets/index.html">widget aplikasi</a>.
|
||||
Anda dapat mendeklarasikan layout dengan dua cara:</p>
|
||||
<ul>
|
||||
<li><strong>Deklarasikan elemen UI dalam XML</strong>. Android menyediakan sebuah kosakata XML
|
||||
sederhana yang sesuai dengan kelas dan subkelas View, seperti halnya untuk widget dan layout.</li>
|
||||
<li><strong>Buat instance elemen layout saat runtime</strong>. Aplikasi Anda
|
||||
bisa membuat objek View dan ViewGroup (dan memanipulasi propertinya) lewat program. </li>
|
||||
</ul>
|
||||
|
||||
<p>Kerangka kerja Android memberi Anda fleksibilitas untuk menggunakan salah satu atau kedua metode ini guna mendeklarasikan dan mengelola UI aplikasi Anda. Misalnya, Anda bisa mendeklarasikan layout default aplikasi Anda dalam XML, termasuk elemen-elemen layar yang akan muncul di dalamnya dan di propertinya. Anda nanti bisa menambahkan kode dalam aplikasi yang akan memodifikasi status objek layar, termasuk yang dideklarasikan dalam XML, saat runtime. </p>
|
||||
|
||||
<div class="sidebox-wrapper">
|
||||
<div class="sidebox">
|
||||
<ul>
|
||||
<li><a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT
|
||||
Plugin for Eclipse</a> menawarkan preview layout XML —
|
||||
Anda dengan file XML yang dibuka, pilih tab <strong>Layout</strong>.</li>
|
||||
<li>Anda juga harus mencoba alat
|
||||
<a href="{@docRoot}tools/debugging/debugging-ui.html#hierarchyViewer">Hierarchy Viewer</a>,
|
||||
untuk merunut layout — alat ini akan menampilkan nilai-nilai properti layout,
|
||||
menggambar bentuk kerangka dengan indikator pengisi/margin, dan tampilan yang dirender penuh selagi
|
||||
Anda merunut pada emulator atau perangkat.</li>
|
||||
<li>Alat <a href="{@docRoot}tools/debugging/debugging-ui.html#layoutopt">layoutopt</a> memungkinkan
|
||||
Anda menganalisis layout dan hierarki dengan untuk mengetahui ketidakefisienan atau masalah lainnya.</li>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Keuntungan mendeklarasikan UI dalam XML adalah karena hal ini memungkinkan Anda memisahkan penampilan aplikasi dari kode yang mengontrol perilakunya dengan lebih baik. Keterangan UI Anda bersifat eksternal bagi kode aplikasi Anda, yang berarti bahwa Anda bisa memodifikasi atau menyesuaikannya tanpa harus memodifikasi dan mengompilasi ulang kode sumber. Misalnya, Anda bisa membuat layout XML untuk berbagai orientasi layar, berbagai ukuran layar perangkat, dan berbagai bahasa. Selain itu, mendeklarasikan layout dalam XML akan mempermudah Anda memvisualisasikan struktur UI, sehingga lebih mudah merunut masalahnya. Karena itu, dokumen ini berfokus pada upaya mengajari Anda cara mendeklarasikan layout dalam XML. Jika Anda
|
||||
tertarik dalam membuat instance objek View saat runtime, lihat referensi kelas {@link android.view.ViewGroup} dan
|
||||
{@link android.view.View}.</p>
|
||||
|
||||
<p>Secara umum, kosakata XML untuk mendeklarasikan elemen UI mengikuti dengan sangat mirip struktur serta penamaan kelas dan metode, dengan nama elemen dipadankan dengan nama kelas dan nama atribut dipadankan dengan metode. Sebenarnya, pemadanan ini kerap kali begitu jelas sehingga Anda bisa menebak atribut XML yang berpadanan dengan sebuah metode kelas, atau menebak kelas yang berpadanan dengan sebuah elemen XML. Akan tetapi, perhatikan bahwa tidak semua kosakata identik. Dalam beberapa kasus, ada sedikit perbedaan penamaan. Misalnya
|
||||
, elemen EditText memiliki atribut <code>text</code> yang berpadanan dengan
|
||||
<code>EditText.setText()</code>. </p>
|
||||
|
||||
<p class="note"><strong>Tip:</strong> Ketahui selengkapnya berbagai tipe layout dalam <a href="{@docRoot}guide/topics/ui/layout-objects.html">Objek
|
||||
Layout Umum</a>. Ada juga sekumpulan tutorial tentang cara membangun berbagai layout dalam panduan tutorial
|
||||
<a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a>.</p>
|
||||
|
||||
<h2 id="write">Tulis XML</h2>
|
||||
|
||||
<p>Dengan menggunakan kosakata XML Android, Anda bisa mendesain secara cepat layout UI dan elemen layar yang dimuatnya, sama dengan cara membuat halaman web dalam HTML — dengan serangkaian elemen tersarang. </p>
|
||||
|
||||
<p>Tiap file layout harus berisi persis satu elemen akar, yang harus berupa sebuah objek View atau ViewGroup. Setelah mendefinisikan elemen akar, Anda bisa menambahkan objek atau widget layout tambahan sebagai elemen anak untuk membangun hierarki View yang mendefinisikan layout Anda secara bertahap. Misalnya, inilah layout XML yang menggunakan {@link android.widget.LinearLayout}
|
||||
vertikal untuk menyimpan {@link android.widget.TextView} dan {@link android.widget.Button}:</p>
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
<TextView android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello, I am a TextView" />
|
||||
<Button android:id="@+id/button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello, I am a Button" />
|
||||
</LinearLayout>
|
||||
</pre>
|
||||
|
||||
<p>Setelah Anda mendeklarasikan layout dalam XML, simpanlah file dengan ekstensi <code>.xml</code>,
|
||||
dalam direktori <code>res/layout/</code> proyek Android, sehingga nanti bisa dikompilasi dengan benar. </p>
|
||||
|
||||
<p>Informasi selengkapnya tentang sintaks untuk file XML layout tersedia dalam dokumen <a href="{@docRoot}guide/topics/resources/layout-resource.html">Sumber Daya Layout</a>.</p>
|
||||
|
||||
<h2 id="load">Muat Sumber Daya XML</h2>
|
||||
|
||||
<p>Saat mengompilasi aplikasi, masing-masing file layout XML akan dikompilasi dalam sebuah sumber daya
|
||||
{@link android.view.View}. Anda harus memuat sumber daya layout dari kode aplikasi, dalam implementasi
|
||||
callback {@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()}.
|
||||
Lakukan dengan memanggil <code>{@link android.app.Activity#setContentView(int) setContentView()}</code>,
|
||||
dengan meneruskan acuan ke sumber daya layout berupa:
|
||||
<code>R.layout.<em>layout_file_name</em></code>.
|
||||
Misalnya, jika XML layout Anda disimpan sebagai <code>main_layout.xml</code>, Anda akan memuatnya
|
||||
untuk Activity seperti ini:</p>
|
||||
<pre>
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main_layout);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Metode callback <code>onCreate()</code> dalam Activity dipanggil oleh kerangka kerja Android saat
|
||||
Activity Anda dijalankan (lihat diskusi tentang daur hidup, dalam dokumen
|
||||
<a href="{@docRoot}guide/components/activities.html#Lifecycle">Aktivitas</a>
|
||||
).</p>
|
||||
|
||||
|
||||
<h2 id="attributes">Atribut</h2>
|
||||
|
||||
<p>Setiap objek View dan ViewGroup mendukung variasi atribut XML-nya sendiri.
|
||||
Sebagian atribut bersifat spesifik untuk objek View (misalnya, TextView mendukung atribut <code>textSize</code>
|
||||
), namun atribut ini juga diwarisi oleh sembarang objek View yang dapat memperluas kelas ini.
|
||||
Sebagian atribut bersifat umum untuk semua objek View, karena diwarisi dari kelas View akar (seperti
|
||||
atribut <code>id</code>). Dan, atribut lain dianggap sebagai "parameter layout" yaitu
|
||||
atribut yang menjelaskan orientasi layout tertentu dari objek View, seperti yang didefinisikan oleh objek ViewGroup induk
|
||||
dari objek itu.</p>
|
||||
|
||||
<h3 id="id">ID</h3>
|
||||
|
||||
<p>Objek View apa saja dapat memiliki ID integer yang dikaitkan dengannya, untuk mengidentifikasi secara unik View dalam pohon.
|
||||
Bila aplikasi dikompilasi, ID ini akan diacu sebagai integer, namun ID biasanya
|
||||
ditetapkan dalam file XML layout sebagai string, dalam atribut <code>id</code>.
|
||||
Ini atribut XML yang umum untuk semua objek View
|
||||
(yang didefinisikan oleh kelas {@link android.view.View}) dan Anda akan sering sekali menggunakannya.
|
||||
Sintaks untuk ID dalam tag XML adalah:</p>
|
||||
<pre>android:id="@+id/my_button"</pre>
|
||||
|
||||
<p>Simbol "at" (@) pada awal string menunjukkan parser XML harus mengurai dan memperluas
|
||||
ID string selebihnya dan mengenalinya sebagai ID sumber daya. Simbol tanda tambah (+) berarti ini nama sumber daya baru yang harus
|
||||
dibuat dan ditambahkan ke sumber daya kita (dalam file <code>R.java</code>). Ada sejumlah sumber daya ID lain yang
|
||||
ditawarkan oleh kerangka kerja Android. Saat mengacu sebuah ID sumber daya Android, Anda tidak memerlukan simbol tanda tambah,
|
||||
namun harus menambahkan namespace paket <code>android</code>, sehingga:</p>
|
||||
<pre>android:id="@android:id/empty"</pre>
|
||||
<p>Dengan namespace paket <code>android</code> yang tersedia, kita sekarang mengacu ID dari kelas sumber daya <code>android.R</code>
|
||||
, daripada kelas sumber daya lokal.</p>
|
||||
|
||||
<p>Untuk membuat tampilan dan mengacunya dari aplikasi, pola yang umum adalah:</p>
|
||||
<ol>
|
||||
<li>Mendefinisikan tampilan/widget dalam file layout dan memberinya ID unik:
|
||||
<pre>
|
||||
<Button android:id="@+id/my_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/my_button_text"/>
|
||||
</pre>
|
||||
</li>
|
||||
<li>Kemudian buat instance objek tampilan dan tangkap instance itu dari layout
|
||||
(biasanya dalam metode <code>{@link android.app.Activity#onCreate(Bundle) onCreate()}</code>):
|
||||
<pre>
|
||||
Button myButton = (Button) findViewById(R.id.my_button);
|
||||
</pre>
|
||||
</li>
|
||||
</ol>
|
||||
<p>Mendefinisikan ID untuk objek tampilan adalah penting saat membuat {@link android.widget.RelativeLayout}.
|
||||
Dalam layout relatif, tampilan saudara bisa mendefinisikan layout secara relatif terhadap tampilan saudara lainnya,
|
||||
yang diacu melalui ID unik.</p>
|
||||
<p>ID tidak perlu unik di seluruh pohon, namun harus
|
||||
unik di bagian pohon yang Anda cari (yang mungkin sering kali seluruh pohon, jadi lebih baik
|
||||
benar-benar unik bila memungkinkan).</p>
|
||||
|
||||
|
||||
<h3 id="layout-params">Parameter Layout</h3>
|
||||
|
||||
<p>Atribut layout XML bernama <code>layout_<em>something</em></code> mendefinisikan
|
||||
parameter layout View yang cocok untuk ViewGroup tempatnya berada.</p>
|
||||
|
||||
<p>Setiap kelas ViewGroup mengimplementasikan kelas tersarang yang memperluas {@link
|
||||
android.view.ViewGroup.LayoutParams}. Subkelas ini
|
||||
berisi tipe properti yang mendefinisikan ukuran dan posisi masing-masing tampilan anak, sebagaimana
|
||||
mestinya untuk grup tampilan. Seperti yang bisa Anda lihat dalam gambar 1,
|
||||
grup tampilan induk mendefinisikan parameter layout untuk masing-masing tampilan anak (termasuk grup tampilan anak).</p>
|
||||
|
||||
<img src="{@docRoot}images/layoutparams.png" alt="" />
|
||||
<p class="img-caption"><strong>Gambar 1.</strong> Visualisasi hierarki tampilan dengan parameter layout
|
||||
yang dikaitkan dengan tiap tampilan.</p>
|
||||
|
||||
<p>Perhatikan bahwa setiap subkelas LayoutParams memiliki sintaksnya sendiri untuk menetapkan
|
||||
nilai-nilai. Tiap elemen anak harus mendefinisikan LayoutParams yang semestinya bagi induknya,
|
||||
meskipun elemen itu bisa juga mendefinisikan LayoutParams untuk anak-anaknya sendiri. </p>
|
||||
|
||||
<p>Semua grup tampilan berisi lebar dan tinggi (<code>layout_width</code> dan
|
||||
<code>layout_height</code>), dan masing-masing tampilan harus mendefinisikannya. Banyak
|
||||
LayoutParams yang juga menyertakan margin dan border opsional. <p>
|
||||
|
||||
<p>Anda bisa menetapkan lebar dan tinggi dengan ukuran persis, meskipun Anda mungkin
|
||||
tidak ingin sering-sering melakukannya. Lebih sering, Anda akan menggunakan salah satu konstanta ini untuk
|
||||
mengatur lebar atau tinggi: </p>
|
||||
|
||||
<ul>
|
||||
<li><var>wrap_content</var> memberi tahu tampilan Anda agar menyesuaikan sendiri ukurannya dengan dimensi
|
||||
yang dibutuhkan oleh isinya.</li>
|
||||
<li><var>match_parent</var> (bernama <var>fill_parent</var> sebelum API Level 8)
|
||||
memberi tahu tampilan Anda agar menjadi sebesar yang diperbolehkan oleh grup tampilan induknya.</li>
|
||||
</ul>
|
||||
|
||||
<p>Secara umum, menetapkan lebar dan tinggi layout dengan satuan mutlak seperti
|
||||
piksel tidaklah disarankan. Melainkan dengan menggunakan ukuran relatif seperti
|
||||
satuan piksel yang tidak bergantung pada kerapatan (<var>dp</var>), <var>wrap_content</var>, atau
|
||||
<var>match_parent</var>, adalah sebuah pendekatan yang lebih baik, karena membantu memastikan bahwa
|
||||
aplikasi Anda akan ditampilkan dengan benar pada berbagai ukuran layar perangkat.
|
||||
Tipe ukuran yang diterima didefinisikan dalam dokumen
|
||||
<a href="{@docRoot}guide/topics/resources/available-resources.html#dimension">
|
||||
Sumber Daya yang Tersedia</a>.</p>
|
||||
|
||||
|
||||
<h2 id="Position">Posisi Layout</h2>
|
||||
<p>
|
||||
Geometri tampilan adalah persegi panjang. Sebuah tampilan memiliki lokasi,
|
||||
yang dinyatakan berupa sepasang koordinat <em>kiri</em> dan <em>atas</em>, dan
|
||||
dua dimensi, yang dinyatakan berupa lebar dan tinggi. Satuan untuk lokasi
|
||||
dan dimensi adalah piksel.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Lokasi tampilan dapat diambil dengan memanggil metode
|
||||
{@link android.view.View#getLeft()} dan {@link android.view.View#getTop()}. Metode terdahulu menghasilkan koordinat kiri, atau X,
|
||||
persegi panjang yang mewakili tampilan. Metode selanjutnya menghasilkan koordinat
|
||||
atas, atau Y, persegi panjang yang mewakili tampilan. Kedua metode ini
|
||||
menghasilkan lokasi tampilan relatif terhadap induknya. Misalnya,
|
||||
bila <code>getLeft()</code> menghasilkan 20, berarti tampilan berlokasi 20 piksel ke
|
||||
kanan dari tepi kiri induk langsungnya.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Selain itu, beberapa metode praktis ditawarkan untuk menghindari komputasi yang tidak perlu,
|
||||
yakni {@link android.view.View#getRight()} dan {@link android.view.View#getBottom()}.
|
||||
Kedua metode ini menghasilkan koordinat tepi kanan dan bawah
|
||||
persegi panjang yang mewakili tampilan. Misalnya, memanggil {@link android.view.View#getRight()}
|
||||
serupa dengan komputasi berikut: <code>getLeft() + getWidth()</code>.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="SizePaddingMargins">Ukuran, Pengisi, dan Margin</h2>
|
||||
<p>
|
||||
Ukuran tampilan dinyatakan dengan lebar dan tinggi. Tampilan sebenarnya
|
||||
memiliki dua pasang nilai lebar dan tinggi.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Sepasang pertama disebut <em>lebar terukur</em> dan
|
||||
<em>tinggi terukur</em>. Dimensi ini mendefinisikan seberapa besar tampilan yang diinginkan
|
||||
dalam induknya. Dimensi
|
||||
terukur bisa diperoleh dengan memanggil {@link android.view.View#getMeasuredWidth()}
|
||||
dan {@link android.view.View#getMeasuredHeight()}.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Sepasang kedua cukup disebut dengan <em>lebar</em> dan <em>tinggi</em>, atau
|
||||
kadang-kadang <em>lebar penggambaran</em> dan <em>tinggi penggambaran</em>. Dimensi-dimensi ini
|
||||
mendefinisikan ukuran tampilan sebenarnya pada layar, saat digambar dan
|
||||
setelah layout. Nilai-nilai ini mungkin, namun tidak harus, berbeda dengan
|
||||
lebar dan tinggi terukur. Lebar dan tinggi bisa diperoleh dengan memanggil
|
||||
{@link android.view.View#getWidth()} dan {@link android.view.View#getHeight()}.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Untuk mengukur dimensinya, tampilan akan memperhitungkan pengisinya (padding). Pengisi
|
||||
dinyatakan dalam piksel untuk bagian kiri, atas, kanan, dan bawah tampilan.
|
||||
Pengisi bisa digunakan untuk meng-offset isi tampilan dengan
|
||||
piksel dalam jumlah tertentu. Misalnya, pengisi kiri sebesar 2 akan mendorong isi tampilan sebanyak
|
||||
2 piksel ke kanan dari tepi kiri. Pengisi bisa diatur menggunakan
|
||||
metode {@link android.view.View#setPadding(int, int, int, int)} dan diketahui dengan memanggil
|
||||
{@link android.view.View#getPaddingLeft()}, {@link android.view.View#getPaddingTop()},
|
||||
{@link android.view.View#getPaddingRight()}, dan {@link android.view.View#getPaddingBottom()}.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Meskipun bisa mendefinisikan pengisi, tampilan tidak menyediakan dukungan untuk
|
||||
margin. Akan tetapi, grup tampilan menyediakan dukungan tersebut. Lihat
|
||||
{@link android.view.ViewGroup} dan
|
||||
{@link android.view.ViewGroup.MarginLayoutParams} untuk informasi lebih jauh.
|
||||
</p>
|
||||
|
||||
<p>Untuk informasi selengkapnya tentang dimensi, lihat
|
||||
<a href="{@docRoot}guide/topics/resources/more-resources.html#Dimension">Nilai-Nilai Dimensi</a>.
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<style type="text/css">
|
||||
div.layout {
|
||||
float:left;
|
||||
width:200px;
|
||||
margin:0 0 20px 20px;
|
||||
}
|
||||
div.layout.first {
|
||||
margin-left:0;
|
||||
clear:left;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="CommonLayouts">Layout Umum</h2>
|
||||
|
||||
<p>Tiap subkelas dari kelas {@link android.view.ViewGroup} menyediakan cara unik untuk menampilkan
|
||||
tampilan yang Anda sarangkan di dalamnya. Di bawah ini adalah beberapa tipe layout lebih umum yang dibuat
|
||||
ke dalam platform Android.</p>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> Walaupun Anda bisa menyarangkan satu atau beberapa layout dalam
|
||||
layout lain untuk mendapatkan desain UI, Anda harus berusaha menjaga hierarki layout sedangkal
|
||||
mungkin. Layout Anda akan digambar lebih cepat jika memiliki layout tersarang yang lebih sedikit (hierarki tampilan yang melebar
|
||||
lebih baik daripada hierarki tampilan yang dalam).</p>
|
||||
|
||||
<!--
|
||||
<h2 id="framelayout">FrameLayout</h2>
|
||||
<p>{@link android.widget.FrameLayout FrameLayout} is the simplest type of layout
|
||||
object. It's basically a blank space on your screen that you can
|
||||
later fill with a single object — for example, a picture that you'll swap in and out.
|
||||
All child elements of the FrameLayout are pinned to the top left corner of the screen; you cannot
|
||||
specify a different location for a child view. Subsequent child views will simply be drawn over
|
||||
previous ones,
|
||||
partially or totally obscuring them (unless the newer object is transparent).
|
||||
</p>
|
||||
-->
|
||||
|
||||
|
||||
<div class="layout first">
|
||||
<h4><a href="layout/linear.html">Layout Linier</a></h4>
|
||||
<a href="layout/linear.html"><img src="{@docRoot}images/ui/linearlayout-small.png" alt="" /></a>
|
||||
<p>Layout yang mengatur anak-anaknya menjadi satu baris horizontal atau vertikal. Layout ini
|
||||
akan membuat scrollbar jika panjang jendela melebihi panjang layar.</p>
|
||||
</div>
|
||||
|
||||
<div class="layout">
|
||||
<h4><a href="layout/relative.html">Layout Relatif</a></h4>
|
||||
<a href="layout/relative.html"><img src="{@docRoot}images/ui/relativelayout-small.png" alt="" /></a>
|
||||
<p>Memungkinkan Anda menentukan lokasi objek anak relatif terhadap satu sama lain (anak A di
|
||||
kiri anak B) atau terhadap induk (disejajarkan dengan atas induknya).</p>
|
||||
</div>
|
||||
|
||||
<div class="layout">
|
||||
<h4><a href="{@docRoot}guide/webapps/webview.html">Tampilan Web</a></h4>
|
||||
<a href="{@docRoot}guide/webapps/webview.html"><img src="{@docRoot}images/ui/webview-small.png" alt="" /></a>
|
||||
<p>Menampilkan halaman web.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="AdapterViews" style="clear:left">Membangun Layout dengan Adaptor</h2>
|
||||
|
||||
<p>Bila isi layout bersifat dinamis atau tidak dipastikan sebelumnya, Anda bisa menggunakan layout yang menjadi
|
||||
subkelas {@link android.widget.AdapterView} untuk mengisi layout dengan tampilan saat runtime.
|
||||
Subkelas dari kelas {@link android.widget.AdapterView} menggunakan {@link android.widget.Adapter} untuk
|
||||
mengikat data ke layoutnya. {@link android.widget.Adapter} berfungsi sebagai penghubung antara sumber data
|
||||
dan layout{@link android.widget.AdapterView}—{@link android.widget.Adapter}
|
||||
menarik data (dari suatu sumber seperti larik (array) atau query database) dan mengubah setiap entri
|
||||
menjadi tampilan yang bisa ditambahkan ke dalam layout {@link android.widget.AdapterView}.</p>
|
||||
|
||||
<p>Layout umum yang didukung oleh adaptor meliputi:</p>
|
||||
|
||||
<div class="layout first">
|
||||
<h4><a href="layout/listview.html">Tampilan Daftar</a></h4>
|
||||
<a href="layout/listview.html"><img src="{@docRoot}images/ui/listview-small.png" alt="" /></a>
|
||||
<p>Menampilkan daftar kolom tunggal yang bergulir.</p>
|
||||
</div>
|
||||
|
||||
<div class="layout">
|
||||
<h4><a href="layout/gridview.html">Tampilan Petak</a></h4>
|
||||
<a href="layout/gridview.html"><img src="{@docRoot}images/ui/gridview-small.png" alt="" /></a>
|
||||
<p>Menampilkan petak bergulir yang terdiri atas kolom dan baris.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h3 id="FillingTheLayout" style="clear:left">Mengisi tampilan adaptor dengan data</h3>
|
||||
|
||||
<p>Anda bisa mengisi {@link android.widget.AdapterView} seperti {@link android.widget.ListView} atau
|
||||
{@link android.widget.GridView} dengan mengikat instance {@link android.widget.AdapterView} ke
|
||||
{@link android.widget.Adapter}, yang akan mengambil data dari sumber eksternal dan membuat {@link
|
||||
android.view.View} yang mewakili tiap entri data.</p>
|
||||
|
||||
<p>Android menyediakan beberapa subkelas {@link android.widget.Adapter} yang berguna untuk
|
||||
menarik berbagai jenis data dan membangun tampilan untuk {@link android.widget.AdapterView}. Dua
|
||||
adaptor yang paling umum adalah:</p>
|
||||
|
||||
<dl>
|
||||
<dt>{@link android.widget.ArrayAdapter}</dt>
|
||||
<dd>Gunakan adaptor ini bila sumber data Anda berupa larik. Secara default, {@link
|
||||
android.widget.ArrayAdapter} akan membuat tampilan untuk tiap elemen larik dengan memanggil {@link
|
||||
java.lang.Object#toString()} pada tiap elemen dan menempatkan isinya dalam {@link
|
||||
android.widget.TextView}.
|
||||
<p>Misalnya, jika Anda memiliki satu larik string yang ingin ditampilkan dalam {@link
|
||||
android.widget.ListView}, buatlah {@link android.widget.ArrayAdapter} baru dengan konstruktor
|
||||
untuk menentukan layout setiap string dan larik string:</p>
|
||||
<pre>
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
|
||||
android.R.layout.simple_list_item_1, myStringArray);
|
||||
</pre>
|
||||
<p>Argumen-argumen untuk konstruktor ini adalah:</p>
|
||||
<ul>
|
||||
<li>{@link android.content.Context} aplikasi Anda</li>
|
||||
<li>Layout yang berisi {@link android.widget.TextView} untuk tiap string dalam larik</li>
|
||||
<li>Larik string</li>
|
||||
</ul>
|
||||
<p>Kemudian tinggal panggil
|
||||
{@link android.widget.ListView#setAdapter setAdapter()} pada {@link android.widget.ListView} Anda:</p>
|
||||
<pre>
|
||||
ListView listView = (ListView) findViewById(R.id.listview);
|
||||
listView.setAdapter(adapter);
|
||||
</pre>
|
||||
|
||||
<p>Untuk menyesuaikan penampilan setiap item, Anda bisa mengesampingkan metode {@link
|
||||
java.lang.Object#toString()} bagi objek dalam larik Anda. Atau, untuk membuat tampilan tiap
|
||||
elemen selain {@link android.widget.TextView} (misalnya, jika Anda menginginkan
|
||||
{@link android.widget.ImageView} bagi setiap item larik), perluas kelas {@link
|
||||
android.widget.ArrayAdapter} dan kesampingkan {@link android.widget.ArrayAdapter#getView
|
||||
getView()} agar memberikan tipe tampilan yang Anda inginkan bagi tiap item.</p>
|
||||
|
||||
</dd>
|
||||
|
||||
<dt>{@link android.widget.SimpleCursorAdapter}</dt>
|
||||
<dd>Gunakan adaptor ini bila data Anda berasal dari {@link android.database.Cursor}. Saat
|
||||
menggunakan {@link android.widget.SimpleCursorAdapter}, Anda harus menentukan layout yang akan digunakan untuk tiap
|
||||
baris dalam {@link android.database.Cursor} dan di kolom mana di {@link android.database.Cursor}
|
||||
harus memasukkan tampilan layout. Misalnya, jika Anda ingin untuk membuat daftar
|
||||
nama orang dan nomor telepon, Anda bisa melakukan query yang menghasilkan {@link
|
||||
android.database.Cursor} yang berisi satu baris untuk tiap orang dan kolom-kolom untuk nama dan
|
||||
nomor. Selanjutnya Anda membuat larik string yang menentukan kolom dari {@link
|
||||
android.database.Cursor} yang Anda inginkan dalam layout untuk setiap hasil dan larik integer yang menentukan
|
||||
tampilan yang sesuai untuk menempatkan masing-masing kolom:</p>
|
||||
<pre>
|
||||
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
|
||||
ContactsContract.CommonDataKinds.Phone.NUMBER};
|
||||
int[] toViews = {R.id.display_name, R.id.phone_number};
|
||||
</pre>
|
||||
<p>Bila Anda membuat instance {@link android.widget.SimpleCursorAdapter}, teruskan layout yang akan digunakan untuk
|
||||
setiap hasil, {@link android.database.Cursor} yang berisi hasil tersebut, dan dua larik ini:</p>
|
||||
<pre>
|
||||
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
|
||||
R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
|
||||
ListView listView = getListView();
|
||||
listView.setAdapter(adapter);
|
||||
</pre>
|
||||
<p>{@link android.widget.SimpleCursorAdapter} kemudian membuat tampilan untuk tiap baris dalam
|
||||
{@link android.database.Cursor} dengan layout yang disediakan dengan memasukkan setiap item {@code
|
||||
fromColumns} ke dalam tampilan {@code toViews} yang sesuai.</p></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
<p>Jika, selama aplikasi berjalan, Anda mengubah data sumber yang dibaca oleh
|
||||
adaptor, maka Anda harus memanggil {@link android.widget.ArrayAdapter#notifyDataSetChanged()}. Hal ini akan
|
||||
memberi tahu tampilan yang bersangkutan bahwa data telah berubah dan tampilan harus memperbarui dirinya sendiri.</p>
|
||||
|
||||
|
||||
|
||||
<h3 id="HandlingUserSelections">Menangani kejadian klik</h3>
|
||||
|
||||
<p>Anda bisa merespons kejadian klik pada setiap item dalam {@link android.widget.AdapterView} dengan
|
||||
menerapkan antarmuka {@link android.widget.AdapterView.OnItemClickListener}. Misalnya:</p>
|
||||
|
||||
<pre>
|
||||
// Create a message handling object as an anonymous class.
|
||||
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
|
||||
public void onItemClick(AdapterView parent, View v, int position, long id) {
|
||||
// Do something in response to the click
|
||||
}
|
||||
};
|
||||
|
||||
listView.setOnItemClickListener(mMessageClickedHandler);
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
798
docs/html-intl/intl/id/guide/topics/ui/dialogs.jd
Normal file
798
docs/html-intl/intl/id/guide/topics/ui/dialogs.jd
Normal file
@@ -0,0 +1,798 @@
|
||||
page.title=Dialog
|
||||
page.tags=alertdialog,dialogfragment
|
||||
|
||||
@jd:body
|
||||
|
||||
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#DialogFragment">Membuat Fragmen Dialog</a></li>
|
||||
<li><a href="#AlertDialog">Membuat Dialog Peringatan</a>
|
||||
<ol>
|
||||
<li><a href="#AddingButtons">Menambahkan tombol</a></li>
|
||||
<li><a href="#AddingAList">Menambahkan daftar</a></li>
|
||||
<li><a href="#CustomLayout">Membuat Layout Custom</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#PassingEvents">Meneruskan Kejadian Kembali ke Host Dialog</a></li>
|
||||
<li><a href="#ShowingADialog">Menampilkan Dialog</a></li>
|
||||
<li><a href="#FullscreenDialog">Menampilkan Dialog sebagai Layar Penuh atau Fragmen Tertanam</a>
|
||||
<ol>
|
||||
<li><a href="#ActivityAsDialog">Menampilkan aktivitas sebagai dialog pada layar besar</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#DismissingADialog">Menutup Dialog</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>Kelas-kelas utama</h2>
|
||||
<ol>
|
||||
<li>{@link android.app.DialogFragment}</li>
|
||||
<li>{@link android.app.AlertDialog}</li>
|
||||
</ol>
|
||||
|
||||
<h2>Lihat juga</h2>
|
||||
<ol>
|
||||
<li><a href="{@docRoot}design/building-blocks/dialogs.html">Panduan desain dialog</a></li>
|
||||
<li><a href="{@docRoot}guide/topics/ui/controls/pickers.html">Picker</a> (dialog Tanggal/Waktu)</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Dialog adalah jendela kecil yang meminta pengguna untuk
|
||||
membuat keputusan atau memasukkan informasi tambahan. Dialog tidak mengisi layar dan
|
||||
biasanya digunakan untuk kejadian modal yang mengharuskan pengguna untuk melakukan tindakan sebelum bisa melanjutkan.</p>
|
||||
|
||||
<div class="note design">
|
||||
<p><strong>Desain Dialog</strong></p>
|
||||
<p>Untuk informasi tentang cara mendesain dialog, termasuk saran
|
||||
untuk bahasa, bacalah panduan Desain <a href="{@docRoot}design/building-blocks/dialogs.html">dialog</a>.</p>
|
||||
</div>
|
||||
|
||||
<img src="{@docRoot}images/ui/dialogs.png" />
|
||||
|
||||
<p>Kelas {@link android.app.Dialog} adalah kelas basis untuk dialog, namun Anda
|
||||
harus menghindari pembuatan instance {@link android.app.Dialog} secara langsung.
|
||||
Sebagai gantinya, gunakan salah satu subkelas berikut:</p>
|
||||
<dl>
|
||||
<dt>{@link android.app.AlertDialog}</dt>
|
||||
<dd>Dialog yang bisa menampilkan judul, hingga tiga tombol, daftar
|
||||
item yang dapat dipilih, atau layout custom.</dd>
|
||||
<dt>{@link android.app.DatePickerDialog} atau {@link android.app.TimePickerDialog}</dt>
|
||||
<dd>Dialog berisi UI yang sudah didefinisikan dan memungkinkan pengguna memilih tanggal atau waktu.</dd>
|
||||
</dl>
|
||||
|
||||
<div class="sidebox">
|
||||
<h2>Hindari ProgressDialog</h2>
|
||||
<p>Android menyertakan kelas dialog lain yang disebut
|
||||
{@link android.app.ProgressDialog} yang menampilkan dialog berisi progress-bar. Akan tetapi, jika Anda
|
||||
perlu menunjukkan kemajuan pemuatan ataupun kemajuan yang tidak pasti, maka Anda harus mengikuti
|
||||
panduan desain untuk <a href="{@docRoot}design/building-blocks/progress.html">Kemajuan &
|
||||
Aktivitas</a> dan menggunakan {@link android.widget.ProgressBar} dalam layout Anda.</p>
|
||||
</div>
|
||||
|
||||
<p>Kelas-kelas ini mendefinisikan gaya dan struktur dialog Anda, namun Anda harus
|
||||
menggunakan {@link android.support.v4.app.DialogFragment} sebagai kontainer dialog Anda.
|
||||
Kelas {@link android.support.v4.app.DialogFragment} menyediakan semua kontrol yang Anda
|
||||
perlukan untuk membuat dialog dan mengelola penampilannya, sebagai ganti memanggil metode
|
||||
pada objek {@link android.app.Dialog}.</p>
|
||||
|
||||
<p>Menggunakan {@link android.support.v4.app.DialogFragment} untuk mengelola dialog
|
||||
akan memastikan bahwa kelas itu menangani kejadian daur hidup
|
||||
dengan benar seperti ketika pengguna menekan tombol <em>Back</em> atau memutar layar. Kelas {@link
|
||||
android.support.v4.app.DialogFragment} juga memungkinkan Anda menggunakan ulang dialog UI sebagai
|
||||
komponen yang bisa ditanamkan dalam UI yang lebih besar, persis seperti {@link
|
||||
android.support.v4.app.Fragment} tradisional (seperti saat Anda ingin dialog UI muncul berbeda
|
||||
pada layar besar dan kecil).</p>
|
||||
|
||||
<p>Bagian-bagian berikutnya dalam panduan ini akan menjelaskan cara menggunakan {@link
|
||||
android.support.v4.app.DialogFragment} yang dikombinasikan dengan objek {@link android.app.AlertDialog}
|
||||
. Jika Anda ingin membuat picker tanggal atau waktu, Anda harus membaca panduan
|
||||
<a href="{@docRoot}guide/topics/ui/controls/pickers.html">Picker</a>.</p>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong>
|
||||
Karena kelas {@link android.app.DialogFragment} mulanya ditambahkan pada
|
||||
Android 3.0 (API level 11), dokumen ini menjelaskan cara menggunakan kelas {@link
|
||||
android.support.v4.app.DialogFragment} yang disediakan bersama <a href="{@docRoot}tools/support-library/index.html">Pustaka Dukungan</a>. Dengan menambahkan pustaka ini
|
||||
ke aplikasi, Anda bisa menggunakan {@link android.support.v4.app.DialogFragment} dan berbagai
|
||||
API lain pada perangkat yang menjalankan Android 1.6 atau yang lebih tinggi. Jika versi minimum yang didukung aplikasi Anda
|
||||
adalah API level 11 atau yang lebih tinggi, maka Anda bisa menggunakan versi kerangka kerja {@link
|
||||
android.app.DialogFragment}, namun ketahuilah bahwa tautan dalam dokumen ini adalah untuk API
|
||||
pustaka dukungan. Saat menggunakan pustaka dukungan,
|
||||
pastikan Anda mengimpor kelas <code>android.support.v4.app.DialogFragment</code>
|
||||
dan <em>bukan</em> <code>android.app.DialogFragment</code>.</p>
|
||||
|
||||
|
||||
<h2 id="DialogFragment">Membuat Fragmen Dialog</h2>
|
||||
|
||||
<p>Anda bisa menghasilkan beragam rancangan dialog—termasuk
|
||||
layout custom dan desain yang dijelaskan dalam panduan desain <a href="{@docRoot}design/building-blocks/dialogs.html">Dialog</a>
|
||||
—dengan memperluas
|
||||
{@link android.support.v4.app.DialogFragment} dan membuat {@link android.app.AlertDialog}
|
||||
dalam metode callback {@link android.support.v4.app.DialogFragment#onCreateDialog
|
||||
onCreateDialog()}.</p>
|
||||
|
||||
<p>Misalnya, berikut ini sebuah {@link android.app.AlertDialog} dasar yang dikelola dalam
|
||||
{@link android.support.v4.app.DialogFragment}:</p>
|
||||
|
||||
<pre>
|
||||
public class FireMissilesDialogFragment extends DialogFragment {
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
// Use the Builder class for convenient dialog construction
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setMessage(R.string.dialog_fire_missiles)
|
||||
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
// FIRE ZE MISSILES!
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
// User cancelled the dialog
|
||||
}
|
||||
});
|
||||
// Create the AlertDialog object and return it
|
||||
return builder.create();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<div class="figure" style="width:290px;margin:0 0 0 20px">
|
||||
<img src="{@docRoot}images/ui/dialog_buttons.png" alt="" />
|
||||
<p class="img-caption"><strong>Gambar 1.</strong>
|
||||
Dialog dengan satu pesan dan dua tombol tindakan.</p>
|
||||
</div>
|
||||
|
||||
<p>Sekarang, bila Anda membuat instance kelas ini dan memanggil {@link
|
||||
android.support.v4.app.DialogFragment#show show()} pada objek itu, dialog akan muncul seperti
|
||||
yang ditampilkan dalam gambar 1.</p>
|
||||
|
||||
<p>Bagian berikutnya menjelaskan lebih jauh tentang penggunaan API {@link android.app.AlertDialog.Builder}
|
||||
untuk membuat dialog.</p>
|
||||
|
||||
<p>Bergantung pada seberapa rumit dialog tersebut, Anda bisa menerapkan berbagai metode callback lain
|
||||
dalam {@link android.support.v4.app.DialogFragment}, termasuk semua
|
||||
<a href="{@docRoot}guide/components/fragments.html#Lifecycle">metode daur hidup fragmen</a> dasar.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="AlertDialog">Membuat Dialog Peringatan</h2>
|
||||
|
||||
|
||||
<p>Kelas {@link android.app.AlertDialog} memungkinkan Anda membuat berbagai desain dialog dan
|
||||
seringkali satu-satunya kelas dialog yang akan Anda perlukan.
|
||||
Seperti yang ditampilkan dalam gambar 2, ada tiga area pada dialog peringatan:</p>
|
||||
|
||||
<div class="figure" style="width:311px;margin-top:0">
|
||||
<img src="{@docRoot}images/ui/dialogs_regions.png" alt="" style="margin-bottom:0" />
|
||||
<p class="img-caption"><strong>Gambar 2.</strong> Layout dialog.</p>
|
||||
</div>
|
||||
|
||||
<ol>
|
||||
<li><b>Judul</b>
|
||||
<p>Area ini opsional dan hanya boleh digunakan bila area konten
|
||||
ditempati oleh pesan terperinci, daftar, atau layout custom. Jika Anda perlu menyatakan
|
||||
pesan atau pertanyaan sederhana (seperti dialog dalam gambar 1), Anda tidak memerlukan judul.</li>
|
||||
<li><b>Area konten</b>
|
||||
<p>Area ini bisa menampilkan pesan, daftar, atau layout custom lainnya.</p></li>
|
||||
<li><b>Tombol tindakan</b>
|
||||
<p>Tidak boleh ada lebih dari tiga tombol tindakan dalam sebuah dialog.</p></li>
|
||||
</ol>
|
||||
|
||||
<p>Kelas {@link android.app.AlertDialog.Builder}
|
||||
menyediakan API yang memungkinkan Anda membuat {@link android.app.AlertDialog}
|
||||
dengan jenis konten ini, termasuk layout custom.</p>
|
||||
|
||||
<p>Untuk membuat {@link android.app.AlertDialog}:</p>
|
||||
|
||||
<pre>
|
||||
<b>// 1. Instantiate an {@link android.app.AlertDialog.Builder} with its constructor</b>
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
|
||||
<b>// 2. Chain together various setter methods to set the dialog characteristics</b>
|
||||
builder.setMessage(R.string.dialog_message)
|
||||
.setTitle(R.string.dialog_title);
|
||||
|
||||
<b>// 3. Get the {@link android.app.AlertDialog} from {@link android.app.AlertDialog.Builder#create()}</b>
|
||||
AlertDialog dialog = builder.create();
|
||||
</pre>
|
||||
|
||||
<p>Topik-topik selanjutnya menampilkan cara mendefinisikan berbagai atribut dialog dengan menggunakan
|
||||
kelas {@link android.app.AlertDialog.Builder}.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 id="AddingButtons">Menambahkan tombol</h3>
|
||||
|
||||
<p>Untuk menambahkan tombol tindakan seperti dalam gambar 2,
|
||||
panggil metode {@link android.app.AlertDialog.Builder#setPositiveButton setPositiveButton()} dan
|
||||
{@link android.app.AlertDialog.Builder#setNegativeButton setNegativeButton()}:</p>
|
||||
|
||||
<pre style="clear:right">
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
// Add the buttons
|
||||
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
// User clicked OK button
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
// User cancelled the dialog
|
||||
}
|
||||
});
|
||||
// Set other dialog properties
|
||||
...
|
||||
|
||||
// Create the AlertDialog
|
||||
AlertDialog dialog = builder.create();
|
||||
</pre>
|
||||
|
||||
<p>Metode <code>set...Button()</code> mengharuskan adanya judul bagi tombol (disediakan
|
||||
oleh suatu <a href="{@docRoot}guide/topics/resources/string-resource.html">sumber daya string</a>) dan
|
||||
{@link android.content.DialogInterface.OnClickListener} yang mendefinisikan tindakan yang diambil
|
||||
bila pengguna menekan tombol.</p>
|
||||
|
||||
<p>Ada tiga macam tombol tindakan yang Anda bisa tambahkan:</p>
|
||||
<dl>
|
||||
<dt>Positif</dt>
|
||||
<dd>Anda harus menggunakan tipe ini untuk menerima dan melanjutkan tindakan (tindakan "OK").</dd>
|
||||
<dt>Negatif</dt>
|
||||
<dd>Anda harus menggunakan tipe ini untuk membatalkan tindakan.</dd>
|
||||
<dt>Netral</dt>
|
||||
<dd>Anda harus menggunakan tipe ini bila pengguna mungkin tidak ingin melanjutkan tindakan,
|
||||
namun tidak ingin membatalkan. Tipe ini muncul antara tombol positif dan
|
||||
tombol negatif. Misalnya, tindakan bisa berupa "Ingatkan saya nanti".</dd>
|
||||
</dl>
|
||||
|
||||
<p>Anda hanya bisa menambahkan salah satu tipe tombol ke {@link
|
||||
android.app.AlertDialog}. Artinya, Anda tidak bisa memiliki lebih dari satu tombol "positif".</p>
|
||||
|
||||
|
||||
|
||||
<div class="figure" style="width:290px;margin:0 0 0 40px">
|
||||
<img src="{@docRoot}images/ui/dialog_list.png" alt="" />
|
||||
<p class="img-caption"><strong>Gambar 3.</strong>
|
||||
Dialog dengan satu judul dan daftar.</p>
|
||||
</div>
|
||||
|
||||
<h3 id="AddingAList">Menambahkan daftar</h3>
|
||||
|
||||
<p>Ada tiga macam daftar yang tersedia pada API {@link android.app.AlertDialog}:</p>
|
||||
<ul>
|
||||
<li>Daftar pilihan tunggal biasa</li>
|
||||
<li>Daftar pilihan tunggal persisten (tombol radio)</li>
|
||||
<li>Daftar pilihan ganda persisten (kotak cek)</li>
|
||||
</ul>
|
||||
|
||||
<p>Untuk membuat daftar pilihan tunggal seperti dalam gambar 3,
|
||||
gunakan metode {@link android.app.AlertDialog.Builder#setItems setItems()}:</p>
|
||||
|
||||
<pre style="clear:right">
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setTitle(R.string.pick_color)
|
||||
.setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// The 'which' argument contains the index position
|
||||
// of the selected item
|
||||
}
|
||||
});
|
||||
return builder.create();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Karena daftar muncul dalam area konten dialog,
|
||||
dialog tidak bisa menampilkan pesan dan daftar sekaligus dan Anda harus menetapkan judul untuk
|
||||
dialog dengan {@link android.app.AlertDialog.Builder#setTitle setTitle()}.
|
||||
Untuk menentukan item daftar, panggil {@link
|
||||
android.app.AlertDialog.Builder#setItems setItems()}, dengan meneruskan larik.
|
||||
Atau, Anda bisa menetapkan daftar menggunakan {@link
|
||||
android.app.AlertDialog.Builder#setAdapter setAdapter()}. Hal ini memungkinkan Anda mendukung daftar
|
||||
dengan data dinamis (seperti dari database) dengan menggunakan {@link android.widget.ListAdapter}.</p>
|
||||
|
||||
<p>Jika Anda memilih untuk mendukung daftar dengan {@link android.widget.ListAdapter},
|
||||
selalu gunakan sebuah {@link android.support.v4.content.Loader} agar konten dimuat
|
||||
secara asinkron. Hal ini dijelaskan lebih jauh dalam panduan
|
||||
<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Membuat Layout
|
||||
dengan Adaptor</a> dan <a href="{@docRoot}guide/components/loaders.html">Loader</a>
|
||||
.</p>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> Secara default, menyentuh sebuah item daftar akan menutup dialog,
|
||||
kecuali Anda menggunakan salah satu daftar pilihan persisten berikut ini.</p>
|
||||
|
||||
<div class="figure" style="width:290px;margin:-30px 0 0 40px">
|
||||
<img src="{@docRoot}images/ui/dialog_checkboxes.png" />
|
||||
<p class="img-caption"><strong>Gambar 4.</strong>
|
||||
Daftar item pilihan ganda.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<h4 id="Checkboxes">Menambahkan daftar pilihan ganda atau pilihan tunggal persisten</h4>
|
||||
|
||||
<p>Untuk menambahkan daftar item pilihan ganda (kotak cek) atau
|
||||
item pilihan tunggal (tombol radio), gunakan masing-masing metode
|
||||
{@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String,
|
||||
DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()}, atau
|
||||
{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
|
||||
setSingleChoiceItems()}.</p>
|
||||
|
||||
<p>Misalnya, berikut ini cara membuat daftar pilihan ganda seperti
|
||||
yang ditampilkan dalam gambar 4 yang menyimpan item
|
||||
yang dipilih dalam {@link java.util.ArrayList}:</p>
|
||||
|
||||
<pre style="clear:right">
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
mSelectedItems = new ArrayList(); // Where we track the selected items
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
// Set the dialog title
|
||||
builder.setTitle(R.string.pick_toppings)
|
||||
// Specify the list array, the items to be selected by default (null for none),
|
||||
// and the listener through which to receive callbacks when items are selected
|
||||
.setMultiChoiceItems(R.array.toppings, null,
|
||||
new DialogInterface.OnMultiChoiceClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which,
|
||||
boolean isChecked) {
|
||||
if (isChecked) {
|
||||
// If the user checked the item, add it to the selected items
|
||||
mSelectedItems.add(which);
|
||||
} else if (mSelectedItems.contains(which)) {
|
||||
// Else, if the item is already in the array, remove it
|
||||
mSelectedItems.remove(Integer.valueOf(which));
|
||||
}
|
||||
}
|
||||
})
|
||||
// Set the action buttons
|
||||
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
// User clicked OK, so save the mSelectedItems results somewhere
|
||||
// or return them to the component that opened the dialog
|
||||
...
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
...
|
||||
}
|
||||
});
|
||||
|
||||
return builder.create();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Walaupun daftar tradisional maupun daftar dengan tombol radio
|
||||
menyediakan tindakan "pilihan tunggal", Anda harus menggunakan {@link
|
||||
android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
|
||||
setSingleChoiceItems()} jika ingin mempertahankan pilihan pengguna.
|
||||
Yakni, jika nanti membuka dialog lagi untuk menunjukkan pilihan pengguna,
|
||||
maka Anda perlu membuat daftar dengan tombol radio.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 id="CustomLayout">Membuat Layout Custom</h3>
|
||||
|
||||
<div class="figure" style="width:290px;margin:-30px 0 0 40px">
|
||||
<img src="{@docRoot}images/ui/dialog_custom.png" alt="" />
|
||||
<p class="img-caption"><strong>Gambar 5.</strong> Layout dialog custom.</p>
|
||||
</div>
|
||||
|
||||
<p>Jika Anda menginginkan layout custom dalam dialog, buatlah layout dan tambahkan ke
|
||||
{@link android.app.AlertDialog} dengan memanggil {@link
|
||||
android.app.AlertDialog.Builder#setView setView()} pada objek {@link
|
||||
android.app.AlertDialog.Builder} Anda.</p>
|
||||
|
||||
<p>Secara default, layout custom akan mengisi jendela dialog, namun Anda masih bisa
|
||||
menggunakan metode {@link android.app.AlertDialog.Builder} untuk menambahkan tombol dan judul.</p>
|
||||
|
||||
<p>Misalnya, berikut ini adalah file layout untuk dialog dalam Gambar 5:</p>
|
||||
|
||||
<p style="clear:right" class="code-caption">res/layout/dialog_signin.xml</p>
|
||||
<pre>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:src="@drawable/header_logo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:scaleType="center"
|
||||
android:background="#FFFFBB33"
|
||||
android:contentDescription="@string/app_name" />
|
||||
<EditText
|
||||
android:id="@+id/username"
|
||||
android:inputType="textEmailAddress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:hint="@string/username" />
|
||||
<EditText
|
||||
android:id="@+id/password"
|
||||
android:inputType="textPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:hint="@string/password"/>
|
||||
</LinearLayout>
|
||||
</pre>
|
||||
|
||||
<p class="note"><strong>Tip:</strong> Secara default, bila Anda telah mengatur sebuah elemen {@link android.widget.EditText}
|
||||
agar menggunakan tipe input {@code "textPassword"}, keluarga font akan diatur ke spasi tunggal, sehingga
|
||||
Anda harus mengubah keluarga font ke {@code "sans-serif"} sehingga kedua bidang teks menggunakan
|
||||
gaya font yang cocok.</p>
|
||||
|
||||
<p>Untuk memekarkan layout dalam {@link android.support.v4.app.DialogFragment} Anda,
|
||||
ambillah {@link android.view.LayoutInflater} dengan
|
||||
{@link android.app.Activity#getLayoutInflater()} dan panggil
|
||||
{@link android.view.LayoutInflater#inflate inflate()}, dengan parameter pertama
|
||||
adalah ID sumber daya layout dan parameter kedua adalah tampilan induk untuk layout.
|
||||
Selanjutnya Anda bisa memanggil {@link android.app.AlertDialog#setView setView()}
|
||||
untuk menempatkan layout dalam dialog.</p>
|
||||
|
||||
<pre>
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
// Get the layout inflater
|
||||
LayoutInflater inflater = getActivity().getLayoutInflater();
|
||||
|
||||
// Inflate and set the layout for the dialog
|
||||
// Pass null as the parent view because its going in the dialog layout
|
||||
builder.setView(inflater.inflate(R.layout.dialog_signin, null))
|
||||
// Add action buttons
|
||||
.setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
// sign in the user ...
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
LoginDialogFragment.this.getDialog().cancel();
|
||||
}
|
||||
});
|
||||
return builder.create();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<div class="note">
|
||||
<p><strong>Tip:</strong> Jika Anda menginginkan dialog custom,
|
||||
Anda bisa menampilkan {@link android.app.Activity} sebagai dialog
|
||||
daripada menggunakan API {@link android.app.Dialog}. Cukup buat satu aktivitas dan mengatur temanya ke
|
||||
{@link android.R.style#Theme_Holo_Dialog Theme.Holo.Dialog}
|
||||
di elemen manifes <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
|
||||
<activity>}</a>:</p>
|
||||
|
||||
<pre>
|
||||
<activity android:theme="@android:style/Theme.Holo.Dialog" >
|
||||
</pre>
|
||||
<p>Demikian saja. Aktivitas sekarang ditampilkan dalam jendela dialog, sebagai ganti layar penuh.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h2 id="PassingEvents">Meneruskan Kejadian Kembali ke Host Dialog</h2>
|
||||
|
||||
<p>Bila pengguna menyentuh salah satu tombol tindakan dialog atau memilih satu item dari daftarnya,
|
||||
{@link android.support.v4.app.DialogFragment} Anda bisa melakukan sendiri tindakan yang diperlukan
|
||||
, namun sering kali Anda perlu mengirim kejadian itu ke aktivitas atau fragmen yang
|
||||
membuka dialog. Caranya, definisikan antarmuka dengan sebuah metode untuk masing-masing tipe kejadian klik.
|
||||
Lalu implementasikan antarmuka itu dalam komponen host yang akan
|
||||
menerima kejadian tindakan dari dialog.</p>
|
||||
|
||||
<p>Misalnya, berikut ini adalah {@link android.support.v4.app.DialogFragment} yang mendefinisikan
|
||||
antarmuka yang akan digunakan untuk mengirim kembali suatu kejadian ke aktivitas host:</p>
|
||||
|
||||
<pre>
|
||||
public class NoticeDialogFragment extends DialogFragment {
|
||||
|
||||
/* The activity that creates an instance of this dialog fragment must
|
||||
* implement this interface in order to receive event callbacks.
|
||||
* Each method passes the DialogFragment in case the host needs to query it. */
|
||||
public interface NoticeDialogListener {
|
||||
public void onDialogPositiveClick(DialogFragment dialog);
|
||||
public void onDialogNegativeClick(DialogFragment dialog);
|
||||
}
|
||||
|
||||
// Use this instance of the interface to deliver action events
|
||||
NoticeDialogListener mListener;
|
||||
|
||||
// Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
// Verify that the host activity implements the callback interface
|
||||
try {
|
||||
// Instantiate the NoticeDialogListener so we can send events to the host
|
||||
mListener = (NoticeDialogListener) activity;
|
||||
} catch (ClassCastException e) {
|
||||
// The activity doesn't implement the interface, throw exception
|
||||
throw new ClassCastException(activity.toString()
|
||||
+ " must implement NoticeDialogListener");
|
||||
}
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Aktivitas yang menjadi host dialog tersebut akan membuat instance dialog
|
||||
dengan konstruktor fragmen dialog dan menerima kejadian dialog
|
||||
melalui implementasi antarmuka {@code NoticeDialogListener}:</p>
|
||||
|
||||
<pre>
|
||||
public class MainActivity extends FragmentActivity
|
||||
implements NoticeDialogFragment.NoticeDialogListener{
|
||||
...
|
||||
|
||||
public void showNoticeDialog() {
|
||||
// Create an instance of the dialog fragment and show it
|
||||
DialogFragment dialog = new NoticeDialogFragment();
|
||||
dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
|
||||
}
|
||||
|
||||
// The dialog fragment receives a reference to this Activity through the
|
||||
// Fragment.onAttach() callback, which it uses to call the following methods
|
||||
// defined by the NoticeDialogFragment.NoticeDialogListener interface
|
||||
@Override
|
||||
public void onDialogPositiveClick(DialogFragment dialog) {
|
||||
// User touched the dialog's positive button
|
||||
...
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDialogNegativeClick(DialogFragment dialog) {
|
||||
// User touched the dialog's negative button
|
||||
...
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Karena aktivitas host mengimplementasikan {@code NoticeDialogListener}—yang
|
||||
diberlakukan oleh metode callback {@link android.support.v4.app.Fragment#onAttach onAttach()}
|
||||
di atas,—fragmen dialog bisa menggunakan
|
||||
metode callback antarmuka untuk mengirimkan kejadian klik ke aktivitas:</p>
|
||||
|
||||
<pre>
|
||||
public class NoticeDialogFragment extends DialogFragment {
|
||||
...
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
// Build the dialog and set up the button click handlers
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setMessage(R.string.dialog_fire_missiles)
|
||||
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
// Send the positive button event back to the host activity
|
||||
mListener.onDialogPositiveClick(NoticeDialogFragment.this);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
// Send the negative button event back to the host activity
|
||||
mListener.onDialogNegativeClick(NoticeDialogFragment.this);
|
||||
}
|
||||
});
|
||||
return builder.create();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
<h2 id="ShowingADialog">Menampilkan Dialog</h2>
|
||||
|
||||
<p>Bila Anda ingin menampilkan dialog, buatlah instance {@link
|
||||
android.support.v4.app.DialogFragment} dan panggil {@link android.support.v4.app.DialogFragment#show
|
||||
show()}, dengan meneruskan {@link android.support.v4.app.FragmentManager} dan nama tag
|
||||
untuk fragmen dialognya.</p>
|
||||
|
||||
<p>Anda bisa mendapatkan {@link android.support.v4.app.FragmentManager} dengan memanggil
|
||||
{@link android.support.v4.app.FragmentActivity#getSupportFragmentManager()} dari
|
||||
{@link android.support.v4.app.FragmentActivity} atau {@link
|
||||
android.support.v4.app.Fragment#getFragmentManager()} dari {@link
|
||||
android.support.v4.app.Fragment}. Misalnya:</p>
|
||||
|
||||
<pre>
|
||||
public void confirmFireMissiles() {
|
||||
DialogFragment newFragment = new FireMissilesDialogFragment();
|
||||
newFragment.show(getSupportFragmentManager(), "missiles");
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Argumen kedua, {@code "missiles"}, adalah nama tag unik yang digunakan sistem untuk menyimpan
|
||||
dan memulihkan status fragmen bila diperlukan. Tag ini juga memungkinkan Anda mendapatkan handle ke
|
||||
fragmen dengan memanggil {@link android.support.v4.app.FragmentManager#findFragmentByTag
|
||||
findFragmentByTag()}.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="FullscreenDialog">Menampilkan Dialog sebagai Layar Penuh atau Fragmen Tertanam</h2>
|
||||
|
||||
<p>Anda mungkin memiliki desain UI yang di dalamnya Anda ingin UI muncul sebagai dialog dalam beberapa
|
||||
situasi, namun sebagai layar penuh atau fragmen tertanam dalam situasi lain (mungkin bergantung pada apakah
|
||||
perangkat memiliki layar besar atau layar kecil). Kelas {@link android.support.v4.app.DialogFragment}
|
||||
menawarkan fleksibilitas ini karena masih bisa berperilaku sebagai {@link
|
||||
android.support.v4.app.Fragment} yang bisa ditanamkan.</p>
|
||||
|
||||
<p>Akan tetapi, dalam hal ini Anda tidak bisa menggunakan {@link android.app.AlertDialog.Builder AlertDialog.Builder}
|
||||
atau objek {@link android.app.Dialog} lain untuk membangun dialog. Jika
|
||||
Anda ingin {@link android.support.v4.app.DialogFragment}
|
||||
bisa ditanamkan, Anda harus mendefinisikan dialog UI dalam layout, lalu memuat layout itu dalam metode callback
|
||||
{@link android.support.v4.app.DialogFragment#onCreateView
|
||||
onCreateView()}.</p>
|
||||
|
||||
<p>Berikut ini adalah contoh {@link android.support.v4.app.DialogFragment} yang bisa muncul sebagai
|
||||
dialog maupun fragmen yang bisa ditanamkan (menggunakan layout bernama <code>purchase_items.xml</code>):</p>
|
||||
|
||||
<pre>
|
||||
public class CustomDialogFragment extends DialogFragment {
|
||||
/** The system calls this to get the DialogFragment's layout, regardless
|
||||
of whether it's being displayed as a dialog or an embedded fragment. */
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout to use as dialog or embedded fragment
|
||||
return inflater.inflate(R.layout.purchase_items, container, false);
|
||||
}
|
||||
|
||||
/** The system calls this only when creating the layout in a dialog. */
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
// The only reason you might override this method when using onCreateView() is
|
||||
// to modify any dialog characteristics. For example, the dialog includes a
|
||||
// title by default, but your custom layout might not need it. So here you can
|
||||
// remove the dialog title, but you must call the superclass to get the Dialog.
|
||||
Dialog dialog = super.onCreateDialog(savedInstanceState);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Dan berikut ini adalah beberapa kode yang memutuskan apakah akan menampilkan fragmen sebagai dialog
|
||||
atau UI layar penuh, berdasarkan ukuran layar:</p>
|
||||
|
||||
<pre>
|
||||
public void showDialog() {
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
CustomDialogFragment newFragment = new CustomDialogFragment();
|
||||
|
||||
if (mIsLargeLayout) {
|
||||
// The device is using a large layout, so show the fragment as a dialog
|
||||
newFragment.show(fragmentManager, "dialog");
|
||||
} else {
|
||||
// The device is smaller, so show the fragment fullscreen
|
||||
FragmentTransaction transaction = fragmentManager.beginTransaction();
|
||||
// For a little polish, specify a transition animation
|
||||
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
|
||||
// To make it fullscreen, use the 'content' root view as the container
|
||||
// for the fragment, which is always the root view for the activity
|
||||
transaction.add(android.R.id.content, newFragment)
|
||||
.addToBackStack(null).commit();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Untuk informasi selengkapnya tentang melakukan transaksi fragmen, lihat panduan
|
||||
<a href="{@docRoot}guide/components/fragments.html">Fragmen</a>.</p>
|
||||
|
||||
<p>Dalam contoh ini, nilai boolean <code>mIsLargeLayout</code> menentukan apakah perangkat saat ini
|
||||
harus menggunakan desain layout besar aplikasi (dan dengan demikian menampilkan fragmen ini sebagai dialog, bukan
|
||||
layar penuh). Cara terbaik untuk mengatur jenis boolean ini adalah mendeklarasikan
|
||||
<a href="{@docRoot}guide/topics/resources/more-resources.html#Bool">nilai sumber daya boolean</a>
|
||||
dengan nilai <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">sumber daya alternatif</a> untuk berbagai ukuran layar. Misalnya, berikut ini adalah dua
|
||||
versi sumber daya boolean untuk berbagai ukuran layar:</p>
|
||||
|
||||
<p class="code-caption">res/values/bools.xml</p>
|
||||
<pre>
|
||||
<!-- Default boolean values -->
|
||||
<resources>
|
||||
<bool name="large_layout">false</bool>
|
||||
</resources>
|
||||
</pre>
|
||||
|
||||
<p class="code-caption">res/values-large/bools.xml</p>
|
||||
<pre>
|
||||
<!-- Large screen boolean values -->
|
||||
<resources>
|
||||
<bool name="large_layout">true</bool>
|
||||
</resources>
|
||||
</pre>
|
||||
|
||||
<p>Selanjutnya Anda bisa menetapkan nilai {@code mIsLargeLayout} selama
|
||||
metode {@link android.app.Activity#onCreate onCreate()} aktivitas:</p>
|
||||
|
||||
<pre>
|
||||
boolean mIsLargeLayout;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
mIsLargeLayout = getResources().getBoolean(R.bool.large_layout);
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
<h3 id="ActivityAsDialog">Menampilkan aktivitas sebagai dialog pada layar besar</h3>
|
||||
|
||||
<p>Sebagai ganti menampilkan dialog berupa UI layar penuh saat di layar kecil, Anda bisa memperoleh
|
||||
hasil yang sama dengan menampilkan {@link android.app.Activity} sebagai dialog saat di
|
||||
layar besar. Pendekatan yang Anda pilih bergantung pada desain aplikasi, namun
|
||||
menampilkan aktivitas sebagai dialog sering kali berguna bila aplikasi Anda sudah didesain untuk
|
||||
layar kecil dan Anda ingin meningkatkan pengalaman pada tablet dengan menampilkan aktivitas berjangka pendek
|
||||
sebagai dialog.</p>
|
||||
|
||||
<p>Untuk menampilkan aktivitas sebagai dialog hanya saat di layar besar,
|
||||
terapkan tema {@link android.R.style#Theme_Holo_DialogWhenLarge Theme.Holo.DialogWhenLarge}
|
||||
pada elemen manifes <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
|
||||
<activity>}</a>:</p>
|
||||
|
||||
<pre>
|
||||
<activity android:theme="@android:style/Theme.Holo.DialogWhenLarge" >
|
||||
</pre>
|
||||
|
||||
<p>Untuk informasi selengkapnya tentang mengatur gaya aktivitas Anda dengan tema, lihat panduan <a href="{@docRoot}guide/topics/ui/themes.html">Gaya dan Tema</a>.</p>
|
||||
|
||||
|
||||
|
||||
<h2 id="DismissingADialog">Menutup Dialog</h2>
|
||||
|
||||
<p>Bila pengguna menyentuh salah satu tombol tindakan yang dibuat dengan
|
||||
{@link android.app.AlertDialog.Builder}, sistem akan menutup dialog untuk Anda.</p>
|
||||
|
||||
<p>Sistem juga menutup dialog bila pengguna menyentuh sebuah item dalam daftar dialog, kecuali
|
||||
bila daftar itu menggunakan tombol radio atau kotak cek. Jika tidak, Anda bisa menutup dialog secara manual
|
||||
dengan memanggil {@link android.support.v4.app.DialogFragment#dismiss()} pada {@link
|
||||
android.support.v4.app.DialogFragment} Anda.</p>
|
||||
|
||||
<p>Jika Anda perlu melakukan
|
||||
tindakan tertentu saat dialog menghilang, Anda bisa menerapkan metode {@link
|
||||
android.support.v4.app.DialogFragment#onDismiss onDismiss()} dalam {@link
|
||||
android.support.v4.app.DialogFragment} Anda.</p>
|
||||
|
||||
<p>Anda juga bisa <em>membatalkan</em> dialog. Ini merupakan kejadian khusus yang menunjukkan bahwa pengguna
|
||||
secara eksplisit meninggalkan dialog tanpa menyelesaikan tugas. Hal ini terjadi jika pengguna menekan tombol
|
||||
<em>Back</em>, menyentuh layar di luar area dialog,
|
||||
atau jika Anda secara eksplisit memanggil {@link android.app.Dialog#cancel()} pada {@link
|
||||
android.app.Dialog} (seperti saat merespons tombol "Cancel" dalam dialog).</p>
|
||||
|
||||
<p>Seperti yang ditampilkan dalam contoh di atas, Anda bisa merespons kejadian batal dengan menerapkan
|
||||
{@link android.support.v4.app.DialogFragment#onCancel onCancel()} dalam kelas {@link
|
||||
android.support.v4.app.DialogFragment} Anda.</p>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> Sistem akan memanggil
|
||||
{@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} pada tiap kejadian yang
|
||||
memanggil callback {@link android.support.v4.app.DialogFragment#onCancel onCancel()}. Akan tetapi,
|
||||
jika Anda memanggil {@link android.app.Dialog#dismiss Dialog.dismiss()} atau {@link
|
||||
android.support.v4.app.DialogFragment#dismiss DialogFragment.dismiss()},
|
||||
sistem akan memanggil {@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} <em>namun
|
||||
bukan</em> {@link android.support.v4.app.DialogFragment#onCancel onCancel()}. Jadi biasanya Anda harus
|
||||
memanggil {@link android.support.v4.app.DialogFragment#dismiss dismiss()} bila pengguna menekan tombol
|
||||
<em>positif</em> dalam dialog untuk menghilangkan tampilan dialog.</p>
|
||||
|
||||
|
||||
1031
docs/html-intl/intl/id/guide/topics/ui/menus.jd
Normal file
1031
docs/html-intl/intl/id/guide/topics/ui/menus.jd
Normal file
File diff suppressed because it is too large
Load Diff
589
docs/html-intl/intl/id/guide/topics/ui/multi-window.jd
Normal file
589
docs/html-intl/intl/id/guide/topics/ui/multi-window.jd
Normal file
@@ -0,0 +1,589 @@
|
||||
page.title=Dukungan Multi-Jendela
|
||||
page.metaDescription=Dukungan baru di Android N untuk menampilkan lebih dari satu aplikasi sekaligus.
|
||||
page.keywords="multi-window", "android N", "split screen", "free-form"
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#overview">Ringkasan</a></li>
|
||||
<li><a href="#lifecycle">Daur Hidup Multi-Jendela</a></li>
|
||||
<li><a href="#configuring">Mengonfigurasi Aplikasi Anda untuk Mode
|
||||
Multi-Jendela</a></li>
|
||||
<li><a href="#running">Menjalankan Aplikasi Anda dalam Mode Multi-Jendela</a></li>
|
||||
<li><a href="#testing">Menguji Dukungan Multi-Jendela Aplikasi Anda</a></li>
|
||||
</ol>
|
||||
<h2>Lihat Juga</h2>
|
||||
<ol>
|
||||
<li><a class="external-link" href="https://github.com/googlesamples/android-MultiWindowPlayground">Aplikasi contoh Playground
|
||||
Multi-Jendela</a></li>
|
||||
<li><a class="external-link" href="https://medium.com/google-developers/5-tips-for-preparing-for-multi-window-in-android-n-7bed803dda64">Lima Tip untuk Mempersiapkan Multi-Jendela di Android N</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Android N menambahkan dukungan untuk menampilkan lebih dari satu aplikasi
|
||||
sekaligus. Pada perangkat genggam, dua aplikasi bisa berjalan berdampingan atau
|
||||
atas-bawah dalam mode <em>layar terbagi</em>. Pada perangkat TV, aplikasi bisa
|
||||
menggunakan mode <em>gambar-dalam-gambar</em> untuk melanjutkan pemutaran video selagi pengguna
|
||||
berinteraksi dengan aplikasi lain.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Jika Anda membangun aplikasi Anda dengan N Preview SDK, Anda bisa mengonfigurasi cara aplikasi
|
||||
menangani tampilan multi-jendela. Misalnya, Anda bisa menetapkan dimensi
|
||||
minimum yang diizinkan aktivitas Anda. Anda juga bisa menonaktifkan tampilan multi-jendela untuk
|
||||
aplikasi, sehingga memastikan sistem hanya menampilkan aplikasi Anda dalam mode
|
||||
layar penuh.
|
||||
</p>
|
||||
|
||||
<h2 id="overview">Ringkasan</h2>
|
||||
|
||||
<p>
|
||||
Android N memungkinkan beberapa aplikasi berbagi layar sekaligus. Misalnya,
|
||||
pengguna bisa membagi layar, melihat halaman web di sisi kiri
|
||||
sambil menulis email di sisi kanan. Pengalaman pengguna bergantung pada
|
||||
perangkat:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Perangkat genggam yang menjalankan Android N menawarkan mode
|
||||
layar terbagi. Di mode ini, sistem mengisi layar dengan dua aplikasi, menampilkannya secara
|
||||
berdampingan atau atas-bawah. Pengguna bisa menyeret garis pembagi
|
||||
yang memisahkan keduanya untuk membuat satu aplikasi lebih besar dan yang lainnya lebih kecil.
|
||||
</li>
|
||||
|
||||
<li>Pada Nexus Player yang menjalankan Android N, aplikasi bisa menempatkan diri
|
||||
dalam <a href="picture-in-picture.html">mode gambar-dalam-gambar</a>, yang memungkinkannya
|
||||
untuk terus menampilkan materi selagi pengguna menjelajahi atau berinteraksi dengan
|
||||
aplikasi lain.
|
||||
</li>
|
||||
|
||||
<li>Produsen perangkat berukuran lebih besar bisa memilih untuk mengaktifkan mode
|
||||
bentuk bebas, di mana pengguna bisa bebas mengubah ukuran setiap aktivitas. Jika
|
||||
produsen mengaktifkan fitur ini, perangkat akan menawarkan mode bentuk bebas sebagai tambahan
|
||||
untuk mode layar terbagi.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<img src="{@docRoot}images/android-7.0/mw-splitscreen.png" alt="" width="650" srcset="{@docRoot}images/android-7.0/mw-splitscreen.png 1x,
|
||||
{@docRoot}images/android-7.0/mw-splitscreen_2x.png 2x," id="img-split-screen" />
|
||||
<p class="img-caption">
|
||||
<strong>Gambar 1.</strong> Dua aplikasi berjalan berdampingan dalam mode layar terbagi.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Pengguna bisa beralih ke mode multi-jendela dengan cara berikut:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Jika pengguna membuka <a href="{@docRoot}guide/components/recents.html">layar
|
||||
Ringkasan</a> dan menekan lama pada
|
||||
judul aktivitas, mereka bisa menyeret aktivitas itu ke bagian yang disorot pada layar
|
||||
untuk menempatkan aktivitas dalam mode multi-jendela.
|
||||
</li>
|
||||
|
||||
<li>Jika pengguna menekan lama pada tombol Ringkasan, perangkat akan menempatkan
|
||||
aktivitas saat ini dalam mode multi-jendela, dan membuka layar Ringkasan guna
|
||||
memungkinkan pengguna memilih aktivitas lain untuk berbagi layar.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Pengguna bisa <a href="{@docRoot}guide/topics/ui/drag-drop.html">seret dan
|
||||
lepas</a> data dari aktivitas satu ke aktivitas lain sewaktu aktivitas berbagi
|
||||
layar. (Sebelumnya, pengguna hanya bisa menyeret dan melepas data dalam aktivitas
|
||||
tunggal.)
|
||||
</p>
|
||||
|
||||
<h2 id="lifecycle">Daur Hidup Multi-Jendela</h2>
|
||||
|
||||
<p>
|
||||
Mode multi-jendela tidak mengubah <a href="{@docRoot}training/basics/activity-lifecycle/index.html">daur hidup
|
||||
aktivitas</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Dalam mode multi-jendela, hanya aktivitas yang paling sering digunakan pengguna
|
||||
yang akan aktif pada waktu tertentu. Aktivitas ini dianggap <em>teratas</em>.
|
||||
Semua aktivitas lainnya dalam keadaan berhenti sementara, sekalipun terlihat.
|
||||
Akan tetapi, sistem memberikan aktivitas, yang berhenti-sementara-namun-terlihat ini, prioritas lebih tinggi
|
||||
daripada aktivitas yang tidak terlihat. Jika pengguna berinteraksi dengan salah satu
|
||||
aktivitas yang berhenti sementara, aktivitas tersebut akan dilanjutkan kembali, dan aktivitas
|
||||
teratas sebelumnya akan dihentikan sementara.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Dalam mode multi-jendela, aplikasi bisa berada dalam keadaan berhenti sementara
|
||||
dan masih terlihat oleh pengguna. Sebuah aplikasi mungkin perlu melanjutkan aktivitasnya
|
||||
bahkan saat berhenti sementara. Misalnya, aplikasi pemutar video yang ada dalam
|
||||
mode berhenti sementara namun terlihat harus tetap menampilkan videonya. Karena alasan
|
||||
ini, kami menyarankan aktivitas yang memutar video <em>tidak</em> menghentikan sementara video
|
||||
dalam handler {@link android.app.Activity#onPause onPause()} mereka.
|
||||
Sebagai gantinya, aktivitas itu harus menghentikan sementara video di {@link android.app.Activity#onStop
|
||||
onStop()}, dan melanjutkan pemutaran di {@link android.app.Activity#onStart
|
||||
onStart()}.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Bila pengguna menempatkan aplikasi dalam mode multi-jendela, sistem akan memberi tahu
|
||||
aktivitas tersebut mengenai perubahan konfigurasi, sebagaimana ditetapkan dalam <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani Perubahan
|
||||
Waktu Proses</a>. Hal ini juga terjadi ketika pengguna mengubah skala aplikasi, atau menempatkan kembali aplikasi
|
||||
ke mode layar penuh.
|
||||
Pada dasarnya, perubahan ini memiliki implikasi daur hidup aktivitas yang sama
|
||||
seperti saat sistem memberi tahu aplikasi bahwa perangkat telah beralih
|
||||
dari mode potret ke mode lanskap, kecuali dimensi perangkat
|
||||
telah berubah sebagai ganti bertukar posisi. Seperti yang dibahas di <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani Perubahan
|
||||
Waktu Proses</a>, aktivitas Anda bisa menangani perubahan konfigurasi itu sendiri, atau
|
||||
mengizinkan sistem memusnahkan aktivitas dan membuatnya kembali dengan dimensi
|
||||
baru.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Jika pengguna mengubah ukuran jendela dan membuat dimensinya lebih besar, sistem
|
||||
akan mengubah ukuran aktivitas untuk menyesuaikan dengan tindakan pengguna dan mengeluarkan <a href="{@docRoot}guide/topics/resources/runtime-changes.html">perubahan waktu proses</a>
|
||||
bila diperlukan. Jika aplikasi tertinggal dibandingkan gambar di area yang baru diekspos,
|
||||
sistem untuk sementara mengisi area tersebut dengan warna yang ditetapkan oleh atribut {@link
|
||||
android.R.attr#windowBackground windowBackground} atau dengan atribut gaya
|
||||
<code>windowBackgroundFallback</code> secara default.
|
||||
</p>
|
||||
|
||||
<h2 id="configuring">Mengonfigurasi Aplikasi Anda untuk Mode Multi-Jendela</h2>
|
||||
|
||||
<p>
|
||||
Jika aplikasi Anda menargetkan Android N, Anda bisa mengonfigurasi bagaimana dan
|
||||
apakah aktivitas aplikasi Anda mendukung tampilan multi-jendela. Anda bisa menyetel
|
||||
atribut dalam manifes untuk mengontrol ukuran dan layoutnya.
|
||||
Setelan atribut aktivitas root berlaku pada semua aktivitas
|
||||
dalam tumpukan tugasnya. Misalnya, jika aktivitas root memiliki
|
||||
<code>android:resizeableActivity</code> yang disetel ke true, maka semua aktivitas
|
||||
dalam tumpukan tugas bisa diubah ukurannya.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Jika Anda membangun aplikasi multi-orientasi dengan versi
|
||||
SDK lebih rendah dari Android N, dan pengguna menggunakan aplikasi
|
||||
dalam mode multi-jendela, sistem akan mengubah ukuran aplikasi secara paksa. Sistem akan menampilkan kotak
|
||||
dialog yang memperingatkan pengguna bahwa aplikasi mungkin berperilaku tidak terduga. Sistem
|
||||
<em>tidak</em> mengubah ukuran aplikasi yang berorientasi tetap; jika
|
||||
pengguna berusaha membuka aplikasi berorientasi tetap saat mode multi-jendela,
|
||||
aplikasi akan menggunakan seluruh layar.
|
||||
</p>
|
||||
|
||||
<h4 id="resizeableActivity">android:resizeableActivity</h4>
|
||||
<p>
|
||||
Setel atribut ini dalam manifes <code><activity></code> Anda atau simpul
|
||||
<code><application></code> untuk mengaktifkan atau menonaktifkan tampilan
|
||||
multi-jendela:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
android:resizeableActivity=["true" | "false"]
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Jika atribut ini disetel ke true, aktivitas bisa dijalankan di
|
||||
mode layar terbagi dan mode bentuk bebas. Jika atribut ini disetel ke false, aktivitas
|
||||
tidak akan mendukung mode multi-jendela. Jika nilai ini false, dan pengguna
|
||||
berusaha memulai aktivitas dalam mode multi-jendela, aktivitas akan menggunakan
|
||||
layar penuh.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Jika aplikasi Anda menargetkan Android N, namun Anda tidak menetapkan nilai
|
||||
untuk atribut ini, nilai atribut default adalah true.
|
||||
</p>
|
||||
|
||||
<h4 id="supportsPictureInPicture">android:supportsPictureInPicture</h4>
|
||||
|
||||
<p>
|
||||
Setel atribut ini dalam simpul <code><activity></code> manifes Anda untuk
|
||||
menunjukkan apakah aktivitas mendukung tampilan gambar-dalam-gambar. Atribut ini
|
||||
diabaikan jika <code>android:resizeableActivity</code> bernilai false.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
android:supportsPictureInPicture=["true" | "false"]
|
||||
</pre>
|
||||
|
||||
<h3 id="layout">Atribut layout</h3>
|
||||
|
||||
<p>
|
||||
Dengan Android N, elemen manifes <code><layout></code>
|
||||
mendukung beberapa atribut yang memengaruhi cara aktivitas berperilaku dalam
|
||||
mode multi-jendela:
|
||||
</p>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<code>android:defaultWidth</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Lebar default aktivitas saat dijalankan dalam mode bentuk bebas.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>android:defaultHeight</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Tinggi default aktivitas saat dijalankan dalam mode bentuk bebas.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>android:gravity</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Penempatan awal dari aktivitas saat dibuka dalam mode bentuk bebas. Lihat referensi
|
||||
{@link android.view.Gravity} untuk mengetahui nilai yang cocok.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>android:minimalHeight</code>, <code>android:minimalWidth</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Tinggi dan lebar minimum untuk aktivitas dalam mode layar terbagi
|
||||
dan mode bentuk bebas. Jika pengguna memindahkan pembagi dalam mode layar terbagi
|
||||
untuk membuat aktivitas lebih kecil dari minimum yang ditetapkan, sistem akan memangkas
|
||||
aktivitas sesuai dengan ukuran yang diminta pengguna.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
Misalnya, kode berikut menampilkan cara menetapkan ukuran dan lokasi default
|
||||
aktivitas, dan ukuran minimumnya, bila aktivitas ditampilkan dalam
|
||||
mode bentuk bebas:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<activity android:name=".MyActivity">
|
||||
<layout android:defaultHeight="500dp"
|
||||
android:defaultWidth="600dp"
|
||||
android:gravity="top|end"
|
||||
android:minimalHeight="450dp"
|
||||
android:minimalWidth="300dp" />
|
||||
</activity>
|
||||
</pre>
|
||||
|
||||
<h2 id="running">Menjalankan Aplikasi Anda dalam Mode Multi-Jendela</h2>
|
||||
|
||||
<p>
|
||||
Android N menawarkan fungsionalitas baru untuk mendukung aplikasi yang bisa berjalan
|
||||
dalam mode multi-jendela.
|
||||
</p>
|
||||
|
||||
<h3 id="disabled-features">Fitur yang dinonaktifkan dalam mode multi-jendela</h3>
|
||||
|
||||
<p>
|
||||
Fitur tertentu akan dinonaktifkan atau diabaikan bila perangkat berada dalam mode
|
||||
multi-jendela, karena dianggap tidak logis bagi suatu aktivitas yang mungkin berbagi
|
||||
layar perangkat dengan aktivitas atau aplikasi lainnya. Fitur tersebut meliputi:
|
||||
|
||||
<ul>
|
||||
<li>Beberapa opsi penyesuaian di <a href="{@docRoot}training/system-ui/index.html">System UI</a>
|
||||
dinonaktifkan; misalnya, aplikasi tidak bisa menyembunyikan bilah status
|
||||
jika tidak berjalan dalam mode layar penuh.
|
||||
</li>
|
||||
|
||||
<li>Sistem akan mengabaikan perubahan pada atribut <code><a href=
|
||||
"{@docRoot}guide/topics/manifest/activity-element.html#screen"
|
||||
>android:screenOrientation</a></code>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="change-notification">Pemberitahuan perubahan multi-jendela dan melakukan kueri</h3>
|
||||
|
||||
<p>
|
||||
Metode baru berikut telah ditambahkan ke kelas {@link android.app.Activity}
|
||||
untuk mendukung tampilan multi-jendela. Untuk mengetahui detail tentang setiap
|
||||
metode, lihat <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi N
|
||||
Preview SDK</a>.
|
||||
</p>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<code>Activity.isInMultiWindowMode()</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Panggil untuk mengetahui apakah aktivitas berada dalam mode multi-jendela.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>Activity.isInPictureInPictureMode()</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Panggil untuk mengetahui apakah aktivitas berada dalam mode gambar-dalam-gambar.
|
||||
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Mode gambar-dalam-gambar adalah kasus khusus pada
|
||||
mode multi-jendela. Jika <code>myActivity.isInPictureInPictureMode()</code>
|
||||
mengembalikan nilai true, maka <code>myActivity.isInMultiWindowMode()</code> juga
|
||||
mengembalikan nilai true.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>Activity.onMultiWindowModeChanged()</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Sistem akan memanggil metode ini bila aktivitas masuk atau keluar dari
|
||||
mode multi-jendela. Sistem akan meneruskan ke metode sebuah nilai true jika
|
||||
aktivitas tersebut memasuki mode multi-jendela, dan nilai false jika aktivitas
|
||||
tersebut meninggalkan mode multi-jendela.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>Activity.onPictureInPictureModeChanged()</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Sistem akan memanggil metode ini bila aktivitas masuk atau keluar dari
|
||||
mode gambar-dalam-gambar. Sistem akan meneruskan ke metode sebuah nilai true jika
|
||||
aktivitas tersebut memasuki mode gambar-dalam-gambar, dan nilai false jika aktivitas
|
||||
tersebut meninggalkan mode gambar-dalam-gambar.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
Ada juga versi {@link android.app.Fragment} untuk setiap
|
||||
metode ini, misalnya <code>Fragment.isInMultiWindowMode()</code>.
|
||||
</p>
|
||||
|
||||
<h3 id="entering-pip">Memasuki mode gambar-dalam-gambar</h3>
|
||||
|
||||
<p>
|
||||
Untuk menempatkan aktivitas dalam mode gambar-dalam-gambar, panggil metode baru
|
||||
<code>Activity.enterPictureInPictureMode()</code>. Metode ini tidak berpengaruh jika
|
||||
perangkat tidak mendukung mode gambar-dalam-gambar. Untuk informasi selengkapnya,
|
||||
lihat dokumentasi <a href="picture-in-picture.html">Gambar-dalam-Gambar</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="launch">Meluncurkan Aktivitas Baru dalam Mode Multi-Jendela</h3>
|
||||
|
||||
<p>
|
||||
Bila meluncurkan aktivitas baru, Anda bisa memberi petunjuk pada sistem bahwa aktivitas
|
||||
baru harus ditampilkan bersebelahan dengan aktivitas yang sedang aktif, jika memungkinkan. Caranya,
|
||||
gunakan flag
|
||||
<code>Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT</code>. Meneruskan
|
||||
flag ini akan meminta perilaku berikut:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Jika perangkat berada dalam mode layar terbagi, sistem akan berupaya membuat
|
||||
aktivitas baru di sebelah aktivitas yang meluncurkannya, sehingga kedua aktivitas tersebut
|
||||
berbagi layar. Tidak ada jaminan sistem mampu melakukannya, namun sistem akan
|
||||
membuat aktivitas bersebelahan jika memungkinkan.
|
||||
</li>
|
||||
|
||||
<li>Jika perangkat tidak berada dalam mode layar terbagi, flag ini tidak akan berpengaruh.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Jika perangkat dalam mode bentuk bebas dan Anda menjalankan aktivitas baru, Anda bisa
|
||||
menetapkan dimensi aktivitas baru dan lokasi layar dengan memanggil
|
||||
<code>ActivityOptions.setLaunchBounds()</code>. Metode ini tidak berpengaruh jika
|
||||
perangkat tidak berada dalam mode multi-jendela.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Jika Anda meluncurkan aktivitas dalam tumpukan tugas, aktivitas
|
||||
tersebut akan menggantikan aktivitas pada layar, dengan mewarisi semua
|
||||
properti multi-jendelanya. Jika Anda ingin meluncurkan aktivitas baru sebagai jendela
|
||||
terpisah dalam mode multi-jendela, Anda harus meluncurkannya dalam tumpukan tugas baru.
|
||||
</p>
|
||||
|
||||
<h3 id="dnd">Mendukung seret dan lepas</h3>
|
||||
|
||||
<p>
|
||||
Pengguna bisa <a href="{@docRoot}guide/topics/ui/drag-drop.html">menyeret dan
|
||||
melepas</a> data dari satu aktivitas ke aktivitas yang lain selagi kedua aktivitas
|
||||
berbagi layar. (Sebelumnya, pengguna hanya bisa menyeret dan melepas data dalam
|
||||
aktivitas tunggal.) Karena alasan ini, Anda mungkin perlu menambahkan fungsionalitas
|
||||
seret dan lepas ke aplikasi jika aplikasi saat ini belum mendukungnya.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
N Preview SDK menambahkan paket <a href="{@docRoot}reference/android/view/package-summary.html"><code>android.view</code></a>
|
||||
untuk mendukung seret dan lepas lintas-aplikasi. Untuk mengetahui detail tentang kelas dan metode
|
||||
berikut, lihat <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi N
|
||||
Preview SDK</a>.
|
||||
</p>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<code>android.view.DropPermissions</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Objek token bertanggung jawab menetapkan izin yang diberikan kepada aplikasi
|
||||
yang menerima pelepasan tersebut.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>View.startDragAndDrop()</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Alias baru untuk {@link android.view.View#startDrag View.startDrag()}. Untuk
|
||||
mengaktifkan seret dan lepas lintas-aktivitas, teruskan flag baru
|
||||
<code>View.DRAG_FLAG_GLOBAL</code>. Jika Anda perlu memberikan izin URI ke
|
||||
aktivitas penerima, teruskan flag baru,
|
||||
<code>View.DRAG_FLAG_GLOBAL_URI_READ</code> atau
|
||||
<code>View.DRAG_FLAG_GLOBAL_URI_WRITE</code>, sebagaimana mestinya.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>View.cancelDragAndDrop()</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Membatalkan operasi seret yang sedang berlangsung. Hanya bisa dipanggil oleh
|
||||
aplikasi yang menghasilkan operasi seret.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>View.updateDragShadow()</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Menggantikan bayangan penyeretan untuk operasi seret yang sedang berlangsung. Hanya
|
||||
bisa dipanggil oleh aplikasi yang menghasilkan operasi seret.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>Activity.requestDropPermissions()</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Meminta izin untuk URI materi yang diteruskan dengan {@link
|
||||
android.content.ClipData} yang terdapat dalam {@link android.view.DragEvent}.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h2 id="testing">Menguji Dukungan Multi-Jendela Aplikasi Anda</h2>
|
||||
|
||||
<p>
|
||||
Apakah Anda memperbarui aplikasi untuk Android N atau tidak, Anda harus
|
||||
verifikasi bagaimana perilakunya di mode multi-jendela saat pengguna mencoba untuk menjalankannya
|
||||
dalam mode multi-jendela pada perangkat yang menjalankan Android N.
|
||||
</p>
|
||||
|
||||
<h3 id="configuring">Mengonfigurasi Perangkat Pengujian</h3>
|
||||
|
||||
<p>
|
||||
Jika Anda pasang Android N pada perangkat, mode
|
||||
layar terbagi secara otomatis didukung.
|
||||
</p>
|
||||
|
||||
<h3 id="test-non-n">Jika aplikasi Anda tidak dibangun dengan N Preview SDK</h3>
|
||||
|
||||
<p>
|
||||
Jika Anda tidak membangun aplikasi dengan N Preview SDK dan pengguna berupaya menggunakan
|
||||
aplikasi dalam mode multi-jendela, sistem secara paksa akan mengubah ukuran aplikasi kecuali jika aplikasi
|
||||
mendeklarasikan orientasi tetap.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Jika aplikasi Anda tidak mendeklarasikan orientasi tetap, Anda harus meluncurkan aplikasi
|
||||
pada perangkat yang menjalankan Android N dan berupaya menempatkan aplikasi tersebut dalam
|
||||
mode layar terbagi. Verifikasi pengalaman pengguna
|
||||
bisa diterima bila aplikasi secara paksa diubah ukurannya.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Jika aplikasi mendeklarasikan orientasi tetap, Anda harus berupaya menempatkan aplikasi dalam
|
||||
mode multi-jendela. Verifikasi apakah saat Anda melakukannya, aplikasi tetap berada dalam
|
||||
mode layar penuh.
|
||||
</p>
|
||||
|
||||
<h3 id="test-mw">Jika Anda mendukung mode multi-jendela</h3>
|
||||
|
||||
<p>
|
||||
Jika Anda membuat aplikasi Anda dengan N Preview SDK dan belum menonaktifkan
|
||||
dukungan multi-jendela, verifikasi perilaku berikut dalam mode layar terbagi
|
||||
dan mode bentuk bebas.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Luncurkan aplikasi dalam mode layar penuh, kemudian beralih ke mode multi-jendela dengan
|
||||
menekan lama pada tombol Ringkasan. Verifikasi apakah aplikasi beralih dengan benar.
|
||||
</li>
|
||||
|
||||
<li>Jalankan aplikasi secara langsung dalam mode multi-jendela, dan verifikasi aplikasi
|
||||
diluncurkan dengan benar. Anda bisa meluncurkan aplikasi dalam mode multi-jendela dengan menekan
|
||||
tombol Ringkasan, kemudian menekan lama baris judul pada aplikasi Anda dan menyeretnya
|
||||
ke salah satu area yang disorot di layar.
|
||||
</li>
|
||||
|
||||
<li>Ubah ukuran aplikasi Anda dalam mode layar terbagi dengan menyeret garis pembagi.
|
||||
Verifikasi apakah aplikasi mengubah ukuran tanpa mogok, dan apakah elemen UI yang diperlukan
|
||||
terlihat.
|
||||
</li>
|
||||
|
||||
<li>Jika Anda telah menetapkan dimensi minimum aplikasi, cobalah untuk mengubah ukuran
|
||||
aplikasi di bawah dimensi tersebut. Verifikasi apakah Anda tidak bisa mengubah ukuran aplikasi menjadi
|
||||
lebih kecil dari minimum yang ditetapkan.
|
||||
</li>
|
||||
|
||||
<li>Melalui semua pengujian, verifikasi apakah kinerja aplikasi Anda bisa diterima. Misalnya,
|
||||
verifikasi apakah tidak ada jeda yang terlalu lama untuk memperbarui UI setelah
|
||||
aplikasi diubah ukurannya.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4 id="test-checklist">Daftar periksa pengujian</h4>
|
||||
|
||||
<p>
|
||||
Untuk verifikasi kinerja aplikasi Anda dalam mode multi-jendela, cobalah operasi
|
||||
berikut. Anda harus mencoba semua operasi ini dalam mode layar terbagi dan
|
||||
dan mode multi-jendela, kecuali jika dinyatakan berbeda.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Masuki dan tinggalkan mode multi-jendela.
|
||||
</li>
|
||||
|
||||
<li>Beralih dari aplikasi Anda ke aplikasi lain, dan verifikasi apakah aplikasi berperilaku
|
||||
sebagaimana mestinya saat terlihat namun tidak aktif. Misalnya, jika aplikasi Anda
|
||||
sedang memutar video, verifikasi apakah video terus diputar selagi pengguna
|
||||
berinteraksi dengan aplikasi lain.
|
||||
</li>
|
||||
|
||||
<li>Dalam mode layar terbagi, cobalah menggeser garis pembagi untuk membuat aplikasi
|
||||
Anda menjadi lebih besar dan lebih kecil. Coba operasi ini dalam konfigurasi berdampingan dan
|
||||
atas-bawah. Verifikasi apakah aplikasi tidak mogok,
|
||||
fungsionalitas penting bisa terlihat, dan operasi mengubah ukuran tidak memakan waktu terlalu
|
||||
lama.
|
||||
</li>
|
||||
|
||||
<li>Lakukan beberapa operasi ubah ukuran berturut-turut dalam waktu cepat. Verifikasi apakah
|
||||
aplikasi Anda tidak mogok atau mengalami kebocoran memori. Untuk informasi tentang memeriksa penggunaan memori
|
||||
aplikasi Anda, lihat <a href="{@docRoot}tools/debugging/debugging-memory.html">
|
||||
Menyelidiki Penggunaan RAM Anda</a>.
|
||||
</li>
|
||||
|
||||
<li>Gunakan aplikasi secara normal di sejumlah konfigurasi jendela yang berbeda, dan
|
||||
verifikasi apakah aplikasi berperilaku sebagaimana mestinya. Verifikasi apakah teks terbaca, dan apakah
|
||||
elemen UI tidak terlalu kecil untuk interaksi.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="test-disabled-mw">Jika Anda telah menonaktifkan dukungan multi-jendela</h3>
|
||||
|
||||
<p>
|
||||
Jika Anda menonaktifkan dukungan multi-jendela dengan menyetel
|
||||
<code>android:resizableActivity="false"</code>, Anda harus menjalankan aplikasi pada
|
||||
perangkat yang menjalankan Android N dan berusaha menempatkan aplikasi dalam
|
||||
mode bentuk bebas dan mode layar terbagi. Verifikasi apakah saat Anda melakukannya, aplikasi tetap berada dalam
|
||||
mode layar penuh.
|
||||
</p>
|
||||
@@ -0,0 +1,979 @@
|
||||
page.title=Pemberitahuan
|
||||
@jd:body
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#Design">Pertimbangan Desain</a></li>
|
||||
<li><a href="#CreateNotification">Membuat Pemberitahuan</a>
|
||||
<ol>
|
||||
<li><a href="#Required">Isi pemberitahuan yang diperlukan</a></li>
|
||||
<li><a href="#Optional">Isi dan pengaturan pemberitahuan opsional</a></li>
|
||||
<li><a href="#Actions">Tindakan pemberitahuan</a></li>
|
||||
<li><a href="#Priority">Prioritas pemberitahuan</a></li>
|
||||
<li><a href="#SimpleNotification">Membuat pemberitahuan sederhana</a></li>
|
||||
<li><a href="#ApplyStyle">Menerapkan layout yang diperluas pada pemberitahuan</a></li>
|
||||
<li><a href="#Compatibility">Menangani kompatibilitas</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#Managing">Mengelola Pemberitahuan</a>
|
||||
<ol>
|
||||
<li><a href="#Updating">Memperbarui pemberitahuan</a></li>
|
||||
<li><a href="#Removing">Menghapus pemberitahuan</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#NotificationResponse">Mempertahankan Navigasi saat Memulai Aktivitas</a>
|
||||
<ol>
|
||||
<li><a href="#DirectEntry">Menyiapkan PendingIntent aktivitas biasa</a></li>
|
||||
<li><a href="#ExtendedNotification">Menyiapkan PendingIntent aktivitas khusus</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#Progress">Menampilkan Kemajuan dalam Pemberitahuan</a>
|
||||
<ol>
|
||||
<li><a href="#FixedProgress">Menampilkan indikator kemajuan berdurasi tetap</a></li>
|
||||
<li><a href="#ActivityIndicator">Menampilkan indikator aktivitas berlanjut</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#metadata">Metadata Pemberitahuan</a></li>
|
||||
<li><a href="#Heads-up">Pemberitahuan Pendahuluan</a></li>
|
||||
<li><a href="#lockscreenNotification">Pemberitahuan Layar Kunci</a></li>
|
||||
<ol>
|
||||
<li><a href="#visibility">Mengatur Visibilitas</a></li>
|
||||
<li><a href="#controllingMedia">Mengontrol Pemutaran Media pada Layar Kunci</a></li>
|
||||
</ol>
|
||||
<li><a href="#CustomNotification">Layout Pemberitahuan Custom</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>Kelas-kelas utama</h2>
|
||||
<ol>
|
||||
<li>{@link android.app.NotificationManager}</li>
|
||||
<li>{@link android.support.v4.app.NotificationCompat}</li>
|
||||
</ol>
|
||||
<h2>Video</h2>
|
||||
<ol>
|
||||
<li>
|
||||
<a href="http://www.youtube.com/watch?v=Yc8YrVc47TI&feature=player_detailpage#t=1672s">
|
||||
Pemberitahuan di 4.1</a>
|
||||
</li>
|
||||
</ol>
|
||||
<h2>Lihat juga</h2>
|
||||
<ol>
|
||||
<li>
|
||||
<a href="{@docRoot}design/patterns/notifications.html">Desain Android: Pemberitahuan</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
Pemberitahuan adalah pesan yang bisa Anda tampilkan kepada pengguna di luar
|
||||
UI normal aplikasi. Bila Anda memberi tahu sistem untuk mengeluarkan pemberitahuan, pemberitahuan akan muncul lebih dahulu sebagai ikon dalam
|
||||
<strong>area pemberitahuan</strong>. Untuk melihat detail pemberitahuan, pengguna membuka
|
||||
<strong>laci pemberitahuan</strong>. Baik area pemberitahuan maupun laci pemberitahuan
|
||||
adalah area-area yang dikontrol sistem yang bisa dilihat pengguna kapan saja.
|
||||
</p>
|
||||
<img id="figure1" src="{@docRoot}images/ui/notifications/notification_area.png" height="" alt="" />
|
||||
<p class="img-caption">
|
||||
<strong>Gambar 1.</strong> Pemberitahuan di area pemberitahuan.
|
||||
</p>
|
||||
<img id="figure2" src="{@docRoot}images/ui/notifications/notification_drawer.png" width="280px" alt="" />
|
||||
<p class="img-caption">
|
||||
<strong>Gambar 2.</strong> Pemberitahuan di laci pemberitahuan.
|
||||
</p>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> Kecuali disebutkan, panduan ini mengacu pada
|
||||
kelas {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}
|
||||
dalam <a href="{@docRoot}tools/support-library/index.html">Support Library</a> versi 4.
|
||||
Kelas {@link android.app.Notification.Builder Notification.Builder} telah ditambahkan pada Android
|
||||
3.0 (API level 11).</p>
|
||||
|
||||
<h2 id="Design">Pertimbangan Desain</h2>
|
||||
|
||||
<p>Pemberitahuan, sebagai bagian penting dari antarmuka pengguna Android, memiliki panduan desainnya sendiri.
|
||||
Perubahan desain materi yang diperkenalkan dalam Android 5.0 (API level 21) adalah sangat
|
||||
penting, dan Anda harus meninjau pelatihan <a href="{@docRoot}training/material/index.html">Desain Bahan</a>
|
||||
untuk informasi selengkapnya. Untuk mengetahui cara mendesain pemberitahuan dan interaksinya, bacalah panduan desain
|
||||
<a href="{@docRoot}design/patterns/notifications.html">Pemberitahuan</a>.</p>
|
||||
|
||||
<h2 id="CreateNotification">Membuat Pemberitahuan</h2>
|
||||
|
||||
<p>Anda menetapkan informasi dan tindakan UI bagi pemberitahuan dalam
|
||||
objek {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}.
|
||||
Untuk membuat pemberitahuan itu sendiri, panggil
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#build NotificationCompat.Builder.build()},
|
||||
yang akan mengembalikan objek {@link android.app.Notification} berisi spesifikasi Anda. Untuk mengeluarkan
|
||||
pemberitahuan, Anda meneruskan objek {@link android.app.Notification} ke sistem dengan memanggil
|
||||
{@link android.app.NotificationManager#notify NotificationManager.notify()}.</p>
|
||||
|
||||
<h3 id="Required">Isi pemberitahuan yang diperlukan</h3>
|
||||
<p>
|
||||
Objek {@link android.app.Notification} <em>harus</em> berisi yang berikut ini:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Ikon kecil, yang diatur dengan
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setSmallIcon setSmallIcon()}
|
||||
</li>
|
||||
<li>
|
||||
Judul, yang diatur dengan
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}
|
||||
</li>
|
||||
<li>
|
||||
Teks detail, yang diatur dengan
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setContentText setContentText()}
|
||||
</li>
|
||||
</ul>
|
||||
<h3 id="Optional">Isi dan pengaturan pemberitahuan opsional</h3>
|
||||
<p>
|
||||
Semua isi dan pengaturan pemberitahuan lainnya bersifat opsional. Untuk mengetahui selengkapnya tentang semua itu,
|
||||
lihat dokumentasi acuan untuk {@link android.support.v4.app.NotificationCompat.Builder}.
|
||||
</p>
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h3 id="Actions">Tindakan pemberitahuan</h3>
|
||||
<p>
|
||||
Walaupun bersifat opsional, Anda harus menambahkan setidaknya satu tindakan pada pemberitahuan.
|
||||
Tindakan memungkinkan pengguna beralih langsung dari pemberitahuan ke
|
||||
{@link android.app.Activity} dalam aplikasi Anda, tempat pengguna bisa melihat satu atau beberapa kejadian
|
||||
atau melakukan pekerjaan lebih jauh.
|
||||
</p>
|
||||
<p>
|
||||
Pemberitahuan bisa menyediakan beberapa tindakan sekaligus. Anda harus selalu mendefinisikan tindakan yang
|
||||
akan diaktifkan bila pengguna mengklik pemberitahuan; biasanya tindakan ini akan membuka
|
||||
{@link android.app.Activity} dalam aplikasi Anda. Anda juga bisa menambahkan tombol pada pemberitahuan
|
||||
yang melakukan tindakan tambahan seperti mendiamkan alarm atau segera merespons
|
||||
pesan teks; fitur ini tersedia mulai Android 4.1. Jika menggunakan tombol tindakan tambahan, Anda
|
||||
juga harus membuat fungsionalitasnya tersedia dalam {@link android.app.Activity} di aplikasi Anda; lihat
|
||||
bagian <a href="#Compatibility">Menangani kompatibilitas</a> untuk detail selengkapnya.
|
||||
</p>
|
||||
<p>
|
||||
Dalam {@link android.app.Notification}, tindakan itu sendiri didefinisikan oleh
|
||||
{@link android.app.PendingIntent} berisi
|
||||
{@link android.content.Intent} yang memulai
|
||||
{@link android.app.Activity} dalam aplikasi Anda. Untuk mengaitkan
|
||||
{@link android.app.PendingIntent} dengan gestur, panggil metode
|
||||
{@link android.support.v4.app.NotificationCompat.Builder} yang sesuai. Misalnya, jika ingin memulai
|
||||
{@link android.app.Activity} bila pengguna mengklik teks pemberitahuan pada
|
||||
laci pemberitahuan, tambahkan {@link android.app.PendingIntent} dengan memanggil
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}.
|
||||
</p>
|
||||
<p>
|
||||
Memulai {@link android.app.Activity} bila pengguna mengklik pemberitahuan adalah
|
||||
skenario tindakan yang paling umum. Anda juga bisa memulai {@link android.app.Activity} bila pengguna
|
||||
menghilangkan pemberitahuan. Dalam Android 4.1 dan yang lebih baru, Anda bisa memulai
|
||||
{@link android.app.Activity} dari tombol tindakan. Untuk mengetahui selengkapnya, bacalah panduan acuan untuk
|
||||
{@link android.support.v4.app.NotificationCompat.Builder}.
|
||||
</p>
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h3 id="Priority">Prioritas pemberitahuan</h3>
|
||||
<p>
|
||||
Jika diinginkan, Anda bisa mengatur prioritas pemberitahuan. Prioritas berfungsi
|
||||
sebagai petunjuk bagi UI perangkat tentang cara menampilkan pemberitahuan.
|
||||
Untuk mengatur prioritas pemberitahuan, panggil {@link
|
||||
android.support.v4.app.NotificationCompat.Builder#setPriority(int)
|
||||
NotificationCompat.Builder.setPriority()} dan teruskan salah satu konstanta prioritas {@link
|
||||
android.support.v4.app.NotificationCompat}. Ada
|
||||
lima level prioritas, mulai dari {@link
|
||||
android.support.v4.app.NotificationCompat#PRIORITY_MIN} (-2) hingga {@link
|
||||
android.support.v4.app.NotificationCompat#PRIORITY_MAX} (2); jika tidak diatur,
|
||||
prioritas default akan ditetapkan {@link
|
||||
android.support.v4.app.NotificationCompat#PRIORITY_DEFAULT} (0).
|
||||
</p>
|
||||
<p> Untuk informasi tentang mengatur level prioritas, lihat "Mengatur
|
||||
dan mengelola prioritas pemberitahuan dengan benar" dalam panduan
|
||||
Desain <a href="{@docRoot}design/patterns/notifications.html">Pemberitahuan</a>.
|
||||
</p>
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h3 id="SimpleNotification">Membuat pemberitahuan sederhana</h3>
|
||||
<p>
|
||||
Cuplikan berikut mengilustrasikan pemberitahuan sederhana yang menetapkan aktivitas untuk dibuka bila
|
||||
pengguna mengklik pemberitahuan. Perhatikan bahwa kode ini membuat
|
||||
objek {@link android.support.v4.app.TaskStackBuilder} dan menggunakannya untuk membuat
|
||||
{@link android.app.PendingIntent} untuk tindakan. Pola ini dijelaskan secara lebih detail
|
||||
di bagian <a href="#NotificationResponse">
|
||||
Mempertahankan Navigasi saat Memulai Aktivitas</a>:
|
||||
</p>
|
||||
<pre>
|
||||
NotificationCompat.Builder mBuilder =
|
||||
new NotificationCompat.Builder(this)
|
||||
.setSmallIcon(R.drawable.notification_icon)
|
||||
.setContentTitle("My notification")
|
||||
.setContentText("Hello World!");
|
||||
// Creates an explicit intent for an Activity in your app
|
||||
Intent resultIntent = new Intent(this, ResultActivity.class);
|
||||
|
||||
// The stack builder object will contain an artificial back stack for the
|
||||
// started Activity.
|
||||
// This ensures that navigating backward from the Activity leads out of
|
||||
// your application to the Home screen.
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
|
||||
// Adds the back stack for the Intent (but not the Intent itself)
|
||||
stackBuilder.addParentStack(ResultActivity.class);
|
||||
// Adds the Intent that starts the Activity to the top of the stack
|
||||
stackBuilder.addNextIntent(resultIntent);
|
||||
PendingIntent resultPendingIntent =
|
||||
stackBuilder.getPendingIntent(
|
||||
0,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
);
|
||||
mBuilder.setContentIntent(resultPendingIntent);
|
||||
NotificationManager mNotificationManager =
|
||||
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
// mId allows you to update the notification later on.
|
||||
mNotificationManager.notify(mId, mBuilder.build());
|
||||
</pre>
|
||||
<p>Demikian saja. Pengguna Anda kini telah diberi tahu.</p>
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h3 id="ApplyStyle">Menerapkan layout yang diperluas pada pemberitahuan</h3>
|
||||
<p>
|
||||
Agar pemberitahuan muncul dalam tampilan yang diperluas, buat dahulu
|
||||
objek {@link android.support.v4.app.NotificationCompat.Builder} dengan opsi tampilan normal
|
||||
yang Anda inginkan. Berikutnya, panggil {@link android.support.v4.app.NotificationCompat.Builder#setStyle
|
||||
Builder.setStyle()} dengan objek layout yang diperluas sebagai argumennya.
|
||||
</p>
|
||||
<p>
|
||||
Ingatlah bahwa pemberitahuan yang diperluas tidak tersedia pada platform-platform sebelum Android 4.1. Untuk
|
||||
mengetahui cara menangani pemberitahuan untuk Android 4.1 dan untuk platform-platform sebelumnya, bacalah
|
||||
bagian <a href="#Compatibility">Menangani kompatibilitas</a>.
|
||||
</p>
|
||||
<p>
|
||||
Misalnya, cuplikan kode berikut memperagakan cara mengubah pemberitahuan yang dibuat
|
||||
dalam cuplikan sebelumnya untuk menggunakan layout yang diperluas:
|
||||
</p>
|
||||
<pre>
|
||||
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
|
||||
.setSmallIcon(R.drawable.notification_icon)
|
||||
.setContentTitle("Event tracker")
|
||||
.setContentText("Events received")
|
||||
NotificationCompat.InboxStyle inboxStyle =
|
||||
new NotificationCompat.InboxStyle();
|
||||
String[] events = new String[6];
|
||||
// Sets a title for the Inbox in expanded layout
|
||||
inboxStyle.setBigContentTitle("Event tracker details:");
|
||||
...
|
||||
// Moves events into the expanded layout
|
||||
for (int i=0; i < events.length; i++) {
|
||||
|
||||
inboxStyle.addLine(events[i]);
|
||||
}
|
||||
// Moves the expanded layout object into the notification object.
|
||||
mBuilder.setStyle(inBoxStyle);
|
||||
...
|
||||
// Issue the notification here.
|
||||
</pre>
|
||||
|
||||
<h3 id="Compatibility">Menangani kompatibilitas</h3>
|
||||
|
||||
<p>
|
||||
Tidak semua fitur pemberitahuan tersedia untuk versi tertentu, walaupun
|
||||
metode untuk mengaturnya ada dalam kelas pustaka dukungan
|
||||
{@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}.
|
||||
Misalnya, tombol tindakan, yang bergantung pada pemberitahuan yang diperluas, hanya muncul pada Android
|
||||
4.1 dan lebih tinggi, karena pemberitahuan yang diperluas itu sendiri hanya tersedia pada
|
||||
Android 4.1 dan yang lebih tinggi.
|
||||
</p>
|
||||
<p>
|
||||
Untuk memastikan kompatibilitas terbaik, buatlah pemberitahuan dengan
|
||||
{@link android.support.v4.app.NotificationCompat NotificationCompat} dan subkelasnya,
|
||||
khususnya {@link android.support.v4.app.NotificationCompat.Builder
|
||||
NotificationCompat.Builder}. Selain itu, ikutilah proses ini bila Anda mengimplementasikan pemberitahuan:
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
Sediakan semua fungsionalitas pemberitahuan kepada semua pengguna, terlepas dari versi
|
||||
yang mereka gunakan. Caranya, pastikan semua fungsionalitas tersedia dari
|
||||
{@link android.app.Activity} dalam aplikasi Anda. Anda mungkin perlu menambahkan sebuah
|
||||
{@link android.app.Activity} baru untuk melakukannya.
|
||||
<p>
|
||||
Misalnya, jika Anda ingin menggunakan
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#addAction addAction()} untuk
|
||||
menyediakan kontrol yang menghentikan dan memulai pemutaran media, implementasikan dahulu
|
||||
kontrol ini pada {@link android.app.Activity} dalam aplikasi Anda.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Pastikan semua pengguna bisa memperoleh fungsionalitas dalam {@link android.app.Activity},
|
||||
dengan memulainya bila pengguna mengklik pemberitahuan. Caranya,
|
||||
buatlah {@link android.app.PendingIntent}
|
||||
untuk {@link android.app.Activity}. Panggil
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
|
||||
setContentIntent()} untuk menambahkan {@link android.app.PendingIntent} pada pemberitahuan.
|
||||
</li>
|
||||
<li>
|
||||
Kini tambahkan fitur pemberitahuan diperluas yang ingin Anda gunakan pada pemberitahuan. Ingatlah
|
||||
bahwa setiap fungsionalitas yang Anda tambahkan juga harus tersedia dalam {@link android.app.Activity}
|
||||
yang akan dimulai bila pengguna mengklik pemberitahuan.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h2 id="Managing">Mengelola Pemberitahuan</h2>
|
||||
<p>
|
||||
Bila perlu mengeluarkan pemberitahuan beberapa kali untuk tipe kejadian yang sama,
|
||||
hindari membuat pemberitahuan yang sama sekali baru. Sebagai gantinya, Anda harus mempertimbangkan untuk memperbarui
|
||||
pemberitahuan sebelumnya, baik dengan mengubah sebagian nilainya atau dengan menambahkan nilai, atau keduanya.
|
||||
</p>
|
||||
<p>
|
||||
Misalnya, Gmail akan memberi tahu pengguna bila ada email baru dengan menambah hitungan
|
||||
pesan tidak terbaca dan dengan menambahkan rangkuman tiap email ke pemberitahuan. Ini disebut dengan
|
||||
"stacking" (menumpuk) pemberitahuan; hal ini dijelaskan lebih detail dalam panduan
|
||||
Desain <a href="{@docRoot}design/patterns/notifications.html">Pemberitahuan</a>.
|
||||
</p>
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Fitur Gmail ini mensyaratkan layout "kotak masuk" diperluas, yang merupakan
|
||||
bagian dari fitur pemberitahuan diperluas yang tersedia mulai Android 4.1.
|
||||
</p>
|
||||
<p>
|
||||
Bagian berikut menjelaskan cara memperbarui pemberitahuan dan cara menghapusnya.
|
||||
</p>
|
||||
<h3 id="Updating">Memperbarui pemberitahuan</h3>
|
||||
<p>
|
||||
Untuk menyiapkan pemberitahuan agar bisa diperbarui, keluarkan pemberitahuan bersama ID pemberitahuan dengan
|
||||
memanggil {@link android.app.NotificationManager#notify(int, android.app.Notification) NotificationManager.notify()}.
|
||||
Untuk memperbarui pemberitahuan ini setelah Anda
|
||||
mengeluarkan, memperbarui, atau membuat objek {@link android.support.v4.app.NotificationCompat.Builder},
|
||||
buat objek {@link android.app.Notification} darinya, dan keluarkan
|
||||
{@link android.app.Notification} bersama ID yang sama dengan yang Anda gunakan sebelumnya. Jika
|
||||
pemberitahuan sebelumnya tetap terlihat, sistem akan memperbaruinya dari konten
|
||||
objek {@link android.app.Notification}. Jika pemberitahuan sebelumnya telah dihilangkan, sebuah
|
||||
pemberitahuan baru akan dibuat.
|
||||
</p>
|
||||
<p>
|
||||
Cuplikan berikut memperagakan pemberitahuan yang diperbarui untuk mencerminkan
|
||||
jumlah kejadian yang telah terjadi. Cuplikan ini menumpuk pemberitahuan, yang menampilkan rangkuman:
|
||||
</p>
|
||||
<pre>
|
||||
mNotificationManager =
|
||||
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
// Sets an ID for the notification, so it can be updated
|
||||
int notifyID = 1;
|
||||
mNotifyBuilder = new NotificationCompat.Builder(this)
|
||||
.setContentTitle("New Message")
|
||||
.setContentText("You've received new messages.")
|
||||
.setSmallIcon(R.drawable.ic_notify_status)
|
||||
numMessages = 0;
|
||||
// Start of a loop that processes data and then notifies the user
|
||||
...
|
||||
mNotifyBuilder.setContentText(currentText)
|
||||
.setNumber(++numMessages);
|
||||
// Because the ID remains unchanged, the existing notification is
|
||||
// updated.
|
||||
mNotificationManager.notify(
|
||||
notifyID,
|
||||
mNotifyBuilder.build());
|
||||
...
|
||||
</pre>
|
||||
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h3 id="Removing">Menghapus pemberitahuan</h3>
|
||||
<p>
|
||||
Pemberitahuan tetap terlihat hingga salah satu kejadian berikut terjadi:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Pengguna menghilangkan pemberitahuan satu per satu atau dengan menggunakan "Clear All" (jika
|
||||
pemberitahuan bisa dihapus).
|
||||
</li>
|
||||
<li>
|
||||
Pengguna mengklik pemberitahuan, dan Anda memanggil
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setAutoCancel setAutoCancel()} bila
|
||||
Anda telah membuat pemberitahuan.
|
||||
</li>
|
||||
<li>
|
||||
Anda memanggil {@link android.app.NotificationManager#cancel(int) cancel()} untuk
|
||||
ID pemberitahuan tertentu. Metode ini juga menghapus pemberitahuan yang berjalan.
|
||||
</li>
|
||||
<li>
|
||||
Anda memanggil {@link android.app.NotificationManager#cancelAll() cancelAll()}, yang menghapus
|
||||
semua pemberitahuan yang dikeluarkan sebelumnya.
|
||||
</li>
|
||||
</ul>
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h2 id="NotificationResponse">Mempertahankan Navigasi saat Memulai Aktivitas</h2>
|
||||
<p>
|
||||
Bila memulai {@link android.app.Activity} dari pemberitahuan, Anda harus mempertahankan
|
||||
pengalaman navigasi yang diharapkan pengguna. Mengklik <i>Back</i> harus membawa pengguna kembali melalui
|
||||
aliran pekerjaan normal aplikasi ke layar Home, dan mengklik <i>Recents</i> harus menampilkan
|
||||
{@link android.app.Activity} sebagai tugas terpisah. Untuk mempertahankan pengalaman navigasi, Anda
|
||||
harus memulai {@link android.app.Activity} dalam tugas baru. Cara menyiapkan
|
||||
{@link android.app.PendingIntent} untuk memberi Anda tugas baru bergantung pada sifat
|
||||
{@link android.app.Activity} yang Anda mulai. Ada dua situasi umum:
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
Aktivitas rutin
|
||||
</dt>
|
||||
<dd>
|
||||
Anda memulai {@link android.app.Activity} yang merupakan bagian dari aliran pekerjaan normal
|
||||
aplikasi. Dalam situasi ini, siapkan {@link android.app.PendingIntent} untuk
|
||||
memulai tugas baru, dan sediakan {@link android.app.PendingIntent} bersama back-stack
|
||||
yang meniru perilaku <i>Back</i> biasa.
|
||||
<p>
|
||||
Pemberitahuan dari aplikasi Gmail memperagakan hal ini. Bila Anda mengklik pemberitahuan untuk
|
||||
satu pesan email, Anda akan melihat pesan itu sendiri. Menyentuh <b>Back</b> akan membawa Anda
|
||||
kembali melalui Gmail ke layar Home, persis seperti jika memasuki Gmail dari
|
||||
layar Home bukannya memasukinya dari pemberitahuan.
|
||||
</p>
|
||||
<p>
|
||||
Hal ini terjadi terlepas dari aplikasi tempat Anda berada saat menyentuh
|
||||
pemberitahuan. Misalnya, jika Anda dalam Gmail sedang menulis pesan, dan Anda mengklik
|
||||
pemberitahuan untuk satu email, Anda akan segera dibawa ke email itu. Menyentuh <i>Back</i>
|
||||
akan membawa Anda ke kotak masuk kemudian layar Home, bukannya membawa Anda ke
|
||||
pesan yang sedang ditulis.
|
||||
</p>
|
||||
</dd>
|
||||
<dt>
|
||||
Aktivitas khusus
|
||||
</dt>
|
||||
<dd>
|
||||
Pengguna hanya melihat {@link android.app.Activity} ini jika dimulai dari pemberitahuan.
|
||||
Dalam beberapa hal, {@link android.app.Activity} akan memperluas pemberitahuan dengan menyediakan
|
||||
informasi yang akan sulit untuk ditampilkan dalam pemberitahuan itu sendiri. Untuk situasi ini,
|
||||
siapkan {@link android.app.PendingIntent} untuk dimulai dalam tugas baru. Tidak perlu
|
||||
membuat back-stack, karena {@link android.app.Activity} yang dimulai bukan bagian dari
|
||||
aliran aktivitas aplikasi. Mengklik <i>Back</i> tetap akan membawa pengguna ke
|
||||
layar Home.
|
||||
</dd>
|
||||
</dl>
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h3 id="DirectEntry">Menyiapkan PendingIntent aktivitas biasa</h3>
|
||||
<p>
|
||||
Untuk menyiapkan {@link android.app.PendingIntent} yang memulai entri langsung
|
||||
{@link android.app.Activity}, ikuti langkah-langkah ini:
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
Definisikan hierarki {@link android.app.Activity} aplikasi Anda dalam manifes.
|
||||
<ol style="list-style-type: lower-alpha;">
|
||||
<li>
|
||||
Tambahkan dukungan untuk Android 4.0.3 dan yang terdahulu. Caranya, tetapkan induk
|
||||
{@link android.app.Activity} yang Anda mulai dengan menambahkan elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html"><meta-data></a></code>
|
||||
sebagai anak
|
||||
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>.
|
||||
<p>
|
||||
Untuk elemen ini, atur
|
||||
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a>="android.support.PARENT_ACTIVITY"</code>.
|
||||
Atur
|
||||
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#val">android:value</a>="<parent_activity_name>"</code>
|
||||
dengan <code><parent_activity_name></code> sebagai nilai
|
||||
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code>
|
||||
untuk elemen induk
|
||||
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>
|
||||
. Lihat XML berikut sebagai contoh.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Juga tambahkan dukungan untuk Android 4.1 dan yang lebih baru. Caranya, tambahkan atribut
|
||||
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">android:parentActivityName</a></code>
|
||||
pada elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>
|
||||
dari {@link android.app.Activity} yang Anda mulai.
|
||||
</li>
|
||||
</ol>
|
||||
<p>
|
||||
XML akhir akan terlihat seperti ini:
|
||||
</p>
|
||||
<pre>
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ResultActivity"
|
||||
android:parentActivityName=".MainActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".MainActivity"/>
|
||||
</activity>
|
||||
</pre>
|
||||
</li>
|
||||
<li>
|
||||
Buat back-stack berdasarkan {@link android.content.Intent} yang memulai
|
||||
{@link android.app.Activity}:
|
||||
<ol style="list-style-type: lower-alpha;">
|
||||
<li>
|
||||
Buat {@link android.content.Intent} untuk memulai {@link android.app.Activity}.
|
||||
</li>
|
||||
<li>
|
||||
Buat stack-builder (pembangun tumpukan) dengan memanggil {@link android.app.TaskStackBuilder#create
|
||||
TaskStackBuilder.create()}.
|
||||
</li>
|
||||
<li>
|
||||
Tambahkan back-stack ke stack-builder dengan memanggil
|
||||
{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}.
|
||||
Untuk setiap {@link android.app.Activity} dalam hierarki yang telah Anda definisikan dalam
|
||||
manifes, back-stack berisi objek {@link android.content.Intent} yang
|
||||
memulai {@link android.app.Activity}. Metode ini juga menambahkan flag yang memulai
|
||||
back-stack dalam tugas baru.
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Walaupun argumen untuk
|
||||
{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}
|
||||
adalah acuan ke {@link android.app.Activity} yang dimulai, panggilan metode
|
||||
tidak akan menambahkan {@link android.content.Intent} yang memulai
|
||||
{@link android.app.Activity}. Sebagai gantinya, hal itu ditangani dalam langkah berikutnya.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
Tambahkan {@link android.content.Intent} yang memulai {@link android.app.Activity}
|
||||
dari pemberitahuan, dengan memanggil
|
||||
{@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
|
||||
Teruskan {@link android.content.Intent} yang Anda buat dalam langkah pertama sebagai
|
||||
argumen ke
|
||||
{@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
|
||||
</li>
|
||||
<li>
|
||||
Jika perlu, tambahkan argumen ke objek {@link android.content.Intent} pada
|
||||
back-stack dengan memanggil {@link android.support.v4.app.TaskStackBuilder#editIntentAt
|
||||
TaskStackBuilder.editIntentAt()}. Kadang-kadang perlu memastikan apakah
|
||||
{@link android.app.Activity} target menampilkan data bermakna saat pengguna menelusurinya
|
||||
dengan menggunakan <i>Back</i>.
|
||||
</li>
|
||||
<li>
|
||||
Dapatkan {@link android.app.PendingIntent} untuk back-stack ini dengan memanggil
|
||||
{@link android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}.
|
||||
Anda nanti bisa menggunakan {@link android.app.PendingIntent} ini sebagai argumen untuk
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
|
||||
setContentIntent()}.
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
<p>
|
||||
Cuplikan kode berikut memperagakan prosesnya:
|
||||
</p>
|
||||
<pre>
|
||||
...
|
||||
Intent resultIntent = new Intent(this, ResultActivity.class);
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
|
||||
// Adds the back stack
|
||||
stackBuilder.addParentStack(ResultActivity.class);
|
||||
// Adds the Intent to the top of the stack
|
||||
stackBuilder.addNextIntent(resultIntent);
|
||||
// Gets a PendingIntent containing the entire back stack
|
||||
PendingIntent resultPendingIntent =
|
||||
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
...
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
|
||||
builder.setContentIntent(resultPendingIntent);
|
||||
NotificationManager mNotificationManager =
|
||||
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
mNotificationManager.notify(id, builder.build());
|
||||
</pre>
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h3 id="ExtendedNotification">Menyiapkan PendingIntent aktivitas khusus</h3>
|
||||
<p>
|
||||
Bagian berikut menjelaskan cara menyiapkan aktivitas khusus
|
||||
{@link android.app.PendingIntent}.
|
||||
</p>
|
||||
<p>
|
||||
{@link android.app.Activity} khusus tidak memerlukan back-stack, sehingga Anda tidak perlu
|
||||
mendefinisikan hierarki {@link android.app.Activity}-nya dalam manifes, dan Anda tidak perlu
|
||||
memanggil
|
||||
{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} untuk membuat
|
||||
back-stack. Sebagai gantinya, gunakan manifes untuk menyiapkan opsi tugas {@link android.app.Activity},
|
||||
dan buat {@link android.app.PendingIntent} dengan memanggil
|
||||
{@link android.app.PendingIntent#getActivity getActivity()}:
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
Dalam manifes, tambahkan atribut berikut pada elemen
|
||||
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>
|
||||
untuk {@link android.app.Activity}
|
||||
<dl>
|
||||
<dt>
|
||||
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code>
|
||||
</dt>
|
||||
<dd>
|
||||
Nama kelas mutlak (fully qualified) aktivitas.
|
||||
</dd>
|
||||
<dt>
|
||||
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code>
|
||||
</dt>
|
||||
<dd>
|
||||
Dikombinasikan dengan flag
|
||||
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
|
||||
yang Anda atur dalam kode, ini memastikan bahwa {@link android.app.Activity} ini tidak
|
||||
masuk ke dalam tugas default aplikasi. Setiap tugas yang ada yang memiliki
|
||||
afinitas default aplikasi tidak terpengaruh.
|
||||
</dd>
|
||||
<dt>
|
||||
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code>
|
||||
</dt>
|
||||
<dd>
|
||||
Mengecualikan tugas baru dari <i>Recents</i>, sehingga pengguna tidak bisa tanpa sengaja
|
||||
mengarahkan kembali.
|
||||
</dd>
|
||||
</dl>
|
||||
<p>
|
||||
Cuplikan ini menampilkan elemen:
|
||||
</p>
|
||||
<pre>
|
||||
<activity
|
||||
android:name=".ResultActivity"
|
||||
...
|
||||
android:launchMode="singleTask"
|
||||
android:taskAffinity=""
|
||||
android:excludeFromRecents="true">
|
||||
</activity>
|
||||
...
|
||||
</pre>
|
||||
</li>
|
||||
<li>
|
||||
Buat dan keluarkan pemberitahuan:
|
||||
<ol style="list-style-type: lower-alpha;">
|
||||
<li>
|
||||
Buat {@link android.content.Intent} yang memulai
|
||||
{@link android.app.Activity}.
|
||||
</li>
|
||||
<li>
|
||||
Atur {@link android.app.Activity} untuk dimulai dalam tugas kosong yang baru dengan memanggil
|
||||
{@link android.content.Intent#setFlags setFlags()} dengan flag
|
||||
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
|
||||
dan
|
||||
{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}.
|
||||
</li>
|
||||
<li>
|
||||
Atur setiap opsi lain yang Anda perlukan untuk {@link android.content.Intent}.
|
||||
</li>
|
||||
<li>
|
||||
Buat {@link android.app.PendingIntent} dari {@link android.content.Intent}
|
||||
dengan memanggil {@link android.app.PendingIntent#getActivity getActivity()}.
|
||||
Anda nanti bisa menggunakan {@link android.app.PendingIntent} ini sebagai argumen untuk
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
|
||||
setContentIntent()}.
|
||||
</li>
|
||||
</ol>
|
||||
<p>
|
||||
Cuplikan kode berikut memperagakan prosesnya:
|
||||
</p>
|
||||
<pre>
|
||||
// Instantiate a Builder object.
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
|
||||
// Creates an Intent for the Activity
|
||||
Intent notifyIntent =
|
||||
new Intent(this, ResultActivity.class);
|
||||
// Sets the Activity to start in a new, empty task
|
||||
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
// Creates the PendingIntent
|
||||
PendingIntent notifyPendingIntent =
|
||||
PendingIntent.getActivity(
|
||||
this,
|
||||
0,
|
||||
notifyIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
);
|
||||
|
||||
// Puts the PendingIntent into the notification builder
|
||||
builder.setContentIntent(notifyPendingIntent);
|
||||
// Notifications are issued by sending them to the
|
||||
// NotificationManager system service.
|
||||
NotificationManager mNotificationManager =
|
||||
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
// Builds an anonymous Notification object from the builder, and
|
||||
// passes it to the NotificationManager
|
||||
mNotificationManager.notify(id, builder.build());
|
||||
</pre>
|
||||
</li>
|
||||
</ol>
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h2 id="Progress">Menampilkan Kemajuan dalam Pemberitahuan</h2>
|
||||
<p>
|
||||
Pemberitahuan bisa menyertakan indikator kemajuan beranimasi yang menampilkan status
|
||||
operasi yang berjalan kepada pengguna. Jika Anda bisa memperkirakan lamanya operasi berlangsung dan berapa banyak
|
||||
yang sudah selesai pada suatu waktu, gunakan bentuk indikator yang "pasti"
|
||||
(baris kemajuan). Jika Anda tidak bisa memperkirakan lamanya operasi, gunakan
|
||||
bentuk indikator "tidak pasti" (indikator aktivitas).
|
||||
</p>
|
||||
<p>
|
||||
Indikator kemajuan ditampilkan bersama implementasi platform
|
||||
kelas {@link android.widget.ProgressBar}.
|
||||
</p>
|
||||
<p>
|
||||
Untuk menggunakan indikator kemajuan pada platform mulai dari Android 4.0, panggil
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. Untuk
|
||||
versi sebelumnya, Anda harus membuat layout pemberitahuan custom sendiri yang
|
||||
menyertakan tampilan {@link android.widget.ProgressBar}.
|
||||
</p>
|
||||
<p>
|
||||
Bagian berikut ini menjelaskan cara menampilkan kemajuan dalam pemberitahuan dengan menggunakan
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}.
|
||||
</p>
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h3 id="FixedProgress">Menampilkan indikator kemajuan berdurasi tetap</h3>
|
||||
<p>
|
||||
Untuk menampilkan baris kemajuan pasti, tambahkan baris itu ke pemberitahuan dengan memanggil
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setProgress
|
||||
setProgress(max, progress, false)}, kemudian keluarkan pemberitahuan. Selagi operasi berlangsung,
|
||||
tambah <code>progress</code>, dan perbarui pemberitahuan. Di akhir operasi,
|
||||
<code>progress</code> harus sama dengan <code>max</code>. Satu cara umum memanggil
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}
|
||||
adalah mengatur <code>max</code> ke 100, kemudian tambah <code>progress</code> sebagai
|
||||
nilai "persen selesai"untuk operasi itu.
|
||||
</p>
|
||||
<p>
|
||||
Anda bisa membiarkan baris kemajuan ditampilkan saat operasi selesai, atau menghilangkannya. Dalam
|
||||
hal apa pun, ingatlah memperbarui teks pemberitahuan untuk menampilkan bahwa operasi telah selesai.
|
||||
Untuk menghapus baris kemajuan, panggil
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setProgress
|
||||
setProgress(0, 0, false)}. Misalnya:
|
||||
</p>
|
||||
<pre>
|
||||
...
|
||||
mNotifyManager =
|
||||
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
mBuilder = new NotificationCompat.Builder(this);
|
||||
mBuilder.setContentTitle("Picture Download")
|
||||
.setContentText("Download in progress")
|
||||
.setSmallIcon(R.drawable.ic_notification);
|
||||
// Start a lengthy operation in a background thread
|
||||
new Thread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int incr;
|
||||
// Do the "lengthy" operation 20 times
|
||||
for (incr = 0; incr <= 100; incr+=5) {
|
||||
// Sets the progress indicator to a max value, the
|
||||
// current completion percentage, and "determinate"
|
||||
// state
|
||||
mBuilder.setProgress(100, incr, false);
|
||||
// Displays the progress bar for the first time.
|
||||
mNotifyManager.notify(0, mBuilder.build());
|
||||
// Sleeps the thread, simulating an operation
|
||||
// that takes time
|
||||
try {
|
||||
// Sleep for 5 seconds
|
||||
Thread.sleep(5*1000);
|
||||
} catch (InterruptedException e) {
|
||||
Log.d(TAG, "sleep failure");
|
||||
}
|
||||
}
|
||||
// When the loop is finished, updates the notification
|
||||
mBuilder.setContentText("Download complete")
|
||||
// Removes the progress bar
|
||||
.setProgress(0,0,false);
|
||||
mNotifyManager.notify(ID, mBuilder.build());
|
||||
}
|
||||
}
|
||||
// Starts the thread by calling the run() method in its Runnable
|
||||
).start();
|
||||
</pre>
|
||||
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h3 id="ActivityIndicator">Menampilkan indikator aktivitas berlanjut</h3>
|
||||
<p>
|
||||
Untuk menampilkan indikator aktivitas tidak pasti, tambahkan aktivitas ke pemberitahuan dengan
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)}
|
||||
(dua argumen pertama akan diabaikan), dan keluarkan pemberitahuan. Hasilnya adalah indikator
|
||||
yang memiliki gaya yang sama dengan baris kemajuan, hanya saja animasinya terus berjalan.
|
||||
</p>
|
||||
<p>
|
||||
Keluarkan pemberitahuan di awal operasi. Animasi akan berjalan hingga Anda
|
||||
memodifikasi pemberitahuan. Bila operasi selesai, panggil
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, false)}
|
||||
kemudian perbarui pemberitahuan untuk menghapus indikator aktivitas.
|
||||
Selalu lakukan ini; jika makan animasi akan terus berjalan sekalipun operasi telah selesai. Juga
|
||||
ingatlah mengubah teks pemberitahuan untuk menunjukkan bahwa operasi telah selesai.
|
||||
</p>
|
||||
<p>
|
||||
Untuk melihat cara kerja indikator aktivitas, lihat cuplikan terdahulu. Cari lokasi baris-baris berikut:
|
||||
</p>
|
||||
<pre>
|
||||
// Sets the progress indicator to a max value, the current completion
|
||||
// percentage, and "determinate" state
|
||||
mBuilder.setProgress(100, incr, false);
|
||||
// Issues the notification
|
||||
mNotifyManager.notify(0, mBuilder.build());
|
||||
</pre>
|
||||
<p>
|
||||
Ganti baris yang telah Anda temukan dengan baris berikut:
|
||||
</p>
|
||||
<pre>
|
||||
// Sets an activity indicator for an operation of indeterminate length
|
||||
mBuilder.setProgress(0, 0, true);
|
||||
// Issues the notification
|
||||
mNotifyManager.notify(0, mBuilder.build());
|
||||
</pre>
|
||||
|
||||
<h2 id="metadata">Metadata Pemberitahuan</h2>
|
||||
|
||||
<p>Pemberitahuan dapat disortir sesuai metadata yang Anda tetapkan dengan
|
||||
metode {@link android.support.v4.app.NotificationCompat.Builder} berikut:</p>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.support.v4.app.NotificationCompat.Builder#setCategory(java.lang.String) setCategory()}
|
||||
memberi tahu sistem cara menangani pemberitahuan aplikasi Anda bila perangkat berada dalam mode Priority
|
||||
(misalnya, jika pemberitahuan menyatakan suatu panggilan masuk, pesan instan, atau alarm).</li>
|
||||
<li>{@link android.support.v4.app.NotificationCompat.Builder#setPriority(int) setPriority()} menyebabkan
|
||||
pemberitahuan dengan bidang prioritas diatur ke {@code PRIORITY_MAX} atau {@code PRIORITY_HIGH}
|
||||
muncul dalam jendela kecil mengambang jika pemberitahuan juga memiliki suara atau getaran.</li>
|
||||
<li>{@link android.support.v4.app.NotificationCompat.Builder#addPerson(java.lang.String) addPerson()}
|
||||
memungkinkan Anda menambahkan daftar orang ke pemberitahuan. Aplikasi Anda bisa menggunakannya untuk memberi isyarat pada
|
||||
sistem bahwa sistem harus mengelompokkan bersama pemberitahuan dari orang-orang yang ditetapkan, atau memberi peringkat lebih penting pada pemberitahuan
|
||||
untuk orang-orang ini.</li>
|
||||
</ul>
|
||||
|
||||
<div class="figure" style="width:230px">
|
||||
<img src="{@docRoot}images/ui/notifications/heads-up.png" alt="" width="" height="" id="figure3" />
|
||||
<p class="img-caption">
|
||||
<strong>Gambar 3.</strong> Aktivitas layar penuh yang menampilkan pemberitahuan pendahuluan
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2 id="Heads-up">Pemberitahuan Pendahuluan</h2>
|
||||
|
||||
<p>Dengan Android 5.0 (API level 21), pemberitahuan bisa muncul dalam jendela kecil mengambang
|
||||
(yang disebut juga dengan <em>pemberitahuan pendahuluan</em>) saat perangkat aktif
|
||||
(yakni, perangkat dibuka kuncinya dan layarnya menyala). Pemberitahuan ini
|
||||
muncul seperti bentuk ringkas pemberitahuan Anda, hanya saja
|
||||
pemberitahuan pendahuluan juga menampilkan tombol tindakan. Pengguna bisa menindaklanjuti atau mengabaikan,
|
||||
pemberitahuan pendahuluan tanpa meninggalkan aplikasi saat ini.</p>
|
||||
|
||||
<p>Contoh-contoh kondisi yang dapat memicu pemberitahuan pendahuluan antara lain:</p>
|
||||
|
||||
<ul>
|
||||
<li>Aktivitas pengguna berada dalam mode layar penuh (aplikasi menggunakan
|
||||
{@link android.app.Notification#fullScreenIntent}), atau</li>
|
||||
<li>Pemberitahuan memiliki prioritas tinggi dan menggunakan nada dering atau
|
||||
getaran</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="lockscreenNotification">Pemberitahuan Layar Kunci</h2>
|
||||
|
||||
<p>Dengan rilis Android 5.0 (API level 21), pemberitahuan kini dapat muncul pada
|
||||
layar kunci. Aplikasi Anda bisa menggunakan fungsionalitas ini untuk menyediakan kontrol pemutaran media dan
|
||||
tindakan umum lainnya. Pengguna bisa memilih lewat Settings apakah akan menampilkan pemberitahuan pada layar kunci, dan
|
||||
Anda bisa mendesain apakah pemberitahuan aplikasi akan terlihat pada layar kunci.</p>
|
||||
|
||||
<h3 id="visibility">Mengatur Visibilitas</h3>
|
||||
|
||||
<p>Aplikasi Anda bisa mengatur level detail terlihat pada pemberitahuan yang ditampilkan di
|
||||
layar kunci aman. Anda memanggil {@link android.support.v4.app.NotificationCompat.Builder#setVisibility(int) setVisibility()}
|
||||
dan menetapkan salah satu nilai berikut:</p>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC} menampilkan isi lengkap
|
||||
pemberitahuan.</li>
|
||||
<li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_SECRET} tidak menampilkan bagian apa pun dari
|
||||
pemberitahuan ini pada layar kunci.</li>
|
||||
<li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE} menampilkan informasi dasar,
|
||||
misalnya ikon dan judul isi pemberitahuan, namun menyembunyikan isi lengkap pemberitahuan.</li>
|
||||
</ul>
|
||||
|
||||
<p>Bila {@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE} telah diatur, Anda juga bisa
|
||||
menyediakan versi alternatif isi pemberitahuan yang menyembunyikan detail tertentu. Misalnya,
|
||||
aplikasi SMS dapat menampilkan pemberitahuan yang menampilkan <em>Anda memiliki 3 pesan teks baru</em>, namun menyembunyikan
|
||||
isi dan pengirim pesan. Untuk menyediakan pemberitahuan alternatif ini, buat dahulu pemberitahuan
|
||||
pengganti menggunakan {@link android.support.v4.app.NotificationCompat.Builder}. Bila Anda membuat
|
||||
objek pemberitahuan privat, lampirkan pemberitahuan pengganti melalui metode
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setPublicVersion(android.app.Notification) setPublicVersion()}
|
||||
.</p>
|
||||
|
||||
<h3 id="controllingMedia">Mengontrol Pemutaran Media pada Layar Kunci</h3>
|
||||
|
||||
<p>Dalam Android 5.0 (API level 21) layar kunci tidak lagi menampilkan kontrol media
|
||||
berdasarkan {@link android.media.RemoteControlClient}, yang sekarang telah dihilangkan. Sebagai gantinya, gunakan
|
||||
template {@link android.app.Notification.MediaStyle} dengan metode
|
||||
{@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()}
|
||||
, yang mengubah tindakan menjadi ikon yang bisa diklik.</p>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> Template dan metode {@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()}
|
||||
tidak disertakan dalam pustaka dukungan, sehingga fitur-fitur ini berjalan pada Android 5.0 dan yang lebih tinggi
|
||||
saja.</p>
|
||||
|
||||
<p>Untuk menampilkan kontrol pemutaran media di layar kunci dalam Android 5.0, atur visibilitas
|
||||
ke {@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC}, seperti dijelaskan di atas. Kemudian tambahkan
|
||||
tindakan dan atur template {@link android.app.Notification.MediaStyle}, seperti dijelaskan dalam contoh kode
|
||||
berikut:</p>
|
||||
|
||||
<pre>
|
||||
Notification notification = new Notification.Builder(context)
|
||||
// Show controls on lock screen even when user hides sensitive content.
|
||||
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
||||
.setSmallIcon(R.drawable.ic_stat_player)
|
||||
// Add media control buttons that invoke intents in your media service
|
||||
.addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) // #0
|
||||
.addAction(R.drawable.ic_pause, "Pause", pausePendingIntent) // #1
|
||||
.addAction(R.drawable.ic_next, "Next", nextPendingIntent) // #2
|
||||
// Apply the media style template
|
||||
.setStyle(new Notification.MediaStyle()
|
||||
.setShowActionsInCompactView(1 /* #1: pause button */)
|
||||
.setMediaSession(mMediaSession.getSessionToken())
|
||||
.setContentTitle("Wonderful music")
|
||||
.setContentText("My Awesome Band")
|
||||
.setLargeIcon(albumArtBitmap)
|
||||
.build();
|
||||
</pre>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> Dihilangkannya {@link android.media.RemoteControlClient}
|
||||
memiliki implikasi lebih jauh untuk mengontrol media. Lihat
|
||||
<a href="{@docRoot}about/versions/android-5.0.html#MediaPlaybackControl">Kontrol Pemutaran Media</a>
|
||||
untuk informasi selengkapnya tentang API baru untuk mengelola sesi media dan mengontrol pemutaran.</p>
|
||||
|
||||
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h2 id="CustomNotification">Layout Pemberitahuan Custom</h2>
|
||||
<p>
|
||||
Kerangka kerja pemberitahuan memungkinkan Anda mendefinisikan layout pemberitahuan custom, yang
|
||||
mendefinisikan penampilan pemberitahuan dalam objek {@link android.widget.RemoteViews}.
|
||||
Pemberitahuan dengan layout custom serupa pemberitahuan normal, namun dibuat berdasarkan
|
||||
{@link android.widget.RemoteViews} yang didefinisikan dalam file layout XML.
|
||||
</p>
|
||||
<p>
|
||||
Tinggi yang tersedia untuk layout pemberitahuan custom bergantung pada tampilan pemberitahuan. Layout
|
||||
tampilan normal dibatasi hingga 64 dp, dan layout tampilan yang diperluas dibatasi hingga 256 dp.
|
||||
</p>
|
||||
<p>
|
||||
Untuk mendefinisikan layout pemberitahuan custom, mulailah dengan membuat instance
|
||||
objek {@link android.widget.RemoteViews} yang memekarkan file layout XML. Kemudian,
|
||||
sebagai ganti memanggil metode seperti
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()},
|
||||
panggil {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Untuk mengatur
|
||||
detail isi pemberitahuan custom, gunakan metode dalam
|
||||
{@link android.widget.RemoteViews} untuk mengatur nilai anak tampilan:
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
Buat layout XML untuk pemberitahuan di file terpisah. Anda bisa menggunakan nama file
|
||||
apa saja yang diinginkan, namun Anda harus menggunakan ekstensi <code>.xml</code>
|
||||
</li>
|
||||
<li>
|
||||
Dalam aplikasi Anda, gunakan metode {@link android.widget.RemoteViews} untuk mendefinisikan
|
||||
ikon dan teks pemberitahuan. Masukkan objek {@link android.widget.RemoteViews} ini ke dalam
|
||||
{@link android.support.v4.app.NotificationCompat.Builder} Anda dengan memanggil
|
||||
{@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Hindari
|
||||
mengatur {@link android.graphics.drawable.Drawable} latar belakang pada
|
||||
objek {@link android.widget.RemoteViews} Anda, karena warna teks bisa menjadi tidak terbaca.
|
||||
</li>
|
||||
</ol>
|
||||
<p>
|
||||
Kelas {@link android.widget.RemoteViews} juga menyertakan metode yang bisa Anda gunakan untuk
|
||||
menambahkan {@link android.widget.Chronometer} atau {@link android.widget.ProgressBar}
|
||||
dengan mudah ke layout pemberitahuan Anda. Untuk informasi selengkapnya tentang cara membuat layout custom
|
||||
pemberitahuan Anda, lihat dokumentasi acuan {@link android.widget.RemoteViews}.
|
||||
</p>
|
||||
<p class="caution">
|
||||
<strong>Perhatian:</strong> Bila Anda menggunakan layout pemberitahuan custom, berhati-hatilah
|
||||
untuk memastikan bahwa layout custom itu bekerja pada berbagai orientasi dan resolusi perangkat. Walaupun
|
||||
berlaku bagi semua layout View, nasihat ini khususnya penting untuk pemberitahuan karena
|
||||
ruang di laci pemberitahuan sangat terbatas. Jangan buat layout custom terlalu
|
||||
kompleks, dan pastikan mengujinya di berbagai konfigurasi.
|
||||
</p>
|
||||
<!-- ------------------------------------------------------------------------------------------ -->
|
||||
<h4>Menggunakan sumber daya gaya untuk teks pemberitahuan custom</h4>
|
||||
<p>
|
||||
Selalu gunakan sumber daya gaya untuk teks pemberitahuan custom. Warna latar belakang
|
||||
pemberitahuan bisa bervariasi di berbagai perangkat dan versi, dan menggunakan sumber daya gaya
|
||||
membantu Anda menangani hal ini. Mulai Android 2.3, sistem mendefinisikan sebuah gaya untuk
|
||||
teks layout pemberitahuan standar. Jika Anda menggunakan gaya yang sama dalam aplikasi yang menargetkan Android
|
||||
2.3 atau yang lebih tinggi, Anda akan memastikan bahwa teks terlihat pada latar belakang tampilan.
|
||||
</p>
|
||||
71
docs/html-intl/intl/id/guide/topics/ui/overview.jd
Normal file
71
docs/html-intl/intl/id/guide/topics/ui/overview.jd
Normal file
@@ -0,0 +1,71 @@
|
||||
page.title=Ikhtisar UI
|
||||
@jd:body
|
||||
|
||||
|
||||
<p>Semua elemen antarmuka pengguna dalam aplikasi Android dibangun menggunakan objek {@link android.view.View} dan
|
||||
{@link android.view.ViewGroup}. {@link android.view.View} adalah objek yang menarik
|
||||
sesuatu di layar dan dapat berinteraksi dengan pengguna. {@link android.view.ViewGroup} merupakan sebuah
|
||||
objek yang menyimpan objek {@link android.view.View} lainnya (dan {@link android.view.ViewGroup}) untuk
|
||||
mendefinisikan layout antarmuka.</p>
|
||||
|
||||
<p>Android menyediakan sekumpulan subkelas {@link android.view.View} dan {@link
|
||||
android.view.ViewGroup} yang menawarkan kontrol input umum (seperti tombol dan bidang
|
||||
teks) serta berbagai model layout (seperti layout linear atau relatif).</p>
|
||||
|
||||
|
||||
<h2 id="Layout">Layout Antarmuka Pengguna</h2>
|
||||
|
||||
<p>Antarmuka pengguna untuk setiap komponen aplikasi Anda didefinisikan menggunakan hierarki objek {link
|
||||
android.view.View} dan {@link android.view.ViewGroup}, seperti yang ditampilkan dalam gambar 1. Setiap kelompok tampilan
|
||||
merupakan kontainer tak terlihat yang mengelola tampilan anak, sementara tampilan anak ini dapat menjadi kontrol
|
||||
input atau widget lain yang
|
||||
menarik sebagian dari UI. Pohon hierarki ini bisa sederhana atau bisa juga kompleks bergantung kebutuhan
|
||||
(namun yang sederhana paling baik untuk kinerja).</p>
|
||||
|
||||
<img src="{@docRoot}images/viewgroup.png" alt="" />
|
||||
<p class="img-caption"><strong>Gambar 1.</strong> Ilustrasi dari hierarki tampilan, yang mendefinisikan layout
|
||||
UI.</p>
|
||||
|
||||
<p>Untuk mendeklarasikan layout, Anda dapat menyediakan objek {@link android.view.View} dalam kode dan mulai
|
||||
membangun pohon, namun cara termudah dan terefektif untuk mendefinisikan layout adalah dengan file XML.
|
||||
XML menawarkan struktur layout yang dapat dibaca manusia, serupa dengan HTML.</p>
|
||||
|
||||
<p>Nama elemen XML untuk tampilan sesuai dengan kelas Android yang diwakilinya. Dengan demikian elemen
|
||||
<code><TextView></code> membuat widget {@link android.widget.TextView} dalam UI Anda,
|
||||
dan elemen <code><LinearLayout></code> membuat kelompok tampilan {@link android.widget.LinearLayout}
|
||||
. </p>
|
||||
|
||||
<p>Misalnya, layout vertikal sederhana dengan tampilan teks dan tombol akan tampak seperti ini:</p>
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical" >
|
||||
<TextView android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="I am a TextView" />
|
||||
<Button android:id="@+id/button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="I am a Button" />
|
||||
</LinearLayout>
|
||||
</pre>
|
||||
|
||||
<p>Saat Anda memuat sumber daya layout di aplikasi, Android akan menginisialisasi setiap simpul layout menjadi
|
||||
objek runtime yang bisa Anda gunakan untuk mendefinisikan perilaku tambahan, query status objek, atau memodifikasi
|
||||
layout.</p>
|
||||
|
||||
<p>Untuk mendapatkan panduan lengkap mengenai pembuatan layout UI, lihat <a href="declaring-layout.html">Layout
|
||||
XML</a>.
|
||||
|
||||
|
||||
<h2 id="UIComponents">Komponen Antarmuka Pengguna</h2>
|
||||
|
||||
<p>Anda tidak harus membuat semua UI menggunakan objek {@link android.view.View} dan {link
|
||||
android.view.ViewGroup}. Android menyediakan beberapa komponen aplikasi yang menawarkan
|
||||
layout UI standar yang tinggal Anda definisikan kontennya. Komponen UI ini masing-masing
|
||||
memiliki set API unik yang dijelaskan dalam masing-masing dokumennya, seperti <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>, <a href="{@docRoot}guide/topics/ui/dialogs.html">Dialog</a>, dan <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan Status</a>.</p>
|
||||
|
||||
|
||||
1202
docs/html-intl/intl/id/guide/topics/ui/settings.jd
Normal file
1202
docs/html-intl/intl/id/guide/topics/ui/settings.jd
Normal file
File diff suppressed because it is too large
Load Diff
291
docs/html-intl/intl/id/guide/topics/ui/ui-events.jd
Normal file
291
docs/html-intl/intl/id/guide/topics/ui/ui-events.jd
Normal file
@@ -0,0 +1,291 @@
|
||||
page.title=Kejadian Input
|
||||
parent.title=Antarmuka Pengguna
|
||||
parent.link=index.html
|
||||
@jd:body
|
||||
|
||||
<div id="qv-wrapper">
|
||||
<div id="qv">
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#EventListeners">Event Listener</a></li>
|
||||
<li><a href="#EventHandlers">Event Handler</a></li>
|
||||
<li><a href="#TouchMode">Mode Sentuh</a></li>
|
||||
<li><a href="#HandlingFocus">Menangani Fokus</a></li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Di Android, ada lebih dari satu cara untuk mencegat kejadian dari interaksi pengguna dengan aplikasi Anda.
|
||||
Saat mempertimbangkan kejadian dalam antarmuka pengguna Anda, pendekatannya adalah menangkap kejadian
|
||||
dari objek View tertentu yang digunakan pengguna untuk berinteraksi. Kelas View menyediakan sarana untuk melakukannya.</p>
|
||||
|
||||
<p>Dalam berbagai kelas View yang akan digunakan untuk menyusun layout, Anda mungkin melihat beberapa metode callback
|
||||
publik yang tampak berguna untuk kejadian UI. Metode ini dipanggil oleh kerangka kerja Android ketika masing-masing
|
||||
tindakan terjadi pada objek itu. Misalnya, bila View (seperti Button/Tombol) disentuh,
|
||||
metode <code>onTouchEvent()</code> akan dipanggil pada objek itu. Akan tetapi, untuk mencegatnya, Anda harus memperluas
|
||||
kelas dan mengesampingkan metode itu. Akan tetapi, memperluas setiap objek View
|
||||
untuk menangani kejadian seperti itu tidaklah praktis. Karena itulah kelas View juga berisi
|
||||
sekumpulan antarmuka tersarang dengan callback yang jauh lebih mudah didefinisikan. Antarmuka ini,
|
||||
yang disebut <a href="#EventListeners">event listener</a>, merupakan tiket Anda untuk menangkap interaksi pengguna dengan UI.</p>
|
||||
|
||||
<p>Walaupun Anda akan lebih sering menggunakan event listener ini untuk interaksi pengguna,
|
||||
mungkin ada saatnya Anda ingin memperluas kelas View, untuk membuat komponen custom.
|
||||
Mungkin Anda ingin memperluas kelas {@link android.widget.Button}
|
||||
untuk membuat sesuatu yang lebih menarik. Dalam hal ini, Anda akan dapat mendefinisikan perilaku kejadian default untuk kelas Anda dengan menggunakan
|
||||
kelas <a href="#EventHandlers">event handler</a>.</p>
|
||||
|
||||
|
||||
<h2 id="EventListeners">Event Listener</h2>
|
||||
|
||||
<p>Event listener merupakan antarmuka di kelas {@link android.view.View} yang berisi metode
|
||||
callback tunggal. Metode ini akan dipanggil oleh kerangka kerja Android bila View yang
|
||||
telah didaftarkan dengan listener dipicu oleh interaksi pengguna dengan item dalam UI.</p>
|
||||
|
||||
<p>Yang juga disertakan dalam antarmuka event listener adalah metode callback berikut ini:</p>
|
||||
|
||||
<dl>
|
||||
<dt><code>onClick()</code></dt>
|
||||
<dd>Dari {@link android.view.View.OnClickListener}.
|
||||
Ini dipanggil baik saat pengguna menyentuh item
|
||||
(bila dalam mode sentuh), maupun memfokuskan pada item dengan tombol navigasi atau trackball dan
|
||||
menekan tombol "enter" yang sesuai atau menekan trackball.</dd>
|
||||
<dt><code>onLongClick()</code></dt>
|
||||
<dd>Dari {@link android.view.View.OnLongClickListener}.
|
||||
Ini dipanggil baik saat pengguna menyentuh dan menahan item (bila dalam mode sentuh),
|
||||
maupun memfokuskan pada item dengan tombol navigasi atau trackball dan
|
||||
menekan serta menahan tombol "enter" yang sesuai atau menekan dan menahan trackball (selama satu detik).</dd>
|
||||
<dt><code>onFocusChange()</code></dt>
|
||||
<dd>Dari {@link android.view.View.OnFocusChangeListener}.
|
||||
Ini dipanggil saat pengguna menyusuri ke atau dari item, dengan menggunakan tombol navigasi atau trackball.</dd>
|
||||
<dt><code>onKey()</code></dt>
|
||||
<dd>Dari {@link android.view.View.OnKeyListener}.
|
||||
Ini dipanggil saat pengguna memfokuskan pada item dan menekan atau melepas tombol fisik pada perangkat.</dd>
|
||||
<dt><code>onTouch()</code></dt>
|
||||
<dd>Dari {@link android.view.View.OnTouchListener}.
|
||||
Ini dipanggil saat pengguna melakukan tindakan yang digolongkan sebagai kejadian sentuh, termasuk penekanan, pelepasan,
|
||||
atau gerak perpindahan pada layar (dalam batasan item itu).</dd>
|
||||
<dt><code>onCreateContextMenu()</code></dt>
|
||||
<dd>Dari {@link android.view.View.OnCreateContextMenuListener}.
|
||||
Ini dipanggil saat Menu Konteks sedang dibuat (akibat "klik lama" terus-menerus). Lihat diskusi
|
||||
tentang menu konteks di panduan pengembang <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">Menu</a>.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<p>Metode ini satu-satunya yang menempati antarmukanya masing-masing. Untuk mendefinisikan salah satu metode ini
|
||||
dan menangani kejadian Anda, implementasikan antarmuka tersarang dalam Aktivitas Anda atau definisikan sebagai kelas anonim.
|
||||
Kemudian, teruskan satu
|
||||
instance implementasi Anda pada masing-masing metode <code>View.set...Listener()</code>. (Misalnya, panggil
|
||||
<code>{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}</code>
|
||||
dan teruskan implementasi {@link android.view.View.OnClickListener OnClickListener} Anda.)</p>
|
||||
|
||||
<p>Contoh di bawah menunjukkan cara mendaftarkan on-click listener untuk Button. </p>
|
||||
|
||||
<pre>
|
||||
// Create an anonymous implementation of OnClickListener
|
||||
private OnClickListener mCorkyListener = new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
// do something when the button is clicked
|
||||
}
|
||||
};
|
||||
|
||||
protected void onCreate(Bundle savedValues) {
|
||||
...
|
||||
// Capture our button from layout
|
||||
Button button = (Button)findViewById(R.id.corky);
|
||||
// Register the onClick listener with the implementation above
|
||||
button.setOnClickListener(mCorkyListener);
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Anda juga akan merasa lebih praktis mengimplementasikan OnClickListener sebagai bagian dari Aktivitas.
|
||||
Ini akan menghindari beban kelas ekstra dan alokasi objek. Misalnya:</p>
|
||||
<pre>
|
||||
public class ExampleActivity extends Activity implements OnClickListener {
|
||||
protected void onCreate(Bundle savedValues) {
|
||||
...
|
||||
Button button = (Button)findViewById(R.id.corky);
|
||||
button.setOnClickListener(this);
|
||||
}
|
||||
|
||||
// Implement the OnClickListener callback
|
||||
public void onClick(View v) {
|
||||
// do something when the button is clicked
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Perhatikan bahwa callback <code>onClick()</code> dalam contoh di atas tidak memiliki
|
||||
nilai hasil, namun beberapa metode event listener lainnya harus mengembalikan boolean. Sebabnya
|
||||
bergantung pada kejadian. Untuk sebagian yang mengembalikan boolean, ini sebabnya:</p>
|
||||
<ul>
|
||||
<li><code>{@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()}</code> -
|
||||
Ini mengembalikan boolean untuk menunjukkan apakah Anda telah menggunakan kejadian dan tidak boleh dibawa lebih jauh.
|
||||
Yaitu, mengembalikan <em>benar</em> untuk menunjukkan apakah Anda telah menangani kejadian dan semestinya berhenti di sini;
|
||||
mengembalikan <em>salah</em> jika Anda tidak menanganinya dan/atau kejadian semestinya berlanjut ke
|
||||
on-click listener lainnya.</li>
|
||||
<li><code>{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()}</code> -
|
||||
Ini mengembalikan boolean untuk menunjukkan apakah Anda telah menggunakan kejadian dan tidak boleh dibawa lebih jauh.
|
||||
Yaitu, mengembalikan <em>benar</em> untuk menunjukkan apakah Anda telah menangani kejadian dan semestinya berhenti di sini;
|
||||
mengembalikan <em>salah</em> jika Anda tidak menanganinya dan/atau kejadian semestinya berlanjut ke
|
||||
on-key listener lainnya.</li>
|
||||
<li><code>{@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()}</code> -
|
||||
Ini mengembalikan boolean untuk menunjukkan apakah listener Anda telah menggunakan kejadian ini. Yang penting adalah
|
||||
kejadian ini bisa memiliki beberapa tindakan yang saling mengikuti. Jadi, jika Anda mengembalikan <em>salah</em>saat
|
||||
kejadian tindakan turun diterima, itu menunjukkan bahwa Anda belum menggunakan kejadian itu dan juga
|
||||
tidak tertarik dengan tindakan berikutnya dari kejadian ini. Karena itu, Anda tidak akan diminta untuk melakukan tindakan
|
||||
lainnya dalam kejadian, seperti gerakan jari, atau kejadian tindakan naik yang akan terjadi.</li>
|
||||
</ul>
|
||||
|
||||
<p>Ingatlah bahwa kejadian tombol fisik selalu disampaikan ke View yang sedang difokus. Kejadian ini dikirim mulai dari atas
|
||||
hierarki View, kemudian turun hingga tujuan yang sesuai. Jika View Anda (atau anak View Anda)
|
||||
saat ini sedang fokus, maka Anda dapat melihat kejadian berpindah melalui metode.<code>{@link android.view.View#dispatchKeyEvent(KeyEvent)
|
||||
dispatchKeyEvent()}</code> Sebagai pengganti untuk menangkap kejadian penting melalui View, Anda juga dapat menerima
|
||||
semua kejadian dalam Aktivitas Anda dengan <code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>
|
||||
dan <code>{@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}</code>.</p>
|
||||
|
||||
<p>Selain itu, saat memikirkan tentang input teks aplikasi Anda, ingatlah bahwa banyak perangkat yang hanya memiliki
|
||||
metode input perangkat lunak. Metode seperti itu tidak harus berbasis tombol; sebagian mungkin menggunakan input suara, tulisan tangan, dan seterusnya. Meskipun
|
||||
metode input menyajikan antarmuka seperti keyboard, itu umumnya <strong>tidak</strong> memicu keluarga kejadian
|
||||
<code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>. Anda sama sekali tidak boleh
|
||||
membangun UI yang mengharuskan penekanan tombol tertentu dikontrol kecuali jika Anda ingin membatasi aplikasi Anda pada perangkat yang memiliki
|
||||
keyboard fisik. Khususnya, jangan mengandalkan metode ini untuk memvalidasi input saat pengguna menekan tombol
|
||||
enter; melainkan, gunakan tindakan seperti {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE} untuk menandai
|
||||
metode input mengenai reaksi yang diharapkan aplikasi Anda, sehingga bisa mengubah UI-nya secara signifikan. Hindari anggapan
|
||||
tentang bagaimana metode input perangkat lunak seharusnya bekerja dan percayalah bahwa metode akan menyediakan teks yang sudah diformat bagi aplikasi Anda.</p>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> Android akan memanggil event handler terlebih dahulu kemudian handler
|
||||
default yang sesuai dari definisi kelas. Karena itu, mengembalikan <em>benar</em> dari event listener ini akan menghentikan
|
||||
penyebaran kejadian ke event listener lain dan juga akan memblokir callback ke
|
||||
event handler default di View. Pastikan bahwa Anda ingin mengakhiri kejadian saat mengembalikan <em>true</em>.</p>
|
||||
|
||||
|
||||
<h2 id="EventHandlers">Event Handler</h2>
|
||||
|
||||
<p>Jika Anda membuat komponen custom dari View, maka Anda dapat mendefinisikan penggunaan beberapa
|
||||
metode callback sebagai event handler default.
|
||||
Dalam dokumen tentang <a href="{@docRoot}guide/topics/ui/custom-components.html">Komponen
|
||||
Custom</a>, Anda akan melihat penggunaan beberapa callback umum untuk penanganan kejadian,
|
||||
termasuk:</p>
|
||||
<ul>
|
||||
<li><code>{@link android.view.View#onKeyDown}</code> - Dipanggil bila terjadi kejadian tombol baru.</li>
|
||||
<li><code>{@link android.view.View#onKeyUp}</code> - Dipanggil bila terjadi kejadian tombol naik.</li>
|
||||
<li><code>{@link android.view.View#onTrackballEvent}</code> - Dipanggil bila terjadi kejadian gerakan trackball.</li>
|
||||
<li><code>{@link android.view.View#onTouchEvent}</code> - Dipanggil bila terjadi kejadian gerakan layar sentuh.</li>
|
||||
<li><code>{@link android.view.View#onFocusChanged}</code> - Dipanggil bila View memperoleh atau kehilangan fokus.</li>
|
||||
</ul>
|
||||
<p>Ada beberapa metode lain yang harus Anda ketahui, yang bukan bagian dari kelas View,
|
||||
namun bisa berdampak langsung pada kemampuan Anda menangani kejadian. Jadi, saat mengelola kejadian yang lebih kompleks dalam
|
||||
layout, pertimbangkanlah metode-metode lain ini:</p>
|
||||
<ul>
|
||||
<li><code>{@link android.app.Activity#dispatchTouchEvent(MotionEvent)
|
||||
Activity.dispatchTouchEvent(MotionEvent)}</code> - Ini memungkinkan {@link
|
||||
android.app.Activity} Anda mencegat semua kejadian sentuh sebelum dikirim ke jendela.</li>
|
||||
<li><code>{@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)
|
||||
ViewGroup.onInterceptTouchEvent(MotionEvent)}</code> - Ini memungkinkan {@link
|
||||
android.view.ViewGroup} memantau kejadian saat dikirim ke View anak.</li>
|
||||
<li><code>{@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean)
|
||||
ViewParent.requestDisallowInterceptTouchEvent(boolean)}</code> - Panggil ini
|
||||
pada View induk untuk menunjukan larangan mencegat kejadian sentuh dengan <code>{@link
|
||||
android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}</code>.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="TouchMode">Mode Sentuh</h2>
|
||||
<p>
|
||||
Saat pengguna menyusuri antarmuka pengguna dengan tombol pengarah atau trackball, Anda
|
||||
perlu memberikan fokus pada item tindakan (seperti tombol) agar pengguna bisa mengetahui apa
|
||||
yang akan menerima input. Akan tetapi jika perangkat memiliki kemampuan sentuh, dan pengguna
|
||||
mulai berinteraksi dengan antarmuka dengan menyentuhnya, maka Anda tidak perlu lagi
|
||||
menyorot item, atau memfokuskan pada View tertentu. Karena itu, ada mode
|
||||
untuk interaksi yang bernama "mode sentuh".
|
||||
</p>
|
||||
<p>
|
||||
Untuk perangkat berkemampuan sentuh, setelah pengguna menyentuh layar, perangkat
|
||||
akan masuk ke mode sentuh. Dari sini dan selanjutnya, hanya View dengan
|
||||
{@link android.view.View#isFocusableInTouchMode} benar yang akan dapat difokus, seperti widget pengedit teks.
|
||||
View lain yang dapat disentuh, seperti tombol, tidak akan difokus bila disentuh; View ini akan
|
||||
langsung memicu on-click listener bila ditekan.
|
||||
</p>
|
||||
<p>
|
||||
Kapan saja pengguna menekan tombol pengarah atau menggulir dengan trackball, perangkat akan
|
||||
keluar dari mode sentuh, dan mencari tampilan untuk difokuskan. Kini pengguna bisa melanjutkan interaksi
|
||||
dengan antarmuka pengguna tanpa menyentuh layar.
|
||||
</p>
|
||||
<p>
|
||||
Status mode sentuh dipertahankan di seluruh sistem (semua jendela dan aktivitas).
|
||||
Untuk query status saat ini, Anda bisa memanggil
|
||||
{@link android.view.View#isInTouchMode} untuk mengetahui apakah perangkat saat ini sedang dalam mode sentuh.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="HandlingFocus">Menangani Fokus</h2>
|
||||
|
||||
<p>Kerangka kerja ini akan menangani gerakan fokus rutin sebagai respons input pengguna.
|
||||
Ini termasuk mengubah fokus saat View dihapus atau disembunyikan, atau saat tersedia View
|
||||
baru. View menunjukkan kesediaannya untuk mengambil fokus
|
||||
melalui metode <code>{@link android.view.View#isFocusable()}</code>. Untuk mengubah apakah View bisa mengambil
|
||||
fokus, panggil <code>{@link android.view.View#setFocusable(boolean) setFocusable()}</code>. Saat dalam mode sentuh,
|
||||
Anda dapat me-query apakah View memungkinkan fokus dengan <code>{@link android.view.View#isFocusableInTouchMode()}</code>.
|
||||
Anda bisa mengubahnya dengan <code>{@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode()}</code>.
|
||||
</p>
|
||||
|
||||
<p>Gerakan fokus berdasarkan pada algoritma yang mencari tetangga terdekat dalam
|
||||
arah yang diberikan. Dalam kasus yang jarang terjadi, algoritma default mungkin
|
||||
tidak cocok dengan perilaku yang diinginkan pengembang. Dalam situasi ini, Anda bisa memberikan
|
||||
pengesampingan eksplisit dengan mengikuti atribut XML berikut dalam file layout:
|
||||
<var>nextFocusDown</var>, <var>nextFocusLeft</var>, <var>nextFocusRight</var>, dan
|
||||
<var>nextFocusUp</var>. Tambahkan salah satu atribut ini ke View <em>dari</em> mana fokus
|
||||
meninggalkan. Definisikan nilai atribut untuk menjadi ID View
|
||||
<em>ke</em> mana fokus harus diberikan. Misalnya:</p>
|
||||
<pre>
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
... >
|
||||
<Button android:id="@+id/top"
|
||||
android:nextFocusUp="@+id/bottom"
|
||||
... />
|
||||
<Button android:id="@+id/bottom"
|
||||
android:nextFocusDown="@+id/top"
|
||||
... />
|
||||
</LinearLayout>
|
||||
</pre>
|
||||
|
||||
<p>Biasanya, dalam layout vertikal ini, navigasi ke atas dari Button pertama tidak akan membawa ke
|
||||
mana pun, tidak pula akan menyusuri ke bawah dari Button kedua. Karena sekarang Button atas telah
|
||||
mendefinisikan Button bawah sebagai <var>nextFocusUp</var> (dan sebaliknya), fokus navigasi akan
|
||||
silih berganti dari atas ke bawah dan bawah ke atas.</p>
|
||||
|
||||
<p>Jika Anda ingin mendeklarasikan View sebagai dapat difokus dalam UI (bila biasanya tidak dapat difokus),
|
||||
tambahkan atribut XML <code>android:focusable</code> ke View, dalam deklarasi layout Anda.
|
||||
Atur nilai <var>true</var>. Anda juga bisa mendeklarasikan View
|
||||
sebagai dapat difokus saat dalam Mode Sentuh dengan <code>android:focusableInTouchMode</code>.</p>
|
||||
<p>Untuk meminta View tertentu difokus, panggil <code>{@link android.view.View#requestFocus()}</code>.</p>
|
||||
<p>Untuk mendengarkan kejadian fokus (diberi tahu bila View menerima atau kehilangan fokus), gunakan
|
||||
<code>{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}</code>
|
||||
, seperti yang dibahas di bagian <a href="#EventListeners">Event Listener</a>, di atas.</p>
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
<h2 is="EventCycle">Event Cycle</h2>
|
||||
<p>The basic cycle of a View is as follows:</p>
|
||||
<ol>
|
||||
<li>An event comes in and is dispatched to the appropriate View. The View
|
||||
handles the event and notifies any listeners.</li>
|
||||
<li>If, in the course of processing the event, the View's bounds may need
|
||||
to be changed, the View will call {@link android.view.View#requestLayout()}.</li>
|
||||
<li>Similarly, if in the course of processing the event the View's appearance
|
||||
may need to be changed, the View will call {@link android.view.View#invalidate()}.</li>
|
||||
<li>If either {@link android.view.View#requestLayout()} or {@link android.view.View#invalidate()} were called,
|
||||
the framework will take care of measuring, laying out, and drawing the tree
|
||||
as appropriate.</li>
|
||||
</ol>
|
||||
|
||||
<p class="note"><strong>Note:</strong> The entire View tree is single threaded. You must always be on
|
||||
the UI thread when calling any method on any View.
|
||||
If you are doing work on other threads and want to update the state of a View
|
||||
from that thread, you should use a {@link android.os.Handler}.
|
||||
</p>
|
||||
-->
|
||||
181
docs/html-intl/intl/id/training/articles/direct-boot.jd
Normal file
181
docs/html-intl/intl/id/training/articles/direct-boot.jd
Normal file
@@ -0,0 +1,181 @@
|
||||
page.title=Direct Boot
|
||||
page.keywords=pratinjau,sdk,direct boot
|
||||
page.tags=androidn
|
||||
page.image=images/cards/card-nyc_2x.jpg
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#run">Meminta Akses untuk Berjalan Selama Direct Boot</a></li>
|
||||
<li><a href="#access">Mengakses Penyimpanan yang Dienkripsi dengan Perangkat</a></li>
|
||||
<li><a href="#notification">Mendapatkan Pemberitahuan saat Pengguna Membuka Kunci</a></li>
|
||||
<li><a href="#migrating">Migrasi Data yang Ada</a></li>
|
||||
<li><a href="#testing">Menguji Aplikasi Peka Enkripsi Anda</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Android N berjalan dalam mode <i>Direct Boot</i> yang aman
|
||||
bila perangkat telah dihidupkan namun pengguna tidak membuka
|
||||
kunci perangkat. Untuk mendukung hal ini, sistem menyediakan dua lokasi penyimpanan untuk data:</p>
|
||||
|
||||
<ul>
|
||||
<li><i>Penyimpanan yang dienkripsi dengan kredensial</i>, yang merupakan lokasi penyimpanan default
|
||||
dan hanya tersedia setelah pengguna membuka kunci perangkat.</li>
|
||||
<li><i>Penyimpanan yang dienkripsi dengan perangkat</i>, yang merupakan lokasi penyimpanan yang tersedia
|
||||
selama mode Direct Boot dan setelah pengguna membuka kunci perangkat.</li>
|
||||
</ul>
|
||||
|
||||
<p>Secara default, aplikasi tidak berjalan selama mode Direct Boot.
|
||||
Jika aplikasi Anda perlu melakukan tindakan selama mode Direct Boot, Anda bisa mendaftarkan
|
||||
komponen aplikasi yang harus dijalankan selama mode ini. Beberapa kasus penggunaan umum
|
||||
untuk aplikasi yang perlu dijalankan selama mode Direct Boot antara lain:</p>
|
||||
|
||||
<ul>
|
||||
<li>Aplikasi yang telah menjadwalkan pemberitahuan, seperti aplikasi
|
||||
beker.</li>
|
||||
<li>Aplikasi yang menyediakan pemberitahuan pengguna yang penting, seperti aplikasi SMS.</li>
|
||||
<li>Aplikasi yang menyediakan layanan aksesibilitas, seperti TalkBack.</li>
|
||||
</ul>
|
||||
|
||||
<p>Jika aplikasi Anda perlu mengakses data saat dijalankan dalam mode Direct Boot, gunakan
|
||||
penyimpanan yang dienkripsi dengan perangkat. Penyimpanan yang dienkripsi dengan perangkat berisi data
|
||||
yang dienkripsi dengan kunci yang hanya tersedia setelah perangkat melakukan
|
||||
booting yang berhasil diverifikasi.</p>
|
||||
|
||||
<p>Untuk data yang harus dienkripsi dengan kunci yang dikaitkan dengan kredensial
|
||||
pengguna, seperti PIN atau kata sandi, gunakan penyimpanan yang dienkripsi dengan kredensial.
|
||||
Penyimpanan yang dienkripsi dengan kredensial hanya tersedia setelah pengguna berhasil
|
||||
membuka kunci perangkat, hingga saat pengguna menghidupkan ulang perangkat lagi. Jika
|
||||
pengguna mengaktifkan layar kunci setelah membuka kunci perangkat, hal ini tidak akan mengunci
|
||||
penyimpanan yang dienkripsi dengan kredensial.</p>
|
||||
|
||||
<h2 id="run">Meminta Akses untuk Berjalan Selama Direct Boot</h2>
|
||||
|
||||
<p>Aplikasi harus mendaftarkan komponennya pada sistem agar
|
||||
bisa berjalan selama mode Direct Boot atau mengakses
|
||||
penyimpanan yang dienkripsi dengan perangkat. Aplikasi mendaftar pada sistem dengan menandai komponen sebagai
|
||||
<i>peka enkripsi</i>. Untuk menandai komponen Anda sebagai peka enkripsi, setel atribut
|
||||
<code>android:directBootAware</code> ke true dalam manifes Anda.<p>
|
||||
|
||||
<p>Komponen yang peka enkripsi bisa mendaftar untuk menerima pesan siaran
|
||||
<code>LOCKED_BOOT_COMPLETED</code> dari
|
||||
sistem bila perangkat telah dihidupkan ulang. Pada tahap ini
|
||||
penyimpanan yang dienkripsi dengan perangkat akan tersedia, dan komponen Anda bisa mengeksekusi tugas-tugas yang perlu
|
||||
dijalankan selama mode Direct Boot, seperti memicu alarm yang terjadwal.</p>
|
||||
|
||||
<p>Cuplikan kode berikut adalah contoh cara mendaftarkan
|
||||
{@link android.content.BroadcastReceiver} sebagai peka enkripsi, dan menambahkan sebuah
|
||||
filter intent untuk <code>LOCKED_BOOT_COMPLETED</code>, dalam manifes aplikasi:</p>
|
||||
|
||||
<pre>
|
||||
<receiver
|
||||
android:directBootAware="true" >
|
||||
...
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</pre>
|
||||
|
||||
<p>Setelah pengguna membuka kunci perangkat, semua komponen bisa mengakses
|
||||
penyimpanan yang dienkripsi dengan perangkat serta penyimpanan yang dienkripsi dengan kredensial.</p>
|
||||
|
||||
<h2 id="access">Mengakses Penyimpanan yang Dienkripsi dengan Perangkat</h2>
|
||||
|
||||
<p>Untuk mengakses penyimpanan yang dienkripsi dengan perangkat, buat instance
|
||||
{@link android.content.Context} kedua dengan memanggil
|
||||
<code>Context.createDeviceProtectedStorageContext()</code>. Semua panggilan
|
||||
API penyimpanan yang dibuat menggunakan konteks ini mengakses penyimpanan yang dienkripsi dengan perangkat. Contoh
|
||||
berikut mengakses penyimpanan yang dienkripsi dengan perangkat dan membuka file data aplikasi
|
||||
yang ada:</p>
|
||||
|
||||
<pre>
|
||||
Context directBootContext = appContext.createDeviceProtectedStorageContext();
|
||||
// Access appDataFilename that lives in device encrypted storage
|
||||
FileInputStream inStream = directBootContext.openFileInput(appDataFilename);
|
||||
// Use inStream to read content...
|
||||
</pre>
|
||||
|
||||
<p>Gunakan penyimpanan yang dienkripsi dengan perangkat hanya untuk
|
||||
informasi yang harus bisa diakses selama mode Direct Boot.
|
||||
Jangan gunakan penyimpanan yang dienkripsi dengan perangkat sebagai penyimpanan terenkripsi serba guna.
|
||||
Untuk informasi pengguna yang bersifat pribadi, atau data terenkripsi yang tidak diperlukan selama
|
||||
mode Direct Boot, gunakan penyimpanan yang dienkripsi dengan kredensial.</p>
|
||||
|
||||
<h2 id="notification">Mendapatkan Pemberitahuan saat Pengguna Membuka Kunci</h2>
|
||||
|
||||
<p>Setelah pengguna membuka kunci perangkat setelah restart, aplikasi Anda bisa beralih untuk
|
||||
mengakses penyimpanan yang dienkripsi dengan kredensial dan menggunakan layanan sistem biasa yang
|
||||
bergantung pada kredensial pengguna.</p>
|
||||
|
||||
<p>Agar diberi tahu bila pengguna membuka kunci perangkat setelah boot ulang,
|
||||
daftarkan {@link android.content.BroadcastReceiver} dari komponen yang berjalan
|
||||
untuk mendengarkan pesan <code>ACTION_USER_UNLOCKED</code>. Atau, Anda bisa
|
||||
menerima pesan {@link android.content.Intent#ACTION_BOOT_COMPLETED
|
||||
ACTION_BOOT_COMPLETED} yang ada, yang sekarang menunjukkan bahwa perangkat telah dihidupkan dan
|
||||
pengguna telah membuka kunci perangkat.</p>
|
||||
|
||||
<p>Anda bisa langsung kueri apakah pengguna telah membuka kunci perangkat dengan memanggil
|
||||
<code>UserManager.isUserUnlocked()</code>.</p>
|
||||
|
||||
<h2 id="migrating">Migrasi Data yang Ada</h2>
|
||||
|
||||
<p>Jika pengguna memperbarui perangkat mereka untuk menggunakan mode Direct Boot,
|
||||
data Anda yang ada mungkin perlu dipindahkan ke penyimpanan yang dienkripsi dengan perangkat. Gunakan
|
||||
<code>Context.moveSharedPreferencesFrom()</code> dan
|
||||
<code>Context.moveDatabaseFrom()</code> untuk memindahkan data preferensi dan
|
||||
basis data antara penyimpanan yang dienkripsi dengan kredensial dan penyimpanan yang dienkripsi dengan perangkat.</p>
|
||||
|
||||
<p>Pertimbangkan dengan baik saat memutuskan data apa yang akan dipindahkan dari
|
||||
penyimpanan yang dienkripsi dengan kredensial ke penyimpanan yang dienkripsi dengan perangkat. Anda sebaiknya tidak memindahkan
|
||||
informasi pengguna yang bersifat rahasia, seperti kata sandi atau token otorisasi, ke
|
||||
penyimpanan yang dienkripsi dengan perangkat. Dalam beberapa skenario, Anda mungkin perlu mengelola
|
||||
set data terpisah pada dua tempat penyimpanan yang dienkripsi.</p>
|
||||
|
||||
<h2 id="testing">Menguji Aplikasi Peka Enkripsi Anda</h2>
|
||||
|
||||
<p>Uji aplikasi peka enkripsi Anda menggunakan mode Direct Boot baru. Ada
|
||||
dua cara untuk mengaktifkan Direct Boot.</p>
|
||||
|
||||
<p class="caution"><strong>Perhatian:</strong> Mengaktifkan Direct Boot
|
||||
akan menghapus semua data pengguna pada perangkat.</p>
|
||||
|
||||
<p>Pada perangkat yang didukung dengan Android N terpasang, aktifkan
|
||||
Direct Boot dengan melakukan salah satu hal berikut:</p>
|
||||
|
||||
<ul>
|
||||
<li>Pada perangkat, aktifkan <b>Developer options</b> jika Anda belum melakukannya dengan
|
||||
masuk ke <b>Settings > About phone</b>, dan menyentuh <b>Build number</b>
|
||||
tujuh kali. Setelah layar Developer options terbuka, masuk ke
|
||||
<b>Settings > Developer options</b> dan pilih
|
||||
<b>Convert to file encryption</b>.</li>
|
||||
<li>Gunakan perintah shell adb berikut untuk mengaktifkan mode Direct Boot:
|
||||
<pre class="no-pretty-print">
|
||||
$ adb reboot-bootloader
|
||||
$ fastboot --wipe-and-use-fbe
|
||||
</pre>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Mode emulasi Direct Boot juga tersedia, jika Anda perlu mengganti
|
||||
mode pada perangkat pengujian. Mode emulasi sebaiknya hanya digunakan selama
|
||||
pengembangan dan bisa menyebabkan kehilangan data. Untuk mengaktifkan mode emulasi Direct Boot,
|
||||
setel pola kunci pada perangkat, pilih "No thanks" jika ditanya mengenai
|
||||
layar start-up aman saat menetapkan pola kunci, kemudian gunakan
|
||||
perintah shell adb berikut:</p>
|
||||
|
||||
<pre class="no-pretty-print">
|
||||
$ adb shell sm set-emulate-fbe true
|
||||
</pre>
|
||||
|
||||
<p>Untuk menonaktifkan mode emulasi Direct Boot, gunakan perintah berikut:</p>
|
||||
|
||||
<pre class="no-pretty-print">
|
||||
$ adb shell sm set-emulate-fbe false
|
||||
</pre>
|
||||
|
||||
<p>Menggunakan perintah ini akan menyebabkan perangkat melakukan boot ulang.</p>
|
||||
@@ -0,0 +1,148 @@
|
||||
page.title=Scoped Directory Access
|
||||
page.keywords=pratinjau,sdk,scoped directory access
|
||||
page.tags=androidn
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#accessing">Mengakses Direktori Penyimpanan Eksternal</a></li>
|
||||
<li><a href="#removable">Mengakses Direktori pada Media Lepas-Pasang</a></li>
|
||||
<li><a href="#best">Praktik Terbaik</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Aplikasi seperti aplikasi foto biasanya hanya memerlukan akses ke direktori tertentu dalam
|
||||
penyimpanan eksternal, seperti direktori <code>Pictures</code>. Pendekatan
|
||||
yang ada dalam mengakses penyimpanan eksternal tidak didesain untuk memberi kemudahan
|
||||
akses direktori tertarget untuk tipe aplikasi ini. Misalnya:</p>
|
||||
|
||||
<ul>
|
||||
<li>Meminta {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}
|
||||
atau {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} dalam manifes Anda
|
||||
akan memungkinkan akses ke semua direktori publik pada penyimpanan eksternal, yang mungkin
|
||||
lebih banyak akses dari yang dibutuhkan aplikasi Anda.</li>
|
||||
<li>Menggunakan
|
||||
<a href="{@docRoot}guide/topics/providers/document-provider.html">Storage
|
||||
Access Framework</a> biasanya membuat pengguna Anda memilih direktori
|
||||
melalui UI sistem, yang tidak diperlukan jika aplikasi Anda selalu mengakses
|
||||
direktori eksternal yang sama.</li>
|
||||
</ul>
|
||||
|
||||
<p>Android N menyediakan API baru yang disederhanakan untuk mengakses
|
||||
direktori penyimpanan eksternal umum. </p>
|
||||
|
||||
<h2 id="accessing">Mengakses Direktori Penyimpanan Eksternal</h2>
|
||||
|
||||
<p>Gunakan kelas <code>StorageManager</code> untuk mendapatkan instance
|
||||
<code>StorageVolume</code> yang tepat. Kemudian, buat intent dengan memanggil metode
|
||||
<code>StorageVolume.createAccessIntent()</code> dari instance itu.
|
||||
Gunakan intent ini untuk mengakses direktori penyimpanan eksternal. Untuk mendapatkan daftar
|
||||
semua volume yang tersedia, termasuk volume media lepas-pasang, gunakan
|
||||
<code>StorageManager.getVolumesList()</code>.</p>
|
||||
|
||||
<p>Jika Anda memiliki informasi tentang file spesifik, gunakan
|
||||
<code>StorageManager.getStorageVolume(File)</code> untuk mendapatkan
|
||||
<code>StorageVolume</code> yang berisi file tersebut. Panggil
|
||||
<code>createAccessIntent()</code> pada <code>StorageVolume</code> ini untuk mengakses
|
||||
direktori penyimpanan eksternal untuk file tersebut.</p>
|
||||
|
||||
<p>
|
||||
Di volume kedua, seperti kartu SD eksternal, teruskan null saat memanggil
|
||||
<code>StorageVolume.createAccessIntent()</code> untuk meminta akses ke seluruh
|
||||
volume, sebagai ganti direktori spesifik.
|
||||
<code>StorageVolume.createAccessIntent()</code> akan mengembalikan null jika Anda meneruskan
|
||||
null ke volume utama, atau jika Anda meneruskan nama direktori yang tidak valid.
|
||||
</p>
|
||||
|
||||
<p>Cuplikan kode berikut adalah contoh cara membuka direktori
|
||||
<code>Pictures</code> dalam penyimpanan bersama utama:</p>
|
||||
|
||||
<pre>
|
||||
StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
|
||||
StorageVolume volume = sm.getPrimaryVolume();
|
||||
Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
|
||||
startActivityForResult(intent, request_code);
|
||||
</pre>
|
||||
|
||||
<p>Sistem ini mencoba untuk memberikan akses ke direktori eksternal, dan jika
|
||||
diperlukan mengonfirmasi akses dengan pengguna menggunakan UI yang disederhanakan:</p>
|
||||
|
||||
<img src="{@docRoot}images/android-7.0/scoped-directory-access-framed.png" srcset="{@docRoot}images/android-7.0/scoped-directory-access-framed.png 1x,
|
||||
{@docRoot}images/android-7.0/scoped-directory-access-framed_2x.png 2x" />
|
||||
<p class="img-caption"><strong>Gambar 1.</strong> Sebuah aplikasi yang meminta
|
||||
akses ke direktori Pictures.</p>
|
||||
|
||||
<p>Jika pengguna memberi akses, sistem akan memanggil penggantian
|
||||
<code>onActivityResult()</code> Anda dengan kode hasil
|
||||
<code>Activity.RESULT_OK</code>, dan data intent yang berisi URI. Gunakan
|
||||
URI yang disediakan untuk mengakses informasi direktori, serupa dengan menggunakan URI
|
||||
yang dikembalikan oleh
|
||||
<a href="{@docRoot}guide/topics/providers/document-provider.html">Storage
|
||||
Access Framework</a>.</p>
|
||||
|
||||
<p>Jika pengguna tidak memberi akses, sistem akan memanggil penggantian
|
||||
<code>onActivityResult()</code> Anda dengan kode hasil
|
||||
<code>Activity.RESULT_CANCELED</code>, dan data intent nol.</p>
|
||||
|
||||
<p class="note"><b>Catatan</b>: Mendapatkan akses ke direktori eksternal tertentu
|
||||
juga akan memperoleh akses ke subdirektori dalam direktori tersebut.</p>
|
||||
|
||||
<h2 id="removable">Mengakses Direktori pada Media Lepas-Pasang</h2>
|
||||
|
||||
<p>Untuk menggunakan Scoped Directory Access guna mengakses direktori pada media lepas-pasang,
|
||||
pertama tambahkan {@link android.content.BroadcastReceiver} yang akan mendengarkan pemberitahuan
|
||||
{@link android.os.Environment#MEDIA_MOUNTED}, misalnya:</p>
|
||||
|
||||
<pre>
|
||||
<receiver
|
||||
android:name=".MediaMountedReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MEDIA_MOUNTED" />
|
||||
<data android:scheme="file" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</pre>
|
||||
|
||||
<p>Bila pengguna memasang media lepas-pasang, seperti kartu SD, sistem akan mengirimkan pemberitahuan
|
||||
{@link android.os.Environment#MEDIA_MOUNTED}. Pemberitahuan ini
|
||||
memberikan sebuah objek <code>StorageVolume</code> dalam data intent yang bisa
|
||||
Anda gunakan untuk mengakses direktori pada media lepas-pasang. Contoh berikut
|
||||
mengakses direktori <code>Pictures</code> pada media lepas-pasang:</p>
|
||||
|
||||
<pre>
|
||||
// BroadcastReceiver has already cached the MEDIA_MOUNTED
|
||||
// notification Intent in mediaMountedIntent
|
||||
StorageVolume volume = (StorageVolume)
|
||||
mediaMountedIntent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);
|
||||
volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
|
||||
startActivityForResult(intent, request_code);
|
||||
</pre>
|
||||
|
||||
<h2 id="best">Praktik Terbaik</h2>
|
||||
|
||||
<p>Bila memungkinkan, pertahankan URI akses direktori eksternal sehingga Anda tidak perlu
|
||||
berulang kali meminta akses ke pengguna. Setelah pengguna memberikan akses, panggil
|
||||
<code>getContentResolver().takePersistableUriPermssion()</code> bersama
|
||||
URI akses direktori. Sistem akan mempertahankan URI dan permintaan
|
||||
akses berikutnya akan mengembalikan <code>RESULT_OK</code> dan tidak menampilkan UI konfirmasi kepada
|
||||
pengguna.</p>
|
||||
|
||||
<p>Jika pengguna menolak akses ke direktori eksternal, jangan langsung
|
||||
meminta akses lagi. Berulang kali meminta akses akan menghasilkan pengalaman
|
||||
pengguna yang buruk. Jika permintaan ditolak oleh pengguna, dan aplikasi meminta akses
|
||||
lagi, UI akan menampilkan kotak centang <b>Don't ask again</b>:</p>
|
||||
|
||||
<img src="{@docRoot}images/android-7.0/scoped-directory-access-dont-ask.png" srcset="{@docRoot}images/android-7.0/scoped-directory-access-dont-ask.png 1x,
|
||||
{@docRoot}images/android-7.0/scoped-directory-access-dont-ask_2x.png 2x" />
|
||||
<p class="img-caption"><strong>Gambar 1.</strong> Sebuah aplikasi membuat
|
||||
permintaan kedua untuk mengakses media lepas-pasang.</p>
|
||||
|
||||
<p>Jika pengguna memilih <b>Don't ask again</b> dan menolak permintaan,
|
||||
semua permintaan berikutnya untuk direktori yang diberikan dari aplikasi
|
||||
Anda secara otomatis akan ditolak, dan tidak ada UI permintaan yang akan ditampilkan ke pengguna.</p>
|
||||
747
docs/html-intl/intl/id/training/articles/security-config.jd
Normal file
747
docs/html-intl/intl/id/training/articles/security-config.jd
Normal file
@@ -0,0 +1,747 @@
|
||||
page.title=Konfigurasi Keamanan Jaringan
|
||||
page.keywords=androidn,keamanan,jaringan
|
||||
page.image=images/cards/card-nyc_2x.jpg
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#manifest">Menambahkan File Konfigurasi Keamanan</a></li>
|
||||
<li><a href="#CustomTrust">Menyesuaikan CA Tepercaya</a>
|
||||
<ol>
|
||||
<li><a href="#ConfigCustom">Mengonfigurasi CA Tepercaya Khusus</a></li>
|
||||
<li><a href="#LimitingCas">Membatasi Set CA Tepercaya</a></li>
|
||||
<li><a href="#TrustingAdditionalCas">Mempercayai CA Tambahan</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#TrustingDebugCa">CA Debug Saja</a></li>
|
||||
<li><a href="#UsesCleartextTraffic">Berhenti dari Lalu Lintas Cleartext</a></li>
|
||||
<li><a href="#CertificatePinning">Menyematkan Sertifikat</a></li>
|
||||
<li><a href="#ConfigInheritance">Perilaku Pewarisan Konfigurasi</a></li>
|
||||
<li><a href="#FileFormat">Format File Konfigurasi</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>
|
||||
Android N menyertakan fitur
|
||||
Network Security Configuration yang memungkinkan aplikasi menyesuaikan setelan keamanan jaringan mereka dalam
|
||||
file konfigurasi deklaratif yang aman tanpa memodifikasi kode aplikasi. Setelan ini bisa
|
||||
dikonfigurasi untuk domain dan aplikasi tertentu. Kemampuan
|
||||
utama fitur ini adalah sebagai berikut:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<b>Trust-anchor khusus:</b> Menyesuaikan Certificate Authorities (CA) mana
|
||||
yang dipercaya untuk koneksi aman aplikasi. Misalnya,
|
||||
mempercayai sertifikat tertentu yang ditandatangani sendiri atau membatasi
|
||||
set CA umum yang dipercaya aplikasi.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>Penggantian hanya-debug:</b> Men-debug secara aman koneksi aman dalam aplikasi
|
||||
tanpa menambahkan risiko pada basis yang telah dipasang.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>Berhenti dari lalu lintas cleartext:</b> Melindungi aplikasi dari
|
||||
penggunaan lalu lintas cleartext secara tidak sengaja.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>Penyematan sertifikat:</b> Membatasi koneksi aman aplikasi ke
|
||||
sertifikat tertentu.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2 id="manifest">Menambahkan File Konfigurasi Keamanan</h2>
|
||||
|
||||
<p>
|
||||
Fitur Network Security Configuration menggunakan file XML tempat Anda menetapkan
|
||||
setelan untuk aplikasi. Anda harus menyertakan sebuah entri dalam manifes aplikasi
|
||||
untuk menunjuk ke file ini. Kutipan kode berikut dari sebuah manifes
|
||||
yang memperagakan cara membuat entri ini:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest ... >
|
||||
<application ... >
|
||||
<meta-data android:name="android.security.net.config"
|
||||
android:resource="@xml/network_security_config" />
|
||||
...
|
||||
</application>
|
||||
</manifest>
|
||||
</pre>
|
||||
|
||||
<h2 id="CustomTrust">Menyesuaikan CA Tepercaya</h2>
|
||||
|
||||
<p>
|
||||
Aplikasi mungkin perlu mempercayai set CA khusus sebagai ganti default
|
||||
platform. Alasannya yang paling umum adalah:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Menghubungkan ke host dengan otoritas sertifikat khusus (ditandatangani sendiri,
|
||||
dikeluarkan oleh CA internal, dll).
|
||||
</li>
|
||||
|
||||
<li>Membatasi set CA hanya untuk CA yang Anda percaya sebagai ganti setiap CA
|
||||
yang sudah terpasang.
|
||||
</li>
|
||||
|
||||
<li>Mempercayai CA tambahan yang tidak disertakan dalam sistem.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Secara default koneksi (mis. TLS, HTTPS) aman dari semua aplikasi mempercayai
|
||||
CA yang telah dipasang oleh sistem, dan aplikasi yang menargetkan API level 23
|
||||
(Android M) ke bawah, juga mempercayai penyimpanan CA yang ditambahkan pengguna secara default. Aplikasi
|
||||
bisa menyesuaikan koneksinya menggunakan {@code base-config} (untuk
|
||||
penyesuaian lebar-aplikasi) atau {@code domain-config} (untuk penyesuaian
|
||||
per-domain).
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="ConfigCustom">Mengonfigurasi CA Khusus</h3>
|
||||
|
||||
<p>
|
||||
Anggaplah Anda ingin menghubungkan ke host Anda yang menggunakan sertifikat
|
||||
SSL yang ditandatangani sendiri atau ke host yang sertifikat SSL-nya dikeluarkan oleh CA non-publik
|
||||
yang Anda percaya, seperti CA internal perusahaan Anda.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>res/xml/network_security_config.xml</code>:
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config>
|
||||
<domain includeSubdomains="true">example.com</domain>
|
||||
<trust-anchors>
|
||||
<certificates src="@raw/my_ca"/>
|
||||
</trust-anchors>
|
||||
</domain-config>
|
||||
</network-security-config>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Menambahkan sertifikat CA yang ditandatangani sendiri atau sertifikat CA non-publik, dalam format PEM atau DER, ke
|
||||
{@code res/raw/my_ca}.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="LimitingCas">Membatasi Set CA Tepercaya</h3>
|
||||
|
||||
<p>
|
||||
Aplikasi yang tidak ingin mempercayai semua CA yang dipercaya oleh sistem
|
||||
sebagai gantinya bisa menetapkan set CA sendiri yang telah dikurangi untuk dipercaya. Ini akan melindungi
|
||||
aplikasi dari sertifikat palsu yang dikeluarkan oleh selain CA.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Konfigurasi untuk membatasi set CA tepercaya mirip dengan <a href="#TrustingACustomCa">mempercayai CA khusus</a> untuk domain tertentu selain
|
||||
beberapa CA disediakan dalam sumber daya.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>res/xml/network_security_config.xml</code>:
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config>
|
||||
<domain includeSubdomains="true">secure.example.com</domain>
|
||||
<domain includeSubdomains="true">cdn.example.com</domain>
|
||||
<trust-anchors>
|
||||
<certificates src="@raw/trusted_roots"/>
|
||||
</trust-anchors>
|
||||
</domain-config>
|
||||
</network-security-config>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Menambahkan CA tepercaya, dalam format PEM atau DER, ke {@code res/raw/trusted_roots}.
|
||||
Perhatikan, jika menggunakan format PEM, file <em>hanya</em> boleh berisi data PEM
|
||||
dan tidak ada teks tambahan. Anda juga bisa menyediakan beberapa elemen
|
||||
<a href="#certificates"><code><certificates></code></a>
|
||||
sebagai ganti satu elemen.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="TrustingAdditionalCas">
|
||||
Mempercayai CA Tambahan
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
Sebuah aplikasi mungkin perlu mempercayai CA tambahan yang tidak dipercaya oleh sistem,
|
||||
hal ini bisa disebabkan karena sistem belum menyertakan CA atau CA tidak
|
||||
memenuhi persyaratan untuk memasukkan ke dalam sistem Android. Aplikasi
|
||||
bisa melakukannya dengan menetapkan beberapa sumber sertifikat untuk
|
||||
konfigurasi.
|
||||
</p>
|
||||
<p>
|
||||
<code>res/xml/network_security_config.xml</code>:
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config>
|
||||
<trust-anchors>
|
||||
<certificates src="@raw/extracas"/>
|
||||
<certificates src="system"/>
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="TrustingDebugCa">Mengonfigurasi CA untuk Debug</h2>
|
||||
|
||||
<p>
|
||||
Saat men-debug aplikasi yang terhubung melalui HTTPS, Anda mungkin perlu
|
||||
menghubungkan ke server pengembangan lokal, yang tidak memiliki sertifikat
|
||||
SSL untuk server produksi Anda. Untuk mendukungnya tanpa
|
||||
memodifikasi kode aplikasi, Anda bisa menetapkan CA hanya-debug
|
||||
yang <i>hanya</i> dipercaya bila <a href="{@docRoot}guide/topics/manifest/application-element.html#debug">
|
||||
android:debuggable</a>
|
||||
adalah {@code true} dengan menggunakan {@code debug-overrides}. Biasanya IDE dan alat
|
||||
build menyetel flag ini secara otomatis untuk build non-rilis.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Ini lebih aman daripada kode kondisional biasa karena, sebagai tindakan
|
||||
pencegahan keamanan, toko aplikasi tidak menerima aplikasi yang ditandai
|
||||
bisa-di-debug.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>res/xml/network_security_config.xml</code>:
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<debug-overrides>
|
||||
<trust-anchors>
|
||||
<certificates src="@raw/debug_cas"/>
|
||||
</trust-anchors>
|
||||
</debug-overrides>
|
||||
</network-security-config>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="UsesCleartextTraffic">Berhenti dari Lalu Lintas Cleartext</h2>
|
||||
|
||||
<p>
|
||||
Aplikasi bermaksud menyambung ke tujuan hanya menggunakan koneksi
|
||||
aman dapat memilih keluar dari dukungan cleartext (menggunakan protokol
|
||||
HTTP yang tidak terenkripsi sebagai ganti HTTPS) ke tujuan tersebut. Opsi ini akan membantu mencegah
|
||||
regresi tidak disengaja dalam aplikasi karena perubahan dalam URL yang disediakan oleh sumber-sumber
|
||||
eksternal seperti server backend.
|
||||
Lihat {@link android.security.NetworkSecurityPolicy#isCleartextTrafficPermitted
|
||||
NetworkSecurityPolicy.isCleartextTrafficPermitted()} untuk detail selengkapnya.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Misalnya, aplikasi mungkin ingin memastikan semua koneksi ke {@code
|
||||
secure.example.com} selalu dilakukan melalui HTTPS untuk melindungi lalu lintas sensitif
|
||||
dari jaringan yang berbahaya.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>res/xml/network_security_config.xml</code>:
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config usesCleartextTraffic="false">
|
||||
<domain includeSubdomains="true">secure.example.com</domain>
|
||||
</domain-config>
|
||||
</network-security-config>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="CertificatePinning">Menyematkan Sertifikat</h2>
|
||||
|
||||
<p>
|
||||
Biasanya aplikasi mempercayai semua CA yang telah terpasang. Jika salah satu dari CA ini
|
||||
mengeluarkan sertifikat palsu, aplikasi akan berisiko terkena serangan
|
||||
MiTM. Beberapa aplikasi memilih untuk membatasi set sertifikat yang mereka terima
|
||||
baik dengan membatasi set CA yang mereka percaya atau dengan menyematkan sertifikat.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Penyematan sertifikat dilakukan dengan memberikan seperangkat sertifikat dengan hash
|
||||
kunci publik (SubjectPublicKeyInfo pada sertifikat X.509). Rantai
|
||||
sertifikat nanti hanya berlaku jika rantai sertifikat berisi setidaknya salah satu
|
||||
dari kunci publik yang disematkan.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Perhatikan, saat menggunakan penyematan sertifikat, Anda harus selalu menyertakan kunci
|
||||
cadangan sehingga jika Anda terpaksa beralih ke kunci baru, atau mengubah CA (saat
|
||||
menyematkan ke sertifikat CA atau perantara CA tersebut), konektivitas
|
||||
aplikasi Anda tidak terpengaruh. Jika tidak, Anda harus mendorong
|
||||
pembaruan ke aplikasi tersebut untuk memulihkan konektivitas.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Selain itu dimungkinkan juga menyetel waktu habis masa berlaku untuk pin setelah
|
||||
penyematan tidak dilakukan. Hal ini membantu mencegah masalah konektivitas dalam
|
||||
aplikasi yang belum diperbarui. Akan tetapi, menyetel waktu kedaluwarsa
|
||||
pada pin mungkin akan membuat penyematan bisa diabaikan.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>res/xml/network_security_config.xml</code>:
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config>
|
||||
<domain includeSubdomains="true">example.com</domain>
|
||||
<pin-set expiration="2018-01-01">
|
||||
<pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
|
||||
<!-- backup pin -->
|
||||
<pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin>
|
||||
</pin-set>
|
||||
</domain-config>
|
||||
</network-security-config>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="ConfigInheritance">Perilaku Pewarisan Konfigurasi</h2>
|
||||
|
||||
<p>
|
||||
Nilai yang tidak disetel dalam konfigurasi tertentu akan diwariskan. Perilaku ini memungkinkan konfigurasi
|
||||
yang lebih kompleks sambil menjaga file konfigurasi tetap terbaca.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Jika nilai tidak disetel dalam entri tertentu maka nilai dari entri berikutnya yang lebih
|
||||
umum akan digunakan. Nilai yang tidak disetel dalam {@code domain-config} akan
|
||||
diambil dari {@code domain-config} induk, jika tersarang, atau dari {@code
|
||||
base-config} jika tidak. Nilai yang tidak disetel dalam {@code base-config} akan menggunakan
|
||||
nilai default platform.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Misalnya pertimbangkan, bila semua koneksi ke subdomain {@code
|
||||
example.com} harus menggunakan set CA khusus. Selain itu, lalu lintas cleartext ke
|
||||
domain ini diizinkan <em>kecuali</em> saat menghubungkan ke {@code
|
||||
secure.example.com}. Dengan menyarangkan konfigurasi untuk {@code
|
||||
secure.example.com} dalam konfigurasi untuk {@code example.com},
|
||||
{@code trust-anchors} tidak perlu digandakan.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>res/xml/network_security_config.xml</code>:
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config>
|
||||
<domain includeSubdomains="true">example.com</domain>
|
||||
<trust-anchors>
|
||||
<certificates src="@raw/my_ca"/>
|
||||
</trust-anchors>
|
||||
<domain-config cleartextTrafficPermitted="false">
|
||||
<domain includeSubdomains="true">secure.example.com</domain>
|
||||
</domain-config>
|
||||
</domain-config>
|
||||
</network-security-config>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="FileFormat">Format File Konfigurasi</h2>
|
||||
|
||||
<p>
|
||||
Fitur Network Security Configuration menggunakan format file XML.
|
||||
Struktur keseluruhan file ditampilkan dalam contoh kode berikut:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config>
|
||||
<trust-anchors>
|
||||
<certificates src="..."/>
|
||||
...
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
|
||||
<domain-config>
|
||||
<domain>android.com</domain>
|
||||
...
|
||||
<trust-anchors>
|
||||
<certificates src="..."/>
|
||||
...
|
||||
</trust-anchors>
|
||||
<pin-set>
|
||||
<pin digest="...">...</pin>
|
||||
...
|
||||
</pin-set>
|
||||
</domain-config>
|
||||
...
|
||||
<debug-overrides>
|
||||
<trust-anchors>
|
||||
<certificates src="..."/>
|
||||
...
|
||||
</trust-anchors>
|
||||
</debug-overrides>
|
||||
</network-security-config>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Bagian berikut menjelaskan sintaks dan detail lainnya dari format
|
||||
file.
|
||||
</p>
|
||||
|
||||
<h3 id="network-security-config">
|
||||
<network-security-config>
|
||||
</h3>
|
||||
|
||||
<dl class="xml">
|
||||
<dt>
|
||||
bisa berisi:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
0 atau 1 <code><a href="#base-config"><base-config></a></code><br>
|
||||
Sejumlah <code><a href=
|
||||
"#domain-config"><domain-config></a></code><br>
|
||||
0 atau 1 <code><a href="#debug-overrides"><debug-overrides></a></code>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3 id="base-config">
|
||||
<base-config>
|
||||
</h3>
|
||||
|
||||
<dl class="xml">
|
||||
<dt>
|
||||
sintaks:
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<pre class="stx">
|
||||
<base-config <a href=
|
||||
"#usesCleartextTraffic">usesCleartextTraffic</a>=["true" | "false"]>
|
||||
...
|
||||
</base-config>
|
||||
</pre>
|
||||
<dl class="xml">
|
||||
<dt>
|
||||
bisa berisi:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
<code><a href="#trust-anchors"><trust-anchors></a></code>
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
keterangan:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Konfigurasi default yang digunakan oleh semua koneksi yang tujuannya tidak
|
||||
tercakup oleh <a href="#domain-config"><code>domain-config</code></a>.
|
||||
|
||||
<p>
|
||||
Nilai yang tidak disetel akan menggunakan nilai default platform. Konfigurasi
|
||||
default untuk aplikasi yang menargetkan API level 24 ke atas:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<base-config usesCleartextTraffic="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</pre>
|
||||
Konfigurasi default untuk aplikasi yang menargetkan API level 23 ke bawah:
|
||||
<pre>
|
||||
<base-config usesCleartextTraffic="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<certificates src="user" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</pre>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3 id="domain-config"><domain-config></h3>
|
||||
<dl class="xml">
|
||||
<dt>sintaks:</dt>
|
||||
<dd>
|
||||
<pre class="stx"><domain-config <a href="#usesCleartextTraffic">usesCleartextTraffic</a>=["true" | "false"]>
|
||||
...
|
||||
</domain-config></pre>
|
||||
</dd>
|
||||
|
||||
<dt>Bisa Berisi:</dt>
|
||||
|
||||
<dd>
|
||||
1 atau beberapa <code><a href="#domain"><domain></a></code>
|
||||
<br/>0 atau 1 <code><a href="#trust-anchors"><trust-anchors></a></code>
|
||||
<br/>0 atau 1 <code><a href="#pin-set"><pin-set></code></a>
|
||||
<br/>Sejumlah <code><domain-config></code> tersarang</dd>
|
||||
|
||||
<dt>Keterangan</dt>
|
||||
<dd>Konfigurasi yang digunakan untuk koneksi ke tujuan tertentu seperti didefinisikan oleh elemen {@code domain}.
|
||||
|
||||
<p>Perhatikan, jika beberapa elemen {@code domain-config} mencakup suatu tujuan, konfigurasi dengan aturan domain paling spesifik (terpanjang) yang cocok
|
||||
akan digunakan.</p></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
<h3 id="domain"><domain></h3>
|
||||
|
||||
<dl class="xml">
|
||||
<dt>
|
||||
sintaks:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
<pre class="stx">
|
||||
<domain includeSubdomains=["true" | "false"]>example.com</domain>
|
||||
</pre>
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
Atribut:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
<dl class="attr">
|
||||
<dt>
|
||||
{@code includeSubdomains}
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Jika {@code "true"} maka aturan domain ini akan dicocokkan dengan domain dan semua
|
||||
subdomain, termasuk subdomain dari subdomain, jika tidak peraturan hanya
|
||||
diterapkan pada kecocokan yang persis tepat.
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
Keterangan:
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<h3 id="debug-overrides"><debug-overrides></h3>
|
||||
|
||||
<dl class="xml">
|
||||
<dt>
|
||||
sintaks:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
<pre class="stx">
|
||||
<debug-overrides>
|
||||
...
|
||||
</debug-overrides>
|
||||
</pre>
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
Bisa Berisi:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
0 atau 1 <code><a href="#trust-anchors"><trust-anchors></a></code>
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
Keterangan:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Pengesampingan yang akan diterapkan bila <a href="{@docRoot}guide/topics/manifest/application-element.html#debug">android:debuggable</a>
|
||||
adalah {@code "true"} yang biasanya terjadi untuk build non-rilis
|
||||
yang dihasilkan oleh alat IDE dan build. Trust-anchor yang ditetapkan dalam {@code
|
||||
debug-overrides} akan ditambahkan ke semua konfigurasi lainnya dan penyematan
|
||||
sertifikat tidak dilakukan bila rantai sertifikat server menggunakan satu dari
|
||||
trust-anchor hanya-debug ini. Jika <a href="{@docRoot}guide/topics/manifest/application-element.html#debug">android:debuggable</a>
|
||||
adalah {@code "false"} maka bagian ini akan diabaikan sepenuhnya.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3 id="trust-anchors"><trust-anchors></h3>
|
||||
<dl class="xml">
|
||||
<dt>
|
||||
sintaks:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
<pre class="stx">
|
||||
<trust-anchors>
|
||||
...
|
||||
</trust-anchors>
|
||||
</pre>
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
Bisa Berisi:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Sejumlah <code><a href="#certificates"><certificates></a></code>
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
Keterangan:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Set trust-anchor untuk koneksi aman.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
<h3 id="certificates"><certificates></h3>
|
||||
<dl class="xml">
|
||||
<dt>sintaks:</dt>
|
||||
<dd><pre class="stx"><certificates src=["system" | "user" | "<i>raw resource</i>"]
|
||||
overridePins=["true" | "false"] />
|
||||
</pre></dd>
|
||||
<dt>keterangan:</dt>
|
||||
<dd>Set sertifikat X.509 untuk elemen {@code trust-anchors}.</dd>
|
||||
|
||||
<dt>atribut:</dt>
|
||||
<dd><dl class="attr">
|
||||
<dt>{@code src}</dt>
|
||||
<dd>
|
||||
Sumber sertifikat CA, bisa salah satu dari
|
||||
<ul>
|
||||
<li>ID sumber daya mentah yang menunjuk ke file berisi sertifikat X.509.
|
||||
Sertifikat harus dikodekan dalam format DER atau PEM. Dalam hal sertifikat
|
||||
PEM, file <em>tidak boleh</em> berisi data tambahan non-PEM seperti
|
||||
komentar.
|
||||
</li>
|
||||
|
||||
<li>{@code "system"} untuk sertifikat CA sistem yang telah terpasang.
|
||||
</li>
|
||||
|
||||
<li>{@code "user"} untuk sertifikat CA yang ditambahkan pengguna.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
|
||||
<dt>{@code overridePins}</dt>
|
||||
<dd>
|
||||
<p>
|
||||
Menetapkan apakah CA dari sumber akan mengabaikan penyematan sertifikat. Jika {@code
|
||||
"true"} kemudian rangkaian sertifikat melalui salah satu CA dari
|
||||
sumber ini maka tidak dilakukan penyematan. Hal ini bisa berguna untuk debug CA
|
||||
atau untuk mendukung dengan memungkinkan pengguna melakukan MiTM atas lalu lintas aman aplikasi Anda.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Default-nya adalah {@code "false"} kecuali jika ditetapkan dalam elemen {@code debug-overrides},
|
||||
dalam hal demikian default-nya adalah {@code "true"}.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
|
||||
<h3 id="pin-set"><pin-set></h3>
|
||||
|
||||
<dl class="xml">
|
||||
<dt>
|
||||
sintaks:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
<pre class="stx">
|
||||
<pin-set expiration="date">
|
||||
...
|
||||
</pin-set>
|
||||
</pre>
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
Bisa Berisi:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Sejumlah <code><a href="#pin"><pin></a></code>
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
Keterangan:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Satu set pin kunci publik. Agar koneksi aman bisa dipercaya, salah satu
|
||||
kunci publik dalam rantai kepercayaan harus berada dalam set pin. Lihat
|
||||
<code><a href="#pin"><pin></a></code> untuk mengetahui format pin.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
Atribut:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
<dl class="attr">
|
||||
<dt>
|
||||
{@code expiration}
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Tanggal, dalam format {@code yyyy-MM-dd}, pada saat dan setelah pin
|
||||
kedaluwarsa, sehingga menonaktifkan penyematan. Jika atribut tidak disetel maka
|
||||
pin tidak kedaluwarsa.
|
||||
<p>
|
||||
Tanggal kedaluwarsa membantu mencegah masalah konektivitas di aplikasi yang
|
||||
tidak mengambil pembaruan untuk set pin mereka, misalnya karena pengguna
|
||||
menonaktifkan pembaruan aplikasi.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3 id="pin"><pin></h3>
|
||||
<dl class="xml">
|
||||
<dt>
|
||||
sintaks:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
<pre class="stx">
|
||||
<pin digest=["SHA-256"]>base64 encoded digest of X.509
|
||||
SubjectPublicKeyInfo (SPKI)</pin>
|
||||
</pre>
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
Atribut:
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
<dl class="attr">
|
||||
<dt>
|
||||
{@code digest}
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Algoritme intisari yang digunakan untuk menghasilkan pin. Saat ini, hanya
|
||||
{@code "SHA-256"} yang didukung.
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
234
docs/html-intl/intl/id/training/basics/network-ops/data-saver.jd
Normal file
234
docs/html-intl/intl/id/training/basics/network-ops/data-saver.jd
Normal file
@@ -0,0 +1,234 @@
|
||||
page.title=Data Saver
|
||||
metaDescription=Optimalisasi penggunaan data yang diaktifkan pengguna.
|
||||
page.keywords="android N", "data usage", "metered network"
|
||||
page.image=images/cards/card-nyc_2x.jpg
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>
|
||||
Dalam dokumen ini
|
||||
</h2>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<a href="#status">Memeriksa Preferensi Data Saver</a>
|
||||
<ol>
|
||||
<li>
|
||||
<a href="#request-whitelist">Meminta izin daftar putih</a>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#monitor-changes">Memantau Perubahan pada Preferensi
|
||||
Data Saver</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#testing">Menguji dengan Perintah Android Debug Bridge</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Selama penggunaan ponsel cerdas, biaya paket data seluler bisa saja
|
||||
melebihi harga perangkat itu sendiri. Di N Developer Preview, pengguna bisa
|
||||
mengaktifkan Data Saver berdasarkan lingkup perangkat untuk menghemat data, baik saat
|
||||
roaming, mendekati akhir siklus penagihan, atau pada paket data prabayar kecil.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Bila pengguna mengaktifkan Data Saver di <strong>Settings</strong> dan perangkat
|
||||
berada dalam jaringan berkuota, sistem akan memblokir penggunaan data latar belakang dan memberi tahu
|
||||
aplikasi untuk menghemat penggunaan data latar depan bila memungkinkan. Pengguna bisa
|
||||
memasukkan aplikasi tertentu ke daftar putih untuk memungkinkan penggunaan data berkuota bila Data
|
||||
Saver diaktifkan.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
N Developer Preview memperluas {@link android.net.ConnectivityManager}
|
||||
API untuk menyediakan cara pada aplikasi untuk <a href="#status">menerima preferensi Data Saver
|
||||
pengguna</a> dan <a href="#monitor-changes">memantau perubahan
|
||||
preferensi</a>. Hal ini dianggap praktik terbaik bagi aplikasi untuk memeriksa apakah
|
||||
pengguna telah mengaktifkan DataSaver dan berusaha membatasi penggunaan data latar depan dan
|
||||
data latar belakang.
|
||||
</p>
|
||||
|
||||
<h2 id="status">
|
||||
Memeriksa Preferensi Data Saver
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Di N Developer Preview, aplikasi bisa menggunakan {@link
|
||||
android.net.ConnectivityManager} API untuk menentukan pembatasan penggunaan data
|
||||
apa yang sedang diterapkan. Metode {@code getRestrictBackgroundStatus()}
|
||||
akan mengembalikan salah satu dari nilai berikut:
|
||||
</p>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
{@code RESTRICT_BACKGROUND_STATUS_DISABLED}
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Data Saver dinonaktifkan.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
{@code RESTRICT_BACKGROUND_STATUS_ENABLED}
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Pengguna telah mengaktifkan Data Saver untuk aplikasi ini. Aplikasi harus berusaha membatasi
|
||||
penggunaan data di latar depan dan dengan halus menangani pembatasan penggunaan
|
||||
data latar belakang.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
{@code RESTRICT_BACKGROUND_STATUS_WHITELISTED}
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Pengguna telah mengaktifkan Data Saver namun aplikasi telah dimasukkan dalam daftar putih. Aplikasi harus
|
||||
tetap berusaha membatasi penggunaan data latar belakang dan latar depan.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
Hal ini dianggap praktik terbaik untuk membatasi penggunaan data bila perangkat
|
||||
terhubung ke jaringan berkuota, meskipun Data Saver telah dinonaktifkan atau aplikasi
|
||||
telah dimasukkan dalam daftar putih. Kode contoh berikut menggunakan {@link
|
||||
android.net.ConnectivityManager#isActiveNetworkMetered
|
||||
ConnectivityManager.isActiveNetworkMetered()} dan {@code
|
||||
ConnectivityManager.getRestrictBackgroundStatus()} untuk menentukan berapa banyak data
|
||||
yang harus digunakan aplikasi:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
ConnectivityManager connMgr = (ConnectivityManager)
|
||||
getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
// Checks if the device is on a metered network
|
||||
if (connMgr.isActiveNetworkMetered()) {
|
||||
// Checks user’s Data Saver settings.
|
||||
switch (connMgr.getRestrictBackgroundStatus()) {
|
||||
case RESTRICT_BACKGROUND_STATUS_ENABLED:
|
||||
// Background data usage is blocked for this app. Wherever possible,
|
||||
// the app should also use less data in the foreground.
|
||||
|
||||
case RESTRICT_BACKGROUND_STATUS_WHITELISTED:
|
||||
// The app is whitelisted. Wherever possible,
|
||||
// the app should use less data in the foreground and background.
|
||||
|
||||
case RESTRICT_BACKGROUND_STATUS_DISABLED:
|
||||
// Data Saver is disabled. Since the device is connected to a
|
||||
// metered network, the app should use less data wherever possible.
|
||||
}
|
||||
} else {
|
||||
// The device is not on a metered network.
|
||||
// Use data as required to perform syncs, downloads, and updates.
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3 id="request-whitelist">
|
||||
Meminta izin daftar putih
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
Jika aplikasi Anda perlu menggunakan data di latar belakang, aplikasi bisa meminta izin
|
||||
daftar putih dengan mengirim
|
||||
<code>Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS</code>
|
||||
yang mengandung URI dari nama paket aplikasi Anda: misalnya,
|
||||
<code>package:MY_APP_ID</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Mengirim intent dan URI akan membuka aplikasi <strong>Settings</strong> dan
|
||||
menampilkan setelan penggunaan data untuk aplikasi Anda. Pengguna nanti bisa memutuskan apakah akan
|
||||
mengaktifkan data latar belakang untuk aplikasi Anda. Sebelum Anda mengirim intent ini, sebaiknya
|
||||
tanyakan kepada pengguna terlebih dahulu apakah mereka ingin membuka aplikasi
|
||||
<strong>Settings</strong> untuk keperluan mengaktifkan penggunaan
|
||||
data latar belakang.
|
||||
</p>
|
||||
|
||||
<h2 id="monitor-changes">
|
||||
Memantau Perubahan pada Preferensi Data Saver
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Aplikasi bisa memantau perubahan pada preferensi Data Saver dengan membuat {@link
|
||||
android.content.BroadcastReceiver} untuk memantau {@code
|
||||
ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED} dan secara dinamis
|
||||
mendaftarkan penerima pada {@link android.content.Context#registerReceiver
|
||||
Context.registerReceiver()}. Bila menerima siaran ini, aplikasi harus
|
||||
<a href="#status">memeriksa apakah preferensi Data Saver baru memengaruhi
|
||||
izinnya</a> dengan memanggil {@code
|
||||
ConnectivityManager.getRestrictBackgroundStatus()}.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Sistem hanya mengirim siaran ini ke aplikasi yang
|
||||
secara dinamis mendaftar padanya dengan {@link
|
||||
android.content.Context#registerReceiver Context.registerReceiver()}. Aplikasi
|
||||
yang mendaftar untuk menerima siaran ini dalam manifes mereka
|
||||
tidak akan menerimanya.
|
||||
</p>
|
||||
|
||||
<h2 id="testing">
|
||||
Menguji dengan Perintah Android Debug Bridge
|
||||
</h2>
|
||||
|
||||
<a href="{@docRoot}tools/help/adb.html">Android Debug Bridge (ADB)</a>
|
||||
menyediakan beberapa perintah yang bisa Anda gunakan untuk memeriksa dan
|
||||
mengonfigurasi izin jaringan:
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<code>$ adb shell dumpsys netpolicy</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Menghasilkan laporan berisi setelan pembatasan jaringan latar belakang
|
||||
global saat ini, UID paket saat ini di daftar putih, dan izin jaringan
|
||||
untuk paket yang diketahui lainnya.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>$ adb shell cmd netpolicy</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Menampilkan daftar lengkap dari perintah Network Policy Manager (netpolicy).
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>$ adb shell cmd netpolicy set restrict-background
|
||||
<boolean></code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Mengaktifkan atau menonaktifkan mode Data Saver saat meneruskan <code>true</code> atau
|
||||
<code>false</code>, masing-masing.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>$ adb shell cmd netpolicy add restrict-background-whitelist
|
||||
<UID></code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Menambahkan UID paket tertentu ke daftar putih untuk mengizinkan penggunaan data berkuota
|
||||
di latar belakang.
|
||||
</dd>
|
||||
|
||||
<dt>
|
||||
<code>$ adb shell cmd netpolicy remove restrict-background-whitelist
|
||||
<UID></code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
Membuang UID paket tertentu dari daftar putih untuk memblokir
|
||||
penggunaan data berkuota di latar belakang saat Data Saver diaktifkan.
|
||||
</dd>
|
||||
</dl>
|
||||
550
docs/html-intl/intl/id/training/material/animations.jd
Normal file
550
docs/html-intl/intl/id/training/material/animations.jd
Normal file
@@ -0,0 +1,550 @@
|
||||
page.title=Mendefinisikan Animasi Custom
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Pelajaran ini mengajarkan Anda cara</h2>
|
||||
<ol>
|
||||
<li><a href="#Touch">Menyesuaikan Umpan Balik Sentuh</a></li>
|
||||
<li><a href="#Reveal">Menggunakan Reveal Effect</a></li>
|
||||
<li><a href="#Transitions">Menyesuaikan Transisi Aktivitas</a></li>
|
||||
<li><a href="#ViewState">Menganimasikan Perubahan Status Tampilan</a></li>
|
||||
<li><a href="#AnimVector">Menganimasikan Drawable Vektor</a></li>
|
||||
</ol>
|
||||
<h2>Anda juga harus membaca</h2>
|
||||
<ul>
|
||||
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
|
||||
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Animasi dalam desain bahan memberi pengguna umpan balik tentang tindakannya dan menyediakan
|
||||
kesinambungan visual saat pengguna berinteraksi dengan aplikasi Anda. Tema bahan menyediakan beberapa animasi default
|
||||
untuk tombol dan transisi aktivitas, dan Android 5.0 (API level 21) ke atas memungkinkan Anda menyesuaikan
|
||||
animasi ini dan membuat yang baru:</p>
|
||||
|
||||
<ul>
|
||||
<li>Umpan balik sentuh</li>
|
||||
<li>Singkap Melingkar</li>
|
||||
<li>Transisi aktivitas</li>
|
||||
<li>Gerakan melengkung</li>
|
||||
<li>Perubahan status tampilan</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2 id="Touch">Menyesuaikan Umpan Balik Sentuh</h2>
|
||||
|
||||
<p>Umpan balik sentuh dalam desain bahan menyediakan konfirmasi visual seketika pada
|
||||
titik kontak bila pengguna berinteraksi dengan elemen UI. Animasi umpan balik sentuh default
|
||||
untuk tombol menggunakan kelas {@link android.graphics.drawable.RippleDrawable} baru, yang bertransisi
|
||||
di antara berbagai status dengan efek riak.</p>
|
||||
|
||||
<p>Di sebagian besar kasus, Anda harus menerapkan fungsionalitas ini dalam XML tampilan dengan menetapkan
|
||||
latar belakang tampilan sebagai:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>?android:attr/selectableItemBackground</code> untuk riak berbatas.</li>
|
||||
<li><code>?android:attr/selectableItemBackgroundBorderless</code> untuk riak yang meluas ke luar
|
||||
tampilan. Latar belakang ini akan digambar di atas, dan dibatasi oleh, induk tampilan terdekat dengan
|
||||
latar belakang non-null.</li>
|
||||
</ul>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> <code>selectableItemBackgroundBorderless</code> adalah
|
||||
atribut baru yang diperkenalkan di API level 21.</p>
|
||||
|
||||
|
||||
<p>Atau, Anda bisa mendefinisikan {@link android.graphics.drawable.RippleDrawable}
|
||||
sebagai sumber daya XML dengan menggunakan elemen <code>ripple</code>.</p>
|
||||
|
||||
<p>Anda bisa menetapkan warna ke objek-objek {@link android.graphics.drawable.RippleDrawable}. Untuk mengubah
|
||||
warna default umpan balik sentuh, gunakan atribut <code>android:colorControlHighlight</code>
|
||||
tema.</p>
|
||||
|
||||
<p>Untuk informasi selengkapnya, lihat referensi API bagi kelas {@link
|
||||
android.graphics.drawable.RippleDrawable}.</p>
|
||||
|
||||
|
||||
<h2 id="Reveal">Menggunakan Reveal Effect</h2>
|
||||
|
||||
<p>Animasi singkap memberi pengguna kesinambungan visual saat menampilkan atau menyembunyikan sekelompok
|
||||
elemen UI. Metode {@link android.view.ViewAnimationUtils#createCircularReveal
|
||||
ViewAnimationUtils.createCircularReveal()} memungkinkan Anda menganimasikan lingkaran terpangkas
|
||||
untuk memperlihatkan atau menyembunyikan tampilan.</p>
|
||||
|
||||
<p>Untuk memperlihatkan tampilan yang sebelumnya tidak terlihat dengan menggunakan efek ini:</p>
|
||||
|
||||
<pre>
|
||||
// previously invisible view
|
||||
View myView = findViewById(R.id.my_view);
|
||||
|
||||
// get the center for the clipping circle
|
||||
int cx = (myView.getLeft() + myView.getRight()) / 2;
|
||||
int cy = (myView.getTop() + myView.getBottom()) / 2;
|
||||
|
||||
// get the final radius for the clipping circle
|
||||
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
|
||||
|
||||
// create the animator for this view (the start radius is zero)
|
||||
Animator anim =
|
||||
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
|
||||
|
||||
// make the view visible and start the animation
|
||||
myView.setVisibility(View.VISIBLE);
|
||||
anim.start();
|
||||
</pre>
|
||||
|
||||
<p>Untuk menyembunyikan sebuah tampilan yang sebelumnya terlihat dengan menggunakan efek ini:</p>
|
||||
|
||||
<pre>
|
||||
// previously visible view
|
||||
final View myView = findViewById(R.id.my_view);
|
||||
|
||||
// get the center for the clipping circle
|
||||
int cx = (myView.getLeft() + myView.getRight()) / 2;
|
||||
int cy = (myView.getTop() + myView.getBottom()) / 2;
|
||||
|
||||
// get the initial radius for the clipping circle
|
||||
int initialRadius = myView.getWidth();
|
||||
|
||||
// create the animation (the final radius is zero)
|
||||
Animator anim =
|
||||
ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);
|
||||
|
||||
// make the view invisible when the animation is done
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
myView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
// start the animation
|
||||
anim.start();
|
||||
</pre>
|
||||
|
||||
|
||||
<h2 id="Transitions">Menyesuaikan Transisi Aktivitas</h2>
|
||||
|
||||
<!-- shared transition video -->
|
||||
<div style="width:290px;margin-left:35px;float:right">
|
||||
<div class="framed-nexus5-port-span-5">
|
||||
<video class="play-on-hover" autoplay="">
|
||||
<source src="{@docRoot}design/material/videos/ContactsAnim.mp4">
|
||||
<source src="{@docRoot}design/material/videos/ContactsAnim.webm">
|
||||
<source src="{@docRoot}design/material/videos/ContactsAnim.ogv">
|
||||
</video>
|
||||
</div>
|
||||
<div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
|
||||
<p class="img-caption" style="margin-top:3px;margin-bottom:10px"><strong>Gambar 1</strong> - Transisi
|
||||
dengan elemen bersama.</p>
|
||||
<em>Untuk memutar ulang film, klik layar perangkat</em>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Transisi aktivitas dalam aplikasi desain bahan memberikan koneksi visual antar berbagai status
|
||||
melalui gerakan dan transformasi di antara elemen umum. Anda bisa menetapkan animasi custom untuk
|
||||
masuk ke dan keluar dari transisi dan untuk transisi elemen bersama di antara aktivitas.</p>
|
||||
|
||||
<ul>
|
||||
<li>Transisi <strong>masuk</strong> menentukan cara tampilan di aktivitas memasuki suatu babak.
|
||||
misalnya, dalam transisi masuk <em>explode</em>, tampilan memasuki babak dari sisi luar
|
||||
dan melayang masuk ke arah tengah layar.</li>
|
||||
|
||||
<li>Transisi <strong>keluar</strong> menentukan cara tampilan di aktivitas keluar dari suatu babak. Misalnya
|
||||
, dalam transisi keluar <em>explode</em>, tampilan akan keluar dari babak dari bagian
|
||||
tengahnya.</li>
|
||||
|
||||
<li>Transisi <strong>elemen bersama</strong> menentukan cara menggunakan bersama suatu tampilan
|
||||
oleh dua transisi aktivitas di antara aktivitas-aktivitas ini. Misalnya, jika dua aktivitas memiliki
|
||||
gambar yang sama dengan posisi dan ukuran berbeda, transisi elemen bersama <em>changeImageTransform</em>
|
||||
mentransformasikan dan menskalakan gambar secara mulus di antara aktivitas-aktivitas ini.</li>
|
||||
</ul>
|
||||
|
||||
<p>Android 5.0 (API level 21) mendukung transisi masuk dan transisi keluar ini:</p>
|
||||
|
||||
<ul>
|
||||
<li><em>explode</em> - Memindahkan tampilan masuk ke atau keluar dari tengah babak.</li>
|
||||
<li><em>slide</em> - Memindahkan tampilan masuk ke atau keluar dari salah satu tepi babak.</li>
|
||||
<li><em>fade</em> - Menambahkan atau menghapus tampilan dari babak dengan mengubah opasitasnya.</li>
|
||||
</ul>
|
||||
|
||||
<p>Transisi apa pun yang memperluas kelas {@link android.transition.Visibility} didukung
|
||||
sebagai transisi masuk atau transisi keluar. Untuk informasi selengkapnya, lihat referensi API untuk kelas
|
||||
{@link android.transition.Transition}.</p>
|
||||
|
||||
<p>Android 5.0 (API level 21) juga mendukung transisi elemen bersama ini:</p>
|
||||
|
||||
<ul>
|
||||
<li><em>changeBounds</em> - Menganimasikan perubahan pada batas-batas layout tampilan target.</li>
|
||||
<li><em>changeClipBounds</em> - Menganimasikan perubahan pada batas-batas pemangkasan tampilan target.</li>
|
||||
<li><em>changeTransform</em> - Menganimasikan perubahan pada skala dan rotasi tampilan target.</li>
|
||||
<li><em>changeImageTransform</em> - Menganimasikan perubahan pada ukuran dan skala gambar target.</li>
|
||||
</ul>
|
||||
|
||||
<p>Bila Anda mengaktifkan transisi aktivitas dalam aplikasi, transisi memudar-silang default akan
|
||||
diaktifkan di antara aktivitas masuk dan aktivitas keluar.</p>
|
||||
|
||||
<img src="{@docRoot}training/material/images/SceneTransition.png" alt="" width="600" height="405" style="margin-top:20px" />
|
||||
<p class="img-caption">
|
||||
<strong>Gambar 2</strong> - Transisi babak dengan satu elemen bersama.
|
||||
</p>
|
||||
|
||||
<h3>Menetapkan transisi custom</h3>
|
||||
|
||||
<p>Pertama, aktifkan transisi konten jendela dengan atribut <code>android:windowContentTransitions</code>
|
||||
bila Anda mendefinisikan gaya yang mewarisi tema bahan. Anda juga bisa menetapkan
|
||||
transisi-transisi masuk, keluar, dan elemen bersama dalam definisi gaya:</p>
|
||||
|
||||
<pre>
|
||||
<style name="BaseAppTheme" parent="android:Theme.Material">
|
||||
<!-- enable window content transitions -->
|
||||
<item name="android:windowContentTransitions">true</item>
|
||||
|
||||
<!-- specify enter and exit transitions -->
|
||||
<item name="android:windowEnterTransition">@transition/explode</item>
|
||||
<item name="android:windowExitTransition">@transition/explode</item>
|
||||
|
||||
<!-- specify shared element transitions -->
|
||||
<item name="android:windowSharedElementEnterTransition">
|
||||
@transition/change_image_transform</item>
|
||||
<item name="android:windowSharedElementExitTransition">
|
||||
@transition/change_image_transform</item>
|
||||
</style>
|
||||
</pre>
|
||||
|
||||
<p>Transisi <code>change_image_transform</code> dalam contoh ini didefinisikan sebagai berikut:</p>
|
||||
|
||||
<pre>
|
||||
<!-- res/transition/change_image_transform.xml -->
|
||||
<!-- (see also Shared Transitions below) -->
|
||||
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<changeImageTransform/>
|
||||
</transitionSet>
|
||||
</pre>
|
||||
|
||||
<p>Elemen <code>changeImageTransform</code> menunjukkan
|
||||
kelas {@link android.transition.ChangeImageTransform}. Untuk informasi selengkapnya, lihat referensi
|
||||
API untuk {@link android.transition.Transition}.</p>
|
||||
|
||||
<p>Sebaliknya, untuk mengaktifkan transisi konten jendela dalam kode Anda, panggil
|
||||
metode {@link android.view.Window#requestFeature Window.requestFeature()}:</p>
|
||||
|
||||
<pre>
|
||||
// inside your activity (if you did not enable transitions in your theme)
|
||||
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
|
||||
|
||||
// set an exit transition
|
||||
getWindow().setExitTransition(new Explode());
|
||||
</pre>
|
||||
|
||||
<p>Untuk menetapkan transisi dalam kode Anda, panggil metode-metode ini dengan objek {@link
|
||||
android.transition.Transition}:</p>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.view.Window#setEnterTransition Window.setEnterTransition()}</li>
|
||||
<li>{@link android.view.Window#setExitTransition Window.setExitTransition()}</li>
|
||||
<li>{@link android.view.Window#setSharedElementEnterTransition
|
||||
Window.setSharedElementEnterTransition()}</li>
|
||||
<li>{@link android.view.Window#setSharedElementExitTransition
|
||||
Window.setSharedElementExitTransition()}</li>
|
||||
</ul>
|
||||
|
||||
<p>Metode {@link android.view.Window#setExitTransition setExitTransition()} dan {@link
|
||||
android.view.Window#setSharedElementExitTransition setSharedElementExitTransition()} mendefinisikan
|
||||
transisi keluar untuk aktivitas yang memanggil. Metode {@link android.view.Window#setEnterTransition
|
||||
setEnterTransition()} dan {@link android.view.Window#setSharedElementEnterTransition
|
||||
setSharedElementEnterTransition()} mendefinisikan transisi masuk untuk aktivitas yang dipanggil.</p>
|
||||
|
||||
<p>Untuk mendapatkan efek penuh sebuah transisi, Anda harus mengaktifkan transisi konten jendela pada
|
||||
aktivitas yang memanggil maupun aktivitas yang dipanggil. Jika tidak, aktivitas yang memanggil akan memulai transisi keluar,
|
||||
namun kemudian Anda akan melihat transisi jendela (seperti mengelupas atau memudar).</p>
|
||||
|
||||
<p>Untuk memulai transisi masuk sesegera mungkin, gunakan metode
|
||||
{@link android.view.Window#setAllowEnterTransitionOverlap Window.setAllowEnterTransitionOverlap()}
|
||||
pada aktivitas yang dipanggil. Ini memungkinkan Anda mendapatkan transisi masuk yang lebih dramatis.</p>
|
||||
|
||||
<h3>Memulai aktivitas dengan menggunakan transisi</h3>
|
||||
|
||||
<p>Jika Anda mengaktifkan transisi dan mengatur transisi keluar untuk aktivitas, transisi itu akan diaktifkan
|
||||
bila Anda menjalankan aktivitas lain sebagai berikut:</p>
|
||||
|
||||
<pre>
|
||||
startActivity(intent,
|
||||
ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
|
||||
</pre>
|
||||
|
||||
<p>Jika Anda telah mengatur transisi masuk untuk aktivitas kedua, transisi juga akan diaktifkan
|
||||
bila aktivitas dimulai. Untuk menonaktifkan transisi bila Anda memulai aktivitas lain, sediakan
|
||||
bundel opsi <code>null</code>.</p>
|
||||
|
||||
<h3>Memulai aktivitas dengan satu elemen bersama</h3>
|
||||
|
||||
<p>Untuk membuat animasi transisi layar di antara dua aktivitas yang memiliki satu elemen bersama:</p>
|
||||
|
||||
<ol>
|
||||
<li>Aktifkan transisi konten jendela dalam tema Anda.</li>
|
||||
<li>Tetapkan transisi elemen bersama dalam gaya Anda.</li>
|
||||
<li>Definisikan transisi Anda sebagai sumber daya XML.</li>
|
||||
<li>Tetapkan nama umum pada elemen bersama dalam kedua layout dengan
|
||||
atribut <code>android:transitionName</code>.</li>
|
||||
<li>Gunakan metode {@link android.app.ActivityOptions#makeSceneTransitionAnimation
|
||||
ActivityOptions.makeSceneTransitionAnimation()}.</li>
|
||||
</ol>
|
||||
|
||||
<pre>
|
||||
// get the element that receives the click event
|
||||
final View imgContainerView = findViewById(R.id.img_container);
|
||||
|
||||
// get the common element for the transition in this activity
|
||||
final View androidRobotView = findViewById(R.id.image_small);
|
||||
|
||||
// define a click listener
|
||||
imgContainerView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent intent = new Intent(this, Activity2.class);
|
||||
// create the transition animation - the images in the layouts
|
||||
// of both activities are defined with android:transitionName="robot"
|
||||
ActivityOptions options = ActivityOptions
|
||||
.makeSceneTransitionAnimation(this, androidRobotView, "robot");
|
||||
// start the new activity
|
||||
startActivity(intent, options.toBundle());
|
||||
}
|
||||
});
|
||||
</pre>
|
||||
|
||||
<p>Untuk tampilan dinamis bersama yang Anda hasilkan dalam kode, gunakan
|
||||
metode {@link android.view.View#setTransitionName View.setTransitionName()} untuk menetapkan
|
||||
nama elemen umum di kedua aktivitas.</p>
|
||||
|
||||
<p>Untuk membalik animasi transisi babak bila Anda menyelesaikan aktivitas kedua, panggil metode
|
||||
{@link android.app.Activity#finishAfterTransition Activity.finishAfterTransition()}
|
||||
sebagai ganti {@link android.app.Activity#finish Activity.finish()}.</p>
|
||||
|
||||
<h3>Memulai aktivitas dengan beberapa elemen bersama</h3>
|
||||
|
||||
<p>Untuk membuat animasi transisi babak antara dua aktivitas yang memiliki lebih dari satu
|
||||
elemen bersama, definisikan elemen bersama di kedua layout dengan atribut <code>android:transitionName</code>
|
||||
(atau gunakan metode {@link android.view.View#setTransitionName View.setTransitionName()}
|
||||
di kedua aktivitas), dan buat sebuah objek {@link android.app.ActivityOptions} sebagai berikut:</p>
|
||||
|
||||
<pre>
|
||||
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
|
||||
Pair.create(view1, "agreedName1"),
|
||||
Pair.create(view2, "agreedName2"));
|
||||
</pre>
|
||||
|
||||
|
||||
<h2 id="CurvedMotion">Menggunakan Gerakan Melengkung</h2>
|
||||
|
||||
<p>Animasi dalam desain bahan mengandalkan kurva untuk pola interpolasi waktu dan
|
||||
gerakan spasial. Dengan Android 5.0 (API level 21) ke atas, Anda bisa mendefinisikan kurva pewaktuan custom dan
|
||||
pola gerakan melengkung untuk animasi.</p>
|
||||
|
||||
<p>Kelas {@link android.view.animation.PathInterpolator} adalah interpolator baru berdasarkan sebuah
|
||||
kurva Bézier atau objek {@link android.graphics.Path}. Interpolator ini menetapkan kurva gerakan
|
||||
dalam bujur sangkar 1x1, dengan titik-titik jangkar di (0,0) dan (1,1) dan titik-titik kontrol sebagaimana ditetapkan menggunakan
|
||||
argumen konstruktor. Anda juga bisa mendefinisikan interpolator path sebagai sumber daya XML:</p>
|
||||
|
||||
<pre>
|
||||
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:controlX1="0.4"
|
||||
android:controlY1="0"
|
||||
android:controlX2="1"
|
||||
android:controlY2="1"/>
|
||||
</pre>
|
||||
|
||||
<p>Sistem menyediakan sumber daya XML untuk tiga kurva dasar dalam
|
||||
spesifikasi desain bahan:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>@interpolator/fast_out_linear_in.xml</code></li>
|
||||
<li><code>@interpolator/fast_out_slow_in.xml</code></li>
|
||||
<li><code>@interpolator/linear_out_slow_in.xml</code></li>
|
||||
</ul>
|
||||
|
||||
<p>Anda bisa meneruskan objek {@link android.view.animation.PathInterpolator} ke metode {@link
|
||||
android.animation.Animator#setInterpolator Animator.setInterpolator()}.</p>
|
||||
|
||||
<p>Kelas {@link android.animation.ObjectAnimator} memiliki konstruktor-konstruktor baru yang memungkinkan Anda menganimasikan
|
||||
koordinat bersama sebuah path dengan menggunakan dua atau beberapa properti sekaligus. Misalnya, animator berikut
|
||||
menggunakan objek {@link android.graphics.Path} untuk menganimasikan properti X dan Y sebuah tampilan:</p>
|
||||
|
||||
<pre>
|
||||
ObjectAnimator mAnimator;
|
||||
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
|
||||
...
|
||||
mAnimator.start();
|
||||
</pre>
|
||||
|
||||
|
||||
<h2 id="ViewState">Menganimasikan Perubahan Status Tampilan</h2>
|
||||
|
||||
<p>Kelas {@link android.animation.StateListAnimator} memungkinkan Anda mendefinisikan animator yang berjalan bila
|
||||
status tampilan berubah. Contoh berikut menampilkan cara mendefinisikan {@link
|
||||
android.animation.StateListAnimator} sebagai sumber daya XML:</p>
|
||||
|
||||
<pre>
|
||||
<!-- animate the translationZ property of a view when pressed -->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true">
|
||||
<set>
|
||||
<objectAnimator android:propertyName="translationZ"
|
||||
android:duration="@android:integer/config_shortAnimTime"
|
||||
android:valueTo="2dp"
|
||||
android:valueType="floatType"/>
|
||||
<!-- you could have other objectAnimator elements
|
||||
here for "x" and "y", or other properties -->
|
||||
</set>
|
||||
</item>
|
||||
<item android:state_enabled="true"
|
||||
android:state_pressed="false"
|
||||
android:state_focused="true">
|
||||
<set>
|
||||
<objectAnimator android:propertyName="translationZ"
|
||||
android:duration="100"
|
||||
android:valueTo="0"
|
||||
android:valueType="floatType"/>
|
||||
</set>
|
||||
</item>
|
||||
</selector>
|
||||
</pre>
|
||||
|
||||
<p>Untuk menyertakan animasi status tampilan custom ke tampilan, definisikan animator menggunakan
|
||||
elemen <code>selector</code> dalam sumber daya file XML sebagaimana dalam contoh ini, dan tetapkan ke
|
||||
tampilan Anda dengan atribut <code>android:stateListAnimator</code>. Untuk menetapkan animator daftar status
|
||||
ke sebuah tampilan dalam kode Anda, gunakan metode {@link android.animation.AnimatorInflater#loadStateListAnimator
|
||||
AnimationInflater.loadStateListAnimator()}, dan tetapkan animator ke tampilan dengan
|
||||
metode {@link android.view.View#setStateListAnimator View.setStateListAnimator()}.</p>
|
||||
|
||||
<p>Bila tema Anda memperluas tema bahan, tombol-tombol akan memiliki animasi Z secara default. Untuk menghindari
|
||||
perilaku ini di tombol Anda, aturlah atribut <code>android:stateListAnimator</code> ke
|
||||
<code>@null</code>.</p>
|
||||
|
||||
<p>Kelas {@link android.graphics.drawable.AnimatedStateListDrawable} memungkinkan Anda membuat drawable
|
||||
yang menampilkan animasi di antara perubahan status tampilan terkait. Sebagian widget sistem di
|
||||
Android 5.0 menggunakan animasi ini secara default. Contoh berikut menampilkan cara
|
||||
mendefinisikan {@link android.graphics.drawable.AnimatedStateListDrawable} sebagai sumber daya XML:</p>
|
||||
|
||||
<pre>
|
||||
<!-- res/drawable/myanimstatedrawable.xml -->
|
||||
<animated-selector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- provide a different drawable for each state-->
|
||||
<item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
|
||||
android:state_pressed="true"/>
|
||||
<item android:id="@+id/focused" android:drawable="@drawable/drawableF"
|
||||
android:state_focused="true"/>
|
||||
<item android:id="@id/default"
|
||||
android:drawable="@drawable/drawableD"/>
|
||||
|
||||
<!-- specify a transition -->
|
||||
<transition android:fromId="@+id/default" android:toId="@+id/pressed">
|
||||
<animation-list>
|
||||
<item android:duration="15" android:drawable="@drawable/dt1"/>
|
||||
<item android:duration="15" android:drawable="@drawable/dt2"/>
|
||||
...
|
||||
</animation-list>
|
||||
</transition>
|
||||
...
|
||||
</animated-selector>
|
||||
</pre>
|
||||
|
||||
|
||||
<h2 id="AnimVector">Menganimasikan Drawable Vektor</h2>
|
||||
|
||||
<p><a href="{@docRoot}training/material/drawables.html#VectorDrawables">Drawable Vektor </a>
|
||||
bisa diubah skalanya tanpa kehilangan definisi. Kelas {@link android.graphics.drawable.AnimatedVectorDrawable}
|
||||
memungkinkan Anda menganimasikan properti drawable vektor.</p>
|
||||
|
||||
<p>Anda biasanya mendefinisikan drawable vektor yang dianimasikan dalam tiga file XML:</p>
|
||||
|
||||
<ul>
|
||||
<li>Drawable vektor dengan elemen <code><vector></code> dalam
|
||||
<code>res/drawable/</code></li>
|
||||
<li>Drawable vektor animasi dengan elemen <code><animated-vector></code> dalam
|
||||
<code>res/drawable/</code></li>
|
||||
<li>Satu atau beberapa animator objek dengan elemen <code><objectAnimator></code> dalam
|
||||
<code>res/anim/</code></li>
|
||||
</ul>
|
||||
|
||||
<p>Drawable vektor yang dianimasikan bisa menganimasikan atribut elemen <code><group></code> dan
|
||||
<code><path></code>. Elemen <code><group></code> mendefinisikan satu set
|
||||
path atau subgrup, dan elemen <code><path></code> mendefinisikan path yang harus digambar.</p>
|
||||
|
||||
<p>Bila Anda mendefinisikan drawable vektor yang ingin dianimasikan, gunakan atribut <code>android:name</code>
|
||||
untuk menetapkan nama unik ke grup dan path, sehingga Anda bisa merujuknya dari
|
||||
definisi animator Anda. Misalnya:</p>
|
||||
|
||||
<pre>
|
||||
<!-- res/drawable/vectordrawable.xml -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="64dp"
|
||||
android:width="64dp"
|
||||
android:viewportHeight="600"
|
||||
android:viewportWidth="600">
|
||||
<group
|
||||
<strong>android:name="rotationGroup"</strong>
|
||||
android:pivotX="300.0"
|
||||
android:pivotY="300.0"
|
||||
android:rotation="45.0" >
|
||||
<path
|
||||
<strong>android:name="v"</strong>
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
|
||||
</group>
|
||||
</vector>
|
||||
</pre>
|
||||
|
||||
<p>Definisi drawable vektor yang dianimasikan merujuk pada grup dan path dalam drawable vektor
|
||||
berdasarkan namanya:</p>
|
||||
|
||||
<pre>
|
||||
<!-- res/drawable/animvectordrawable.xml -->
|
||||
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/vectordrawable" >
|
||||
<target
|
||||
android:name="rotationGroup"
|
||||
android:animation="@anim/rotation" />
|
||||
<target
|
||||
android:name="v"
|
||||
android:animation="@anim/path_morph" />
|
||||
</animated-vector>
|
||||
</pre>
|
||||
|
||||
<p>Definisi animasi menyatakan objek {@link android.animation.ObjectAnimator} atau {@link
|
||||
android.animation.AnimatorSet}. Animator pertama dalam contoh ini memutar
|
||||
grup target sebanyak 360 derajat:</p>
|
||||
|
||||
<pre>
|
||||
<!-- res/anim/rotation.xml -->
|
||||
<objectAnimator
|
||||
android:duration="6000"
|
||||
android:propertyName="rotation"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="360" />
|
||||
</pre>
|
||||
|
||||
<p>Animator kedua dalam contoh ini perlahan-lahan mengubah bentuk path drawable vektor dari satu bentuk ke
|
||||
bentuk yang lain. Kedua path harus kompatibel untuk morphing: keduanya harus memiliki jumlah perintah yang sama
|
||||
dan jumlah parameter yang sama untuk setiap perintah.</p>
|
||||
|
||||
<pre>
|
||||
<!-- res/anim/path_morph.xml -->
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<objectAnimator
|
||||
android:duration="3000"
|
||||
android:propertyName="pathData"
|
||||
android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
|
||||
android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z"
|
||||
android:valueType="pathType" />
|
||||
</set>
|
||||
</pre>
|
||||
|
||||
<p>Untuk informasi selengkapnya, lihat referensi API bagi {@link
|
||||
android.graphics.drawable.AnimatedVectorDrawable}.</p>
|
||||
168
docs/html-intl/intl/id/training/material/compatibility.jd
Normal file
168
docs/html-intl/intl/id/training/material/compatibility.jd
Normal file
@@ -0,0 +1,168 @@
|
||||
page.title=Mempertahankan Kompatibilitas
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Pelajaran ini mengajarkan Anda cara</h2>
|
||||
<ol>
|
||||
<li><a href="#Theme">Mendefinisikan Gaya Alternatif</a></li>
|
||||
<li><a href="#Layouts">Menyediakan Layout Alternatif</a></li>
|
||||
<li><a href="#SupportLib">Menggunakan Support Library</a></li>
|
||||
<li><a href="#CheckVersion">Memeriksa Versi Sistem</a></li>
|
||||
</ol>
|
||||
<h2>Anda juga harus membaca</h2>
|
||||
<ul>
|
||||
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
|
||||
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Sebagian fitur desain bahan seperti tema bahan dan transisi aktivitas custom
|
||||
hanya tersedia pada Android 5.0 (API level 21) ke atas. Akan tetapi, Anda bisa mendesain aplikasi untuk menggunakan
|
||||
fitur-fitur ini saat dijalankan pada perangkat yang mendukung desain bahan dan tetap kompatibel
|
||||
dengan perangkat yang menjalankan rilis Android sebelumnya.</p>
|
||||
|
||||
|
||||
<h2 id="Theme">Mendefinisikan Gaya Alternatif</h2>
|
||||
|
||||
<p>Anda bisa mengonfigurasi aplikasi untuk menggunakan tema bahan pada perangkat yang mendukungnya dan mengembalikan
|
||||
ke tema lama pada perangkat yang menjalankan versi Android terdahulu:</p>
|
||||
|
||||
<ol>
|
||||
<li>Definisikan tema yang mewarisi tema lama (seperti Holo) di
|
||||
<code>res/values/styles.xml</code>.</li>
|
||||
<li>Definisikan tema bernama sama yang mewarisi tema bahan di
|
||||
<code>res/values-v21/styles.xml</code>.</li>
|
||||
<li>Atur tema ini sebagai tema aplikasi Anda dalam file manifes.</li>
|
||||
</ol>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong>
|
||||
Jika aplikasi Anda menggunakan tema bahan namun tidak menyediakan tema alternatif dengan cara ini,
|
||||
aplikasi itu tidak akan berjalan pada versi Android sebelum 5.0.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="Layouts">Menyediakan Layout Alternatif</h2>
|
||||
|
||||
<p>Jika layout yang Anda desain sesuai dengan panduan desain bahan tidak menggunakan salah satu
|
||||
atribut XML baru yang diperkenalkan di Android 5.0 (API level 21), layout itu akan berfungsi pada
|
||||
versi Android sebelumnya. Jika tidak, Anda bisa menyediakan layout alternatif. Anda juga bisa menyediakan
|
||||
layout alternatif untuk menyesuaikan cara aplikasi ditampilkan pada versi Android terdahulu.</p>
|
||||
|
||||
<p>Buatlah file layout untuk Android 5.0 (API level 21) dalam <code>res/layout-v21/</code> dan
|
||||
file layout alternatif untuk versi Android terdahulu dalam <code>res/layout/</code>.
|
||||
Misalnya, <code>res/layout/my_activity.xml</code> adalah layout alternatif untuk
|
||||
<code>res/layout-v21/my_activity.xml</code>.</p>
|
||||
|
||||
<p>Untuk menghindari duplikasi kode, definisikan gaya dalam <code>res/values/</code>, modifikasi
|
||||
gaya di <code>res/values-v21/</code> untuk API baru, dan gunakan pewarisan gaya, dengan mendefinisikan
|
||||
gaya dasar di <code>res/values/</code> dan mewarisi gaya di <code>res/values-v21/</code>.</p>
|
||||
|
||||
|
||||
<h2 id="SupportLib">Menggunakan Support Library</h2>
|
||||
|
||||
<p><a href="{@docRoot}tools/support-library/features.html#v7">v7 Support Library</a>
|
||||
r21 ke atas menyertakan fitur desain bahan berikut:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="{@docRoot}training/material/theme.html">Gaya desain bahan</a> untuk beberapa widget sistem
|
||||
bila Anda menerapkan salah satu tema <code>Theme.AppCompat</code>.</li>
|
||||
<li><a href="{@docRoot}training/material/theme.html#ColorPalette">Atribut tema palet warna</a>
|
||||
dalam tema <code>Theme.AppCompat</code>.</li>
|
||||
<li>Widget {@link android.support.v7.widget.RecyclerView} untuk <a href="{@docRoot}training/material/lists-cards.html#RecyclerView">
|
||||
menampilkan kumpulan data.</a></li>
|
||||
<li>Widget {@link android.support.v7.widget.CardView} untuk <a href="{@docRoot}training/material/lists-cards.html#CardView">membuat kartu</a>.</li>
|
||||
<li>Kelas {@link android.support.v7.graphics.Palette} untuk <a href="{@docRoot}training/material/drawables.html#ColorExtract">mengekstrak warna mencolok dari
|
||||
gambar</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3>Widget sistem</h3>
|
||||
|
||||
<p>Tema-tema <code>Theme.AppCompat</code> menyediakan gaya desain bahan untuk widget ini:</p>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.widget.EditText}</li>
|
||||
<li>{@link android.widget.Spinner}</li>
|
||||
<li>{@link android.widget.CheckBox}</li>
|
||||
<li>{@link android.widget.RadioButton}</li>
|
||||
<li>{@link android.support.v7.widget.SwitchCompat}</li>
|
||||
<li>{@link android.widget.CheckedTextView}</li>
|
||||
</ul>
|
||||
|
||||
<h3>Palet Warna</h3>
|
||||
|
||||
<p>Untuk memperoleh gaya desain bahan dan menyesuaikan palet warna dengan Android v7 Support
|
||||
Library, terapkan salah satu tema <code>Theme.AppCompat</code>:</p>
|
||||
|
||||
<pre>
|
||||
<!-- extend one of the Theme.AppCompat themes -->
|
||||
<style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
|
||||
<!-- customize the color palette -->
|
||||
<item name="colorPrimary">@color/material_blue_500</item>
|
||||
<item name="colorPrimaryDark">@color/material_blue_700</item>
|
||||
<item name="colorAccent">@color/material_green_A200</item>
|
||||
</style>
|
||||
</pre>
|
||||
|
||||
<h3>Daftar dan Kartu</h3>
|
||||
|
||||
<p>Widget {@link android.support.v7.widget.RecyclerView} dan {@link
|
||||
android.support.v7.widget.CardView} tersedia di versi Android terdahulu melalui
|
||||
Android v7 Support Library dengan pembatasan ini:</p>
|
||||
<ul>
|
||||
<li>{@link android.support.v7.widget.CardView} memundurkan ke implementasi bayangan terprogram
|
||||
dengan menggunakan pengisi tambahan.</li>
|
||||
<li>{@link android.support.v7.widget.CardView} tidak memangkas tampilan anaknya yang berpotongan
|
||||
dengan sudut melengkung.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3>Dependensi</h3>
|
||||
|
||||
<p>Untuk menggunakan fitur-fitur ini di versi Android sebelum 5.0 (API level 21), sertakan
|
||||
Android v7 Support Library dalam proyek Anda sebagai <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependensi Gradle</a>:</p>
|
||||
|
||||
<pre>
|
||||
dependencies {
|
||||
compile 'com.android.support:appcompat-v7:21.0.+'
|
||||
compile 'com.android.support:cardview-v7:21.0.+'
|
||||
compile 'com.android.support:recyclerview-v7:21.0.+'
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<h2 id="CheckVersion">Memeriksa Versi Sistem</h2>
|
||||
|
||||
<p>Fitur berikut hanya tersedia di Android 5.0 (API level 21) ke atas:</p>
|
||||
|
||||
<ul>
|
||||
<li>Transisi aktivitas</li>
|
||||
<li>Umpan balik sentuh</li>
|
||||
<li>Animasi membuka</li>
|
||||
<li>Animasi berbasis path</li>
|
||||
<li>Drawable vektor</li>
|
||||
<li>Pewarnaan drawable</li>
|
||||
</ul>
|
||||
|
||||
<p>Untuk menjaga kompatibilitas dengan versi Android terdahulu, periksa {@link
|
||||
android.os.Build.VERSION#SDK_INT version} sistem saat runtime sebelum Anda memanggil API untuk salah satu
|
||||
fitur ini:</p>
|
||||
|
||||
<pre>
|
||||
// Check if we're running on Android 5.0 or higher
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// Call some material design APIs here
|
||||
} else {
|
||||
// Implement this feature without material design
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> Untuk menetapkan versi Android yang didukung aplikasi Anda,
|
||||
gunakan atribut <code>android:minSdkVersion</code> dan <code>android:targetSdkVersion</code>
|
||||
dalam file manifes. Untuk menggunakan fitur desain bahan di Android 5.0, atur
|
||||
atribut <code>android:targetSdkVersion</code> ke <code>21</code>. Untuk informasi selengkapnya, lihat
|
||||
panduan <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">API
|
||||
<uses-sdk></a>.</p>
|
||||
126
docs/html-intl/intl/id/training/material/drawables.jd
Normal file
126
docs/html-intl/intl/id/training/material/drawables.jd
Normal file
@@ -0,0 +1,126 @@
|
||||
page.title=Bekerja dengan Drawable
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Pelajaran ini mengajarkan Anda cara</h2>
|
||||
<ol>
|
||||
<li><a href="#DrawableTint">Mewarnai Sumber Daya Drawable</a></li>
|
||||
<li><a href="#ColorExtract">Mengekstrak Warna Mencolok dari Gambar</a></li>
|
||||
<li><a href="#VectorDrawables">Membuat Drawable Vektor</a></li>
|
||||
</ol>
|
||||
<h2>Anda juga harus membaca</h2>
|
||||
<ul>
|
||||
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
|
||||
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Kemampuan berikut untuk drawable membantu Anda mengimplementasikan desain bahan dalam aplikasi Anda:</p>
|
||||
|
||||
<ul>
|
||||
<li>Pewarnaan drawable</li>
|
||||
<li>Ekstraksi warna mencolok</li>
|
||||
<li>Drawable vektor</li>
|
||||
</ul>
|
||||
|
||||
<p>Pelajaran ini menampilkan cara menggunakan fitur-fitur ini dalam aplikasi Anda.</p>
|
||||
|
||||
|
||||
<h2 id="DrawableTint">Mewarnai Sumber Daya Drawable</h2>
|
||||
|
||||
<p>Dengan Android 5.0 (API level 21) ke atas, Anda bisa mewarnai bitmap dan sembilan-tambalan yang didefinisikan sebagai
|
||||
alpha-mask. Anda bisa mewarnainya dengan sumber daya warna atau atribut tema yang mencocokkan ke
|
||||
sumber daya warna (misalnya, <code>?android:attr/colorPrimary</code>). Biasanya, Anda membuat aset ini
|
||||
hanya sekali dan mewarnainya secara otomatis agar cocok dengan tema Anda.</p>
|
||||
|
||||
<p>Anda bisa menerapkan warna ke objek {@link android.graphics.drawable.BitmapDrawable} atau {@link
|
||||
android.graphics.drawable.NinePatchDrawable} dengan metode {@code setTint()}. Anda juga bisa
|
||||
mengatur warna dan mode dalam layout dengan atribut <code>android:tint</code> dan
|
||||
<code>android:tintMode</code>.</p>
|
||||
|
||||
|
||||
<h2 id="ColorExtract">Mengekstrak Warna Mencolok dari Gambar</h2>
|
||||
|
||||
<p>Android Support Library r21 ke atas menyertakan kelas {@link
|
||||
android.support.v7.graphics.Palette}, yang memungkinkan Anda mengekstrak warna mencolok dari gambar.
|
||||
Kelas ini mengekstrak warna mencolok berikut:</p>
|
||||
|
||||
<ul>
|
||||
<li>Menyala</li>
|
||||
<li>Menyala pekat</li>
|
||||
<li>Menyala pucat</li>
|
||||
<li>Pudar</li>
|
||||
<li>Pudar pekat</li>
|
||||
<li>Pudar pucat</li>
|
||||
</ul>
|
||||
|
||||
<p>Untuk mengekstrak warna-warna ini, teruskan objek {@link android.graphics.Bitmap} ke
|
||||
metode statis {@link android.support.v7.graphics.Palette#generate Palette.generate()} dalam
|
||||
thread latar belakang tempat Anda memuat gambar. Jika Anda tidak bisa menggunakan thread itu, panggil metode
|
||||
{@link android.support.v7.graphics.Palette#generateAsync Palette.generateAsync()} dan
|
||||
sediakan listener sebagai gantinya.</p>
|
||||
|
||||
<p>Anda bisa mengambil warna mencolok dari gambar dengan metode getter di kelas
|
||||
<code>Palette</code>, misalnya <code>Palette.getVibrantColor</code>.</p>
|
||||
|
||||
<p>Untuk menggunakan kelas {@link android.support.v7.graphics.Palette} dalam proyek Anda, tambahkan
|
||||
<a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependensi Gradle</a> berikut ke
|
||||
modul aplikasi Anda:</p>
|
||||
|
||||
<pre>
|
||||
dependencies {
|
||||
...
|
||||
compile 'com.android.support:palette-v7:21.0.0'
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Untuk informasi selengkapnya, lihat referensi API untuk kelas {@link android.support.v7.graphics.Palette}.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="VectorDrawables">Membuat Drawable Vektor</h2>
|
||||
|
||||
<!-- video box -->
|
||||
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=wlFVIIstKmA" style="margin-top:18px">
|
||||
<div>
|
||||
<h3>Video</h3>
|
||||
<p>Grafis Vektor Android</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<p>Di Android 5.0 (API Level 21) ke atas, Anda bisa mendefinisikan drawable vektor, yang berubah skala tanpa
|
||||
kehilangan definisi. Anda hanya memerlukan satu file aset per gambar vektor, bukan file aset untuk
|
||||
setiap densitas layar seperti pada gambar bitmap. Untuk membuat gambar vektor, Anda mendefinisikan detail
|
||||
bentuknya dalam sebuah elemen XML <code><vector></code>.</p>
|
||||
|
||||
<p>Contoh berikut mendefinisikan gambar vektor berbentuk hati:</p>
|
||||
|
||||
<pre>
|
||||
<!-- res/drawable/heart.xml -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<!-- intrinsic size of the drawable -->
|
||||
android:height="256dp"
|
||||
android:width="256dp"
|
||||
<!-- size of the virtual canvas -->
|
||||
android:viewportWidth="32"
|
||||
android:viewportHeight="32">
|
||||
|
||||
<!-- draw a path -->
|
||||
<path android:fillColor="#8fff"
|
||||
android:pathData="M20.5,9.5
|
||||
c-1.955,0,-3.83,1.268,-4.5,3
|
||||
c-0.67,-1.732,-2.547,-3,-4.5,-3
|
||||
C8.957,9.5,7,11.432,7,14
|
||||
c0,3.53,3.793,6.257,9,11.5
|
||||
c5.207,-5.242,9,-7.97,9,-11.5
|
||||
C25,11.432,23.043,9.5,20.5,9.5z" />
|
||||
</vector>
|
||||
</pre>
|
||||
|
||||
<p>Gambar vektor direpresentasikan di Android sebagai objek {@link android.graphics.drawable.VectorDrawable}.
|
||||
Untuk informasi selengkapnya tentang sintaks <code>pathData</code>, lihat <a href="http://www.w3.org/TR/SVG11/paths.html#PathData">Referensi Path SVG</a>. Untuk informasi selengkapnya
|
||||
tentang menganimasikan properti drawable vektor, lihat
|
||||
<a href="{@docRoot}training/material/animations.html#AnimVector">Menganimasikan Drawable Vektor</a>.</p>
|
||||
171
docs/html-intl/intl/id/training/material/get-started.jd
Normal file
171
docs/html-intl/intl/id/training/material/get-started.jd
Normal file
@@ -0,0 +1,171 @@
|
||||
page.title=Memulai
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Pelajaran ini mengajarkan Anda cara</h2>
|
||||
<ol>
|
||||
<li><a href="#ApplyTheme">Menerapkan Tema Bahan</a></li>
|
||||
<li><a href="#Layouts">Mendesain Layout Anda</a></li>
|
||||
<li><a href="#Depth">Menetapkan Ketinggian di Tampilan Anda</a></li>
|
||||
<li><a href="#ListsCards">Membuat Daftar dan Kartu</a></li>
|
||||
<li><a href="#Animations">Menyesuaikan Animasi Anda</a></li>
|
||||
</ol>
|
||||
<h2>Anda juga harus membaca</h2>
|
||||
<ul>
|
||||
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
|
||||
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Untuk membuat aplikasi dengan desain bahan:</p>
|
||||
|
||||
<ol>
|
||||
<li style="margin-bottom:10px">
|
||||
Tinjaulah <a href="http://www.google.com/design/spec">spesifikasi desain bahan</a>.</li>
|
||||
<li style="margin-bottom:10px">
|
||||
Terapkan <strong>tema</strong> bahan ke aplikasi Anda.</li>
|
||||
<li style="margin-bottom:10px">
|
||||
Buat <strong>layout</strong> agar mengikuti panduan desain bahan.</li>
|
||||
<li style="margin-bottom:10px">
|
||||
Tetapkan <strong>ketinggian</strong> tampilan Anda untuk menghasilkan bayangan.</li>
|
||||
<li style="margin-bottom:10px">
|
||||
Gunakan <strong>widget</strong> sistem untuk daftar dan kartu.</li>
|
||||
<li style="margin-bottom:10px">
|
||||
Sesuaikan <strong>animasi</strong> di aplikasi Anda.</li>
|
||||
</ol>
|
||||
|
||||
<h3>Mempertahankan kompatibilitas mundur</h3>
|
||||
|
||||
<p>Anda bisa menambahkan banyak fitur desain bahan ke aplikasi sekaligus mempertahankan kompatibilitas dengan
|
||||
versi Android sebelum 5.0. Untuk informasi selengkapnya, lihat
|
||||
<a href="{@docRoot}training/material/compatibility.html">Mempertahankan Kompatibilitas</a>.</p>
|
||||
|
||||
<h3>Memperbarui aplikasi dengan desain bahan</h3>
|
||||
|
||||
<p>Untuk memperbarui aplikasi yang ada guna memasukkan desain bahan, perbarui layout Anda dengan mengikuti
|
||||
panduan desain bahan. Juga pastikan memasukkan kedalaman, umpan balik sentuh, dan
|
||||
animasi.</p>
|
||||
|
||||
<h3>Membuat aplikasi baru dengan desain bahan</h3>
|
||||
|
||||
<p>Jika Anda sedang membuat aplikasi baru dengan fitur desain bahan, <a href="http://www.google.com/design/spec">panduan desain bahan</a> akan memberi Anda
|
||||
kerangka kerja desain yang kohesif. Ikuti panduan itu dan gunakan fungsionalitas baru di
|
||||
kerangka kerja Android untuk mendesain dan mengembangkan aplikasi Anda.</p>
|
||||
|
||||
|
||||
<h2 id="ApplyTheme">Menerapkan Tema Bahan</h2>
|
||||
|
||||
<p>Untuk menerapkan tema bahan dalam aplikasi Anda, tetapkan gaya yang mewarisi
|
||||
<code>android:Theme.Material</code>:</p>
|
||||
|
||||
<pre>
|
||||
<!-- res/values/styles.xml -->
|
||||
<resources>
|
||||
<!-- your theme inherits from the material theme -->
|
||||
<style name="AppTheme" parent="android:Theme.Material">
|
||||
<!-- theme customizations -->
|
||||
</style>
|
||||
</resources>
|
||||
</pre>
|
||||
|
||||
<p>Tema bahan menyediakan widget sistem terbaru yang memungkinkan Anda mengatur palet warnanya dan
|
||||
animasi default untuk umpan balik sentuh dan transisi aktivitas. Untuk detail selengkapnya, lihat
|
||||
<a href="{@docRoot}training/material/theme.html">Menggunakan Tema Bahan</a>.</p>
|
||||
|
||||
|
||||
<h2 id="Layouts">Mendesain Layout Anda</h2>
|
||||
|
||||
<p>Selain menerapkan dan menyesuaikan tema bahan, layout Anda harus mematuhi
|
||||
<a href="http://www.google.com/design/spec">panduan desain bahan</a>. Bila Anda mendesain
|
||||
layout, berikan perhatian khusus pada hal-hal berikut:</p>
|
||||
|
||||
<ul>
|
||||
<li>Petak patokan</li>
|
||||
<li>Garis utama</li>
|
||||
<li>Pengaturan Jarak</li>
|
||||
<li>Ukuran target sentuh</li>
|
||||
<li>Struktur layout</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2 id="Depth">Menetapkan Ketinggian di Tampilan Anda</h2>
|
||||
|
||||
<p>Tampilan bisa menghasilkan bayangan, dan nilai ketinggian tampilan
|
||||
menentukan ukuran bayangan dan urutan penggambarannya. Untuk mengatur ketinggian tampilan, gunakan
|
||||
atribut <code>android:elevation</code> dalam layout:</p>
|
||||
|
||||
<pre>
|
||||
<TextView
|
||||
android:id="@+id/my_textview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/next"
|
||||
android:background="@color/white"
|
||||
android:elevation="5dp" />
|
||||
</pre>
|
||||
|
||||
<p>Properti <code>translationZ</code> baru memungkinkan Anda membuat animasi yang mencerminkan
|
||||
perubahan sementara pada ketinggian tampilan. Perubahan ketinggian bisa berguna saat
|
||||
<a href="{@docRoot}training/material/animations.html#ViewState">merespons
|
||||
gerakan sentuh</a>.</p>
|
||||
|
||||
<p>Untuk detail selengkapnya, lihat <a href="{@docRoot}training/material/shadows-clipping.html">Mendefinisikan
|
||||
Bayangan dan Memangkas Tampilan</a>.</p>
|
||||
|
||||
|
||||
<h2 id="ListsCards">Membuat Daftar dan Kartu</h2>
|
||||
|
||||
<p>{@link android.support.v7.widget.RecyclerView} adalah versi {@link
|
||||
android.widget.ListView} yang lebih mudah dimasukkan dan mendukung beragam tipe layout serta memberikan peningkatan kinerja.
|
||||
{@link android.support.v7.widget.CardView} memungkinkan Anda menampilkan potongan informasi dalam kartu dengan
|
||||
tampilan konsisten di seluruh aplikasi. Contoh kode berikut memperagakan cara menyertakan
|
||||
{@link android.support.v7.widget.CardView} dalam layout Anda:</p>
|
||||
|
||||
<pre>
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/card_view"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="200dp"
|
||||
card_view:cardCornerRadius="3dp">
|
||||
...
|
||||
</android.support.v7.widget.CardView>
|
||||
</pre>
|
||||
|
||||
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/lists-cards.html">Membuat Daftar
|
||||
dan Kartu</a>.</p>
|
||||
|
||||
|
||||
<h2 id="Animations">Menyesuaikan Animasi Anda</h2>
|
||||
|
||||
<p>Android 5.0 (API level 21) menyertakan API baru untuk membuat animasi custom di aplikasi Anda.
|
||||
Misalnya, Anda bisa mengaktifkan transisi aktivitas dan mendefinisikan transisi keluar di
|
||||
aktivitas:</p>
|
||||
|
||||
<pre>
|
||||
public class MyActivity extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// enable transitions
|
||||
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
|
||||
setContentView(R.layout.activity_my);
|
||||
}
|
||||
|
||||
public void onSomeButtonClicked(View view) {
|
||||
getWindow().setExitTransition(new Explode());
|
||||
Intent intent = new Intent(this, MyOtherActivity.class);
|
||||
startActivity(intent,
|
||||
ActivityOptions
|
||||
.makeSceneTransitionAnimation(this).toBundle());
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Bila Anda memulai aktivitas lain dari aktivitas ini, transisi keluar akan diaktifkan.</p>
|
||||
|
||||
<p>Untuk mengetahui selengkapnya tentang API animasi yang baru, lihat <a href="{@docRoot}training/material/animations.html">Mendefinisikan Animasi Custom</a>.</p>
|
||||
60
docs/html-intl/intl/id/training/material/index.jd
Normal file
60
docs/html-intl/intl/id/training/material/index.jd
Normal file
@@ -0,0 +1,60 @@
|
||||
page.title=Desain Bahan untuk Pengembang
|
||||
page.image=images/cards/material_2x.png
|
||||
page.metaDescription=Pelajari cara menerapkan desain bahan pada aplikasi Anda.
|
||||
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Dependensi dan Prasyarat</h2>
|
||||
<ul>
|
||||
<li>Android 5.0 (API Level 21)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Desain bahan adalah panduan komprehensif untuk desain visual, gerak, dan interaksi di
|
||||
berbagai platform dan perangkat. Untuk menggunakan desain bahan di aplikasi Android, ikuti panduan
|
||||
yang dijelaskan dalam
|
||||
<a href="http://www.google.com/design/spec/material-design/introduction.html">spesifikasi desain bahan
|
||||
</a> dan gunakan komponen serta fungsionalitas baru yang tersedia di Android 5.0
|
||||
(API level 21).</p>
|
||||
|
||||
<p>Kelas ini menampilkan kepada Anda cara membuat aplikasi desain bahan dengan elemen-elemen berikut:</p>
|
||||
|
||||
<ul>
|
||||
<li>Tema bahan</li>
|
||||
<li>Widget untuk kartu dan daftar</li>
|
||||
<li>Bayangan custom dan pemangkasan tampilan</li>
|
||||
<li>Drawable vektor</li>
|
||||
<li>Animasi custom</li>
|
||||
</ul>
|
||||
|
||||
<p>Kelas ini juga mengajarkan cara mempertahankan kompatibilitas dengan versi Android sebelum
|
||||
5.0 (API level 21) bila Anda menggunakan fitur desain bahan dalam aplikasi.</p>
|
||||
|
||||
<h2>Pelajaran</h2>
|
||||
|
||||
<dl>
|
||||
<dt><a href="{@docRoot}training/material/get-started.html">Memulai</a></dt>
|
||||
<dd>Pelajari cara memperbarui aplikasi Anda dengan fitur desain bahan.</dd>
|
||||
|
||||
<dt><a href="{@docRoot}training/material/theme.html">Menggunakan Tema Bahan</a></dt>
|
||||
<dd>Pelajari cara menerapkan gaya desain bahan pada aplikasi Anda.</dd>
|
||||
|
||||
<dt><a href="{@docRoot}training/material/lists-cards.html">Membuat Daftar dan Kartu</a></dt>
|
||||
<dd>Pelajari cara membuat daftar dan kartu dengan tampilan dan cara kerja yang konsisten menggunakan widget sistem.</dd>
|
||||
|
||||
<dt><a href="{@docRoot}training/material/shadows-clipping.html">Mendefinisikan Bayangan dan Memangkas Tampilan</a></dt>
|
||||
<dd>Pelajari cara mengatur elevasi tampilan Anda untuk membuat bayangan custom dan cara memangkas tampilan.</dd>
|
||||
|
||||
<dt><a href="{@docRoot}training/material/drawables.html">Bekerja dengan Drawable</a></dt>
|
||||
<dd>Pelajari cara membuat drawable vektor dan cara mewarnai sumber daya drawable.</dd>
|
||||
|
||||
<dt><a href="{@docRoot}training/material/animations.html">Mendefinisikan Animasi Custom</a></dt>
|
||||
<dd>Pelajari cara membuat animasi custom untuk tampilan dan transisi aktivitas dengan elemen bersama.</dd>
|
||||
|
||||
<dt><a href="{@docRoot}training/material/compatibility.html">Mempertahankan Kompatibilitas</a></dt>
|
||||
<dd>Pelajari cara mempertahankan kompatibilitas dengan versi platform sebelum Android 5.0.</dd>
|
||||
</dl>
|
||||
266
docs/html-intl/intl/id/training/material/lists-cards.jd
Normal file
266
docs/html-intl/intl/id/training/material/lists-cards.jd
Normal file
@@ -0,0 +1,266 @@
|
||||
page.title=Membuat Daftar dan Kartu
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Pelajaran ini mengajarkan Anda cara</h2>
|
||||
<ol>
|
||||
<li><a href="#RecyclerView">Membuat Daftar</a></li>
|
||||
<li><a href="#CardView">Membuat Kartu</a></li>
|
||||
<li><a href="#Dependencies">Menambahkan Dependensi</a></li>
|
||||
</ol>
|
||||
<h2>Anda juga harus membaca</h2>
|
||||
<ul>
|
||||
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
|
||||
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Untuk membuat daftar dan kartu yang kompleks dengan gaya desain bahan di aplikasi, Anda bisa menggunakan widget
|
||||
{@link android.support.v7.widget.RecyclerView} dan {@link android.support.v7.widget.CardView}.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="RecyclerView">Membuat Daftar</h2>
|
||||
|
||||
<p>Widget {@link android.support.v7.widget.RecyclerView} adalah
|
||||
versi {@link android.widget.ListView} yang lebih maju dan fleksibel. Widget ini adalah kontainer untuk menampilkan set data
|
||||
besar yang bisa digulir secara sangat efisien dengan mempertahankan tampilan dalam jumlah terbatas. Gunakan
|
||||
widget {@link android.support.v7.widget.RecyclerView} bila Anda memiliki kumpulan data dengan elemen
|
||||
yang berubah saat runtime berdasarkan tindakan pengguna atau kejadian jaringan.</p>
|
||||
|
||||
<p>Kelas {@link android.support.v7.widget.RecyclerView} menyederhanakan penampilan dan penanganan
|
||||
set data yang besar dengan menyediakan:</p>
|
||||
|
||||
<ul>
|
||||
<li>Pengelola layout untuk memosisikan item</li>
|
||||
<li>Animasi default untuk operasi item umum, misalnya penghapusan atau penambahan item</li>
|
||||
</ul>
|
||||
|
||||
<p>Anda juga memiliki keluwesan untuk mendefinisikan pengelola layout custom dan animasi untuk widget {@link
|
||||
android.support.v7.widget.RecyclerView}.</p>
|
||||
|
||||
<img src="{@docRoot}training/material/images/RecyclerView.png" alt="" width="550" height="106" />
|
||||
<p class="img-caption">
|
||||
<strong>Gambar 1</strong>. Widget <code>RecyclerView</code>.
|
||||
</p>
|
||||
|
||||
<p>Untuk menggunakan widget {@link android.support.v7.widget.RecyclerView}, Anda harus menetapkan
|
||||
adaptor dan pengelola layout. Untuk membuat adaptor, perluas kelas {@link
|
||||
android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}. Detail
|
||||
implementasi bergantung pada detail set data Anda dan tipe tampilan. Untuk informasi selengkapnya,
|
||||
lihat <a href="#RVExamples">contoh-contoh</a> di bawah.</p>
|
||||
|
||||
<div style="float:right">
|
||||
<img src="{@docRoot}design/material/images/list_mail.png" alt="" width="250" height="426" />
|
||||
<p class="img-caption" style="margin-left:8px">
|
||||
<strong>Gambar 2</strong> - Daftar berisi <code>RecyclerView</code>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p><strong>Pengelola layout</strong> memosisikan tampilan item dalam {@link
|
||||
android.support.v7.widget.RecyclerView} dan menentukan waktu untuk menggunakan ulang tampilan item yang tidak
|
||||
lagi terlihat oleh pengguna. Untuk menggunakan ulang (atau <em>mendaur ulang</em>) tampilan, pengelola layout bisa meminta
|
||||
adaptor untuk mengganti konten tampilan dengan elemen lain dalam dataset. Mendaur ulang
|
||||
tampilan dengan cara ini akan meningkatkan kinerja karena menghindari pembuatan tampilan yang tidak diperlukan atau
|
||||
melakukan pencarian {@link android.app.Activity#findViewById findViewById()} yang mahal.</p>
|
||||
|
||||
<p>{@link android.support.v7.widget.RecyclerView} menyediakan semua pengelola layout bawaan ini:</p>
|
||||
|
||||
<ul>
|
||||
<li>{@link android.support.v7.widget.LinearLayoutManager} menampilkan item dalam
|
||||
daftar gulir vertikal atau horizontal.</li>
|
||||
<li>{@link android.support.v7.widget.GridLayoutManager} menampilkan item dalam petak.</li>
|
||||
<li>{@link android.support.v7.widget.StaggeredGridLayoutManager} menampilkan item dalam petak zigzag.</li>
|
||||
</ul>
|
||||
|
||||
<p>Untuk membuat pengelola layout custom, perluas kelas {@link
|
||||
android.support.v7.widget.RecyclerView.LayoutManager RecyclerView.LayoutManager}.</p>
|
||||
|
||||
<h3>Animasi</h3>
|
||||
|
||||
<p>Animasi untuk menambahkan dan menghapus item diaktifkan secara default di {@link
|
||||
android.support.v7.widget.RecyclerView}. Untuk menyesuaikan animasi ini, perluas kelas
|
||||
{@link android.support.v7.widget.RecyclerView.ItemAnimator RecyclerView.ItemAnimator}dan gunakan
|
||||
metode {@link android.support.v7.widget.RecyclerView#setItemAnimator RecyclerView.setItemAnimator()}.
|
||||
</p>
|
||||
|
||||
<h3 id="RVExamples">Contoh</h3>
|
||||
|
||||
<p>Contoh kode berikut memperagakan cara menambahkan
|
||||
{@link android.support.v7.widget.RecyclerView} ke layout:</p>
|
||||
|
||||
<pre>
|
||||
<!-- A RecyclerView with some commonly used attributes -->
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/my_recycler_view"
|
||||
android:scrollbars="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
</pre>
|
||||
|
||||
<p>Begitu Anda menambahkan widget {@link android.support.v7.widget.RecyclerView} ke layout,
|
||||
dapatkan pengatur atau handle objek itu, hubungkan dengan pengelola layout, dan sertakan adaptor untuk data
|
||||
yang akan ditampilkan:</p>
|
||||
|
||||
<pre>
|
||||
public class MyActivity extends Activity {
|
||||
private RecyclerView mRecyclerView;
|
||||
private RecyclerView.Adapter mAdapter;
|
||||
private RecyclerView.LayoutManager mLayoutManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.my_activity);
|
||||
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
|
||||
|
||||
// use this setting to improve performance if you know that changes
|
||||
// in content do not change the layout size of the RecyclerView
|
||||
mRecyclerView.setHasFixedSize(true);
|
||||
|
||||
// use a linear layout manager
|
||||
mLayoutManager = new LinearLayoutManager(this);
|
||||
mRecyclerView.setLayoutManager(mLayoutManager);
|
||||
|
||||
// specify an adapter (see also next example)
|
||||
mAdapter = new MyAdapter(myDataset);
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Adaptor menyediakan akses ke item dataset Anda, membuat tampilan untuk item, dan
|
||||
mengganti konten sebagian tampilan dengan item data baru bila item semula tidak lagi
|
||||
terlihat. Contoh kode berikut menampilkan implementasi sederhana untuk sebuah dataset yang terdiri dari
|
||||
larik string yang ditampilkan dengan menggunakan widget {@link android.widget.TextView}:</p>
|
||||
|
||||
<pre>
|
||||
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
|
||||
private String[] mDataset;
|
||||
|
||||
// Provide a reference to the views for each data item
|
||||
// Complex data items may need more than one view per item, and
|
||||
// you provide access to all the views for a data item in a view holder
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
// each data item is just a string in this case
|
||||
public TextView mTextView;
|
||||
public ViewHolder(TextView v) {
|
||||
super(v);
|
||||
mTextView = v;
|
||||
}
|
||||
}
|
||||
|
||||
// Provide a suitable constructor (depends on the kind of dataset)
|
||||
public MyAdapter(String[] myDataset) {
|
||||
mDataset = myDataset;
|
||||
}
|
||||
|
||||
// Create new views (invoked by the layout manager)
|
||||
@Override
|
||||
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
|
||||
int viewType) {
|
||||
// create a new view
|
||||
View v = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.my_text_view, parent, false);
|
||||
// set the view's size, margins, paddings and layout parameters
|
||||
...
|
||||
ViewHolder vh = new ViewHolder(v);
|
||||
return vh;
|
||||
}
|
||||
|
||||
// Replace the contents of a view (invoked by the layout manager)
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
// - get element from your dataset at this position
|
||||
// - replace the contents of the view with that element
|
||||
holder.mTextView.setText(mDataset[position]);
|
||||
|
||||
}
|
||||
|
||||
// Return the size of your dataset (invoked by the layout manager)
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mDataset.length;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<div style="float:right;margin-top:15px;margin-left:30px">
|
||||
<img src="{@docRoot}design/material/images/card_travel.png" alt="" width="225" height="383">
|
||||
<p class="img-caption" style="margin-left:12px">
|
||||
<strong>Gambar 3</strong>. Contoh kartu.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2 id="CardView">Membuat Kartu</h2>
|
||||
|
||||
<p>{@link android.support.v7.widget.CardView} memperluas kelas {@link android.widget.FrameLayout}
|
||||
dan memungkinkan Anda menampilkan informasi dalam kartu yang memiliki tampilan konsisten lintas platform. Widget {@link
|
||||
android.support.v7.widget.CardView} bisa memiliki bayangan dan sudut membulat.</p>
|
||||
|
||||
<p>Untuk membuat kartu dengan bayangan, gunakan atribut <code>card_view:cardElevation</code>.
|
||||
{@link android.support.v7.widget.CardView} menggunakan elevasi nyata dan bayangan dinamis pada Android 5.0
|
||||
(API level 21) ke atas dan memundurkan ke implementasi bayangan terprogram pada versi terdahulu.
|
||||
Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/compatibility.html">Mempertahankan
|
||||
Kompatibilitas</a>.</p>
|
||||
|
||||
<p>Gunakan properti-properti ini untuk menyesuaikan penampilan
|
||||
widget {@link android.support.v7.widget.CardView}:</p>
|
||||
|
||||
<ul>
|
||||
<li>Untuk mengatur radius sudut pada layout Anda, gunakan atribut <code>card_view:cardCornerRadius</code>.
|
||||
</li>
|
||||
<li>Untuk mengatur radius sudut dalam kode Anda, gunakan metode <code>CardView.setRadius</code>.</li>
|
||||
<li>Untuk mengatur warna latar belakang kartu, gunakan atribut <code>card_view:cardBackgroundColor</code>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Contoh kode berikut menampilkan cara menyertakan widget {@link android.support.v7.widget.CardView}
|
||||
dalam layout:</p>
|
||||
|
||||
<pre>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
... >
|
||||
<!-- A CardView that contains a TextView -->
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/card_view"
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="200dp"
|
||||
card_view:cardCornerRadius="4dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/info_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</android.support.v7.widget.CardView>
|
||||
</LinearLayout>
|
||||
</pre>
|
||||
|
||||
<p>Untuk informasi selengkapnya, lihat referensi API untuk {@link android.support.v7.widget.CardView}.</p>
|
||||
|
||||
|
||||
<h2 id="Dependencies">Menambahkan Dependensi</h2>
|
||||
|
||||
<p>Widget {@link android.support.v7.widget.RecyclerView} dan {@link android.support.v7.widget.CardView}
|
||||
adalah bagian dari <a href="{@docRoot}tools/support-library/features.html#v7">v7 Support
|
||||
Library</a>. Untuk menggunakan widget dalam proyek Anda, tambahkan
|
||||
<a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependensi Gradle</a> ini ke
|
||||
modul aplikasi Anda:</p>
|
||||
|
||||
<pre>
|
||||
dependencies {
|
||||
...
|
||||
compile 'com.android.support:cardview-v7:21.0.+'
|
||||
compile 'com.android.support:recyclerview-v7:21.0.+'
|
||||
}
|
||||
</pre>
|
||||
133
docs/html-intl/intl/id/training/material/shadows-clipping.jd
Normal file
133
docs/html-intl/intl/id/training/material/shadows-clipping.jd
Normal file
@@ -0,0 +1,133 @@
|
||||
page.title=Mendefinisikan Bayangan dan Memangkas Tampilan
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Pelajaran ini mengajarkan Anda cara</h2>
|
||||
<ol>
|
||||
<li><a href="#Elevation">Menetapkan Elevasi pada Tampilan Anda</a></li>
|
||||
<li><a href="#Shadows">Menyesuaikan Bayangan dan Garis Luar Tampilan</a></li>
|
||||
<li><a href="#Clip">Memangkas Tampilan</a></li>
|
||||
</ol>
|
||||
<h2>Anda juga harus membaca</h2>
|
||||
<ul>
|
||||
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
|
||||
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Desain bahan memperkenalkan elevasi untuk elemen-elemen UI. Elevasi membantu pengguna memahami
|
||||
arti penting relatif masing-masing elemen dan memfokuskan perhatian pada tugas yang ada.</p>
|
||||
|
||||
<p>Elevasi tampilan, yang dinyatakan dengan properti Z, menentukan tampilan visual
|
||||
bayangannya: tampilan dengan nilai Z lebih tinggi menghasilkan bayangan lebih besar dan lebih halus. Tampilan dengan nilai Z lebih tinggi menutupi
|
||||
tampilan dengan nilai Z lebih rendah; akan tetapi, nilai Z tampilan tidak memengaruhi ukuran tampilan.</p>
|
||||
|
||||
<p>Bayangan digambar oleh induk tampilan yang dinaikkan, sehingga terkena pemangkasan standar tampilan,
|
||||
yang dipangkas oleh induk secara default.</p>
|
||||
|
||||
<p>Elevasi juga berguna untuk membuat animasi tempat memunculkan widget untuk sementara di atas
|
||||
bidang tampilan saat melakukan beberapa tindakan.</p>
|
||||
|
||||
<p>Untuk informasi selengkapnya tentang elevasi dalam desain bahan, lihat
|
||||
<a href="http://www.google.com/design/spec/what-is-material/objects-in-3d-space.html">Objek
|
||||
di ruang 3D</a>.</p>
|
||||
|
||||
|
||||
<h2 id="Elevation">Menetapkan Elevasi pada Tampilan Anda</h2>
|
||||
|
||||
<p>Nilai Z untuk tampilan memiliki dua komponen:
|
||||
|
||||
<ul>
|
||||
<li>Elevasi: Komponen statis.</li>
|
||||
<li>Transformasi: Komponen dinamis yang digunakan untuk animasi.</li>
|
||||
</ul>
|
||||
|
||||
<p><code>Z = elevation + translationZ</code></p>
|
||||
|
||||
<img src="{@docRoot}training/material/images/shadows-depth.png" width="580" height="261" alt="" />
|
||||
<p class="img-caption"><strong>Gambar 1</strong> - Bayangan untuk berbagai elevasi tampilan.</p>
|
||||
|
||||
<p>Untuk mengatur elevasi tampilan dalam definisi layout, gunakan atribut <code>android:elevation</code>.
|
||||
Untuk mengatur elevasi tampilan dalam kode aktivitas, gunakan
|
||||
metode {@link android.view.View#setElevation View.setElevation()}.</p>
|
||||
|
||||
<p>Untuk mengatur transformasi tampilan, gunakan metode {@link android.view.View#setTranslationZ
|
||||
View.setTranslationZ()}.</p>
|
||||
|
||||
<p>Metode {@link android.view.ViewPropertyAnimator#z ViewPropertyAnimator.z()} dan {@link
|
||||
android.view.ViewPropertyAnimator#translationZ ViewPropertyAnimator.translationZ()} yang baru memudahkan
|
||||
Anda menganimasikan elevasi tampilan. Untuk informasi selengkapnya, lihat referensi API untuk
|
||||
{@link android.view.ViewPropertyAnimator} dan panduan pengembang <a href="{@docRoot}guide/topics/graphics/prop-animation.html">Animasi Properti</a>.
|
||||
</p>
|
||||
|
||||
<p>Anda juga bisa menggunakan {@link android.animation.StateListAnimator}
|
||||
untuk menetapkan animasi ini secara deklaratif. Ini khususnya berguna bila
|
||||
perubahan status memicu animasi, seperti saat seorang pengguna menekan tombol. Untuk informasi selengkapnya, lihat
|
||||
<a href="{@docRoot}training/material/animations.html#ViewState">Menganimasikan Perubahan Status Tampilan</a>.</p>
|
||||
|
||||
<p>Nilai Z diukur dengan satuan dp (density-independent pixel).</p>
|
||||
|
||||
|
||||
<h2 id="Shadows">Menyesuaikan Bayangan dan Garis Luar Tampilan</h2>
|
||||
|
||||
<p>Batas-batas drawable latar belakang tampilan menentukan bentuk default bayangannya.
|
||||
<strong>Garis luar</strong> menyatakan bentuk luar objek grafis dan mendefinisikan
|
||||
bidang riak untuk umpan balik sentuh.</p>
|
||||
|
||||
<p>Perhatikan tampilan ini, yang didefinisikan dengan drawable latar belakang:</p>
|
||||
|
||||
<pre>
|
||||
<TextView
|
||||
android:id="@+id/myview"
|
||||
...
|
||||
android:elevation="2dp"
|
||||
android:background="@drawable/myrect" />
|
||||
</pre>
|
||||
|
||||
<p>Drawable latar belakang didefinisikan sebagai persegi panjang dengan sudut membulat:</p>
|
||||
|
||||
<pre>
|
||||
<!-- res/drawable/myrect.xml -->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#42000000" />
|
||||
<corners android:radius="5dp" />
|
||||
</shape>
|
||||
</pre>
|
||||
|
||||
<p>Tampilan ini menghasilkan bayangan dengan sudut membulat, karena drawable latar belakang mendefinisikan
|
||||
garis luar tampilan. Memberikan garis luar custom akan mengesampingkan bentuk default bayangan tampilan.</p>
|
||||
|
||||
<p>Untuk mendefinisikan garis luar custom suatu tampilan dalam kode Anda:<p>
|
||||
|
||||
<ol>
|
||||
<li>Perluas kelas {@link android.view.ViewOutlineProvider}.</li>
|
||||
<li>Kesampingkan metode {@link android.view.ViewOutlineProvider#getOutline getOutline()}.</li>
|
||||
<li>Tetapkan penyedia garis luar baru untuk tampilan Anda dengan metode {@link
|
||||
android.view.View#setOutlineProvider View.setOutlineProvider()}.</li>
|
||||
</ol>
|
||||
|
||||
<p>Anda bisa membuat garis luar lonjong dan persegi panjang yang bersudut membulat dengan menggunakan metode dalam
|
||||
kelas {@link android.graphics.Outline}. Penyedia garis luar default untuk tampilan memperoleh garis luar
|
||||
dari latar belakang tampilan. Untuk mencegah tampilan menghasilkan bayangan, atur penyedia garis luarnya
|
||||
ke <code>null</code>.</p>
|
||||
|
||||
|
||||
<h2 id="Clip">Memangkas Tampilan</h2>
|
||||
|
||||
<p>Memangkas tampilan memudahkan Anda mengubah bentuk tampilan. Anda bisa memangkas tampilan agar
|
||||
konsistensi dengan elemen desain lainnya atau mengubah bentuk tampilan untuk merespons input pengguna.
|
||||
Anda bisa memangkas tampilan hingga area garis luarnya dengan menggunakan metode {@link android.view.View#setClipToOutline
|
||||
View.setClipToOutline()} atau atribut <code>android:clipToOutline</code>. Hanya
|
||||
garis-garis luar persegi panjang, lingkaran, dan persegi panjang bersudut bulat yang mendukung pemangkasan, seperti yang ditentukan oleh
|
||||
metode {@link android.graphics.Outline#canClip Outline.canClip()}.</p>
|
||||
|
||||
<p>Untuk memangkas tampilan ke bentuk drawable, atur drawable sebagai latar belakang tampilan
|
||||
(seperti yang ditampilkan di atas) dan panggil metode {@link android.view.View#setClipToOutline View.setClipToOutline()}.
|
||||
</p>
|
||||
|
||||
<p>Memangkas tampilan adalah operasi yang mahal; jadi, jangan animasikan bentuk yang Anda gunakan
|
||||
untuk memangkas tampilan. Untuk memperoleh efek ini, gunakan animasi <a href="{@docRoot}training/material/animations.html#Reveal">Reveal Effect</a>.</p>
|
||||
131
docs/html-intl/intl/id/training/material/theme.jd
Normal file
131
docs/html-intl/intl/id/training/material/theme.jd
Normal file
@@ -0,0 +1,131 @@
|
||||
page.title=Menggunakan Tema Bahan
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Pelajaran ini mengajarkan Anda cara</h2>
|
||||
<ol>
|
||||
<li><a href="#ColorPalette">Menyesuaikan Palet Warna</a></li>
|
||||
<li><a href="#StatusBar">Menyesuaikan Baris Status</a></li>
|
||||
<li><a href="#Inheritance">Tampilan Setiap Tema</a></li>
|
||||
</ol>
|
||||
<h2>Anda juga harus membaca</h2>
|
||||
<ul>
|
||||
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
|
||||
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Tema bahan yang baru menyediakan:</p>
|
||||
|
||||
<ul>
|
||||
<li>Widget sistem yang memungkinkan Anda mengatur palet warnanya</li>
|
||||
<li>Animasi umpan balik sentuh untuk widget sistem</li>
|
||||
<li>Animasi transisi aktivitas</li>
|
||||
</ul>
|
||||
|
||||
<p>Anda bisa menyesuaikan tampilan tema bahan
|
||||
sesuai dengan identitas merek Anda dengan palet warna yang Anda kontrol. Anda bisa mewarnai action-bar dan
|
||||
baris status dengan menggunakan atribut tema, seperti yang ditampilkan dalam <a href="#fig3">Gambar 3</a>.</p>
|
||||
|
||||
<p>Widget sistem memiliki desain baru dan animasi umpan balik sentuh. Anda bisa menyesuaikan
|
||||
palet warna, animasi umpan balik sentuh, dan transisi aktivitas untuk aplikasi.</p>
|
||||
|
||||
<p>Tema bahan didefinisikan sebagai:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>@android:style/Theme.Material</code> (versi gelap)</li>
|
||||
<li><code>@android:style/Theme.Material.Light</code> (versi terang)</li>
|
||||
<li><code>@android:style/Theme.Material.Light.DarkActionBar</code></li>
|
||||
</ul>
|
||||
|
||||
<p>Untuk daftar gaya bahan yang bisa Anda gunakan, lihat referensi API untuk
|
||||
{@link android.R.style R.style}.</p>
|
||||
|
||||
<!-- two columns, dark/light material theme example -->
|
||||
<div style="width:700px;margin-top:25px;margin-bottom:10px">
|
||||
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
|
||||
<img src="{@docRoot}design/material/images/MaterialDark.png" width="500" height="238">
|
||||
<div style="width:170px;margin:0 auto">
|
||||
<p style="margin-top:8px;font-size:12px"><strong>Gambar 1</strong>. Tema bahan gelap</p>
|
||||
</div>
|
||||
</div>
|
||||
<div style="float:left;width:250px;margin-right:0px;">
|
||||
<img src="{@docRoot}design/material/images/MaterialLight.png" width="500" height="238">
|
||||
<div style="width:170px;margin:0 auto">
|
||||
<p style="margin-top:8px;font-size:12px"><strong>Gambar 2</strong>. Tema bahan terang</p>
|
||||
</div>
|
||||
</div>
|
||||
<br style="clear:left">
|
||||
</div>
|
||||
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Tema bahan hanya tersedia di Android 5.0 (API level 21)
|
||||
ke atas. <a href="{@docRoot}tools/support-library/features.html#v7">v7 Support Library</a>
|
||||
menyediakan tema dengan gaya desain bahan untuk beberapa widget dan dukungan untuk menyesuaikan
|
||||
palet warna. Untuk informasi selengkapnya, lihat
|
||||
<a href="{@docRoot}training/material/compatibility.html">Mempertahankan Kompatibilitas</a>.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="ColorPalette">Menyesuaikan Palet Warna</h2>
|
||||
|
||||
<p style="margin-bottom:30px">Untuk menyesuaikan warna dasar tema agar cocok dengan merek Anda, definisikan
|
||||
warna custom menggunakan atribut tema saat Anda mewariskan dari tema bahan:</p>
|
||||
|
||||
<pre>
|
||||
<resources>
|
||||
<!-- inherit from the material theme -->
|
||||
<style name="AppTheme" parent="android:Theme.Material">
|
||||
<!-- Main theme colors -->
|
||||
<!-- your app branding color for the app bar -->
|
||||
<item name="android:colorPrimary">@color/primary</item>
|
||||
<!-- darker variant for the status bar and contextual app bars -->
|
||||
<item name="android:colorPrimaryDark">@color/primary_dark</item>
|
||||
<!-- theme UI controls like checkboxes and text fields -->
|
||||
<item name="android:colorAccent">@color/accent</item>
|
||||
</style>
|
||||
</resources>
|
||||
</pre>
|
||||
|
||||
<div style="float:right;margin-left:25px;margin-top:20px;margin-bottom:10px" id="fig3">
|
||||
<img src="{@docRoot}training/material/images/ThemeColors.png" width="250" height="445" />
|
||||
<p class="img-caption" style="margin-bottom:0px">
|
||||
<strong>Gambar 3.</strong> Menyesuaikan tema bahan.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<h2 id="StatusBar">Menyesuaikan Baris Status</h2>
|
||||
|
||||
<p>Tema bahan memungkinkan Anda menyesuaikan baris status dengan mudah; jadi Anda bisa menetapkan
|
||||
warna yang cocok dengan merek Anda dan memberikan kontras yang cukup untuk menampilkan ikon status putih. Untuk
|
||||
mengatur warna custom bagi baris status, gunakan atribut <code>android:statusBarColor</code> bila
|
||||
Anda memperluas tema bahan. Secara default, <code>android:statusBarColor</code> mewarisi
|
||||
nilai <code>android:colorPrimaryDark</code>.</p>
|
||||
|
||||
<p>Anda juga bisa menggambar sendiri di belakang baris status. Misalnya, jika Anda ingin menampilkan
|
||||
baris status secara transparan di atas foto, dengan gradasi gelap yang halus untuk memastikan
|
||||
ikon status putih tetap terlihat. Caranya, atur atribut <code>android:statusBarColor</code> ke
|
||||
<code>@android:color/transparent</code> dan sesuaikan flag jendela seperti yang diperlukan. Anda juga bisa
|
||||
menggunakan metode {@link android.view.Window#setStatusBarColor Window.setStatusBarColor()} untuk
|
||||
animasi atau pemudaran.</p>
|
||||
|
||||
<p class="note">
|
||||
<strong>Catatan:</strong> Baris status harus selalu memiliki delineasi yang jelas dari
|
||||
toolbar utama, kecuali bila Anda menampilkan gambar detail atau konten media tepi-ke-tepi di belakang
|
||||
baris ini dan bila Anda menggunakan gradasi untuk memastikan ikon tetap terlihat.
|
||||
</p>
|
||||
|
||||
<p>Bila Anda menyesuaikan baris navigasi dan baris status, jadikan keduanya transparan atau modifikasi
|
||||
baris status saja. Baris navigasi harus tetap hitam di semua kasus lainnya.</p>
|
||||
|
||||
|
||||
<h2 id="Inheritance">Tampilan Setiap Tema</h3>
|
||||
|
||||
<p>Elemen dalam definisi layout XML bisa menetapkan atribut <code>android:theme</code>,
|
||||
yang merujuk sumber daya tema. Atribut ini memodifikasi tema untuk elemen itu dan setiap
|
||||
elemen anak, yang berguna untuk mengubah palet warna tema dalam porsi tertentu
|
||||
pada antarmuka.</p>
|
||||
@@ -0,0 +1,213 @@
|
||||
page.title=Gambar-dalam-gambar
|
||||
page.keywords=pratinjau,sdk,PIP,Gambar-dalam-gambar
|
||||
page.tags=androidn
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#declaring">Mendeklarasikan Bahwa Aktivitas Anda Mendukung
|
||||
Gambar-dalam-gambar</a></li>
|
||||
<li><a href="#pip_button">Mengalihkan Aktivitas Anda ke Gambar-dalam-gambar</a>
|
||||
</li>
|
||||
<li><a href="#handling_ui">Menangani UI Selama Gambar-dalam-gambar</a>
|
||||
</li>
|
||||
<li><a href="#continuing_playback">Melanjutkan Pemutaran Video Saat dalam
|
||||
Gambar-dalam-gambar</a></li>
|
||||
<li><a href="#single_playback">Menggunakan Aktivitas Pemutaran Tunggal untuk
|
||||
Gambar-dalam-gambar</a></li>
|
||||
<li><a href="#best">Praktik Terbaik</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>Lihat Juga</h2>
|
||||
<ol>
|
||||
<li><a href="{@docRoot}preview/features/multi-window.html">Dukungan
|
||||
Multi-Jendela</a></li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Di Android N, pengguna Android TV sekarang bisa menonton video
|
||||
dalam jendela yang disematkan di sudut layar saat menyusuri
|
||||
aplikasi. Mode gambar-dalam-gambar (PIP) memungkinkan aplikasi menjalankan aktivitas
|
||||
video dalam jendela yang disematkan selagi aktivitas lain tetap berjalan di
|
||||
latar belakang. Jendela PIP memungkinkan pengguna melakukan multitasking saat menggunakan aplikasi Anda, yang
|
||||
membantu pengguna menjadi lebih produktif.</p>
|
||||
|
||||
<p>Aplikasi Anda bisa memutuskan kapan memicu mode PIP. Inilah beberapa contoh
|
||||
kapan memasuki mode PIP:</p>
|
||||
|
||||
<ul>
|
||||
<li>Aplikasi Anda bisa memindahkan video ke dalam mode PIP bila pengguna mengarah
|
||||
mundur dari video untuk menjelajah materi lainnya.</li>
|
||||
<li>Aplikasi Anda bisa mengalihkan video ke dalam mode PIP selagi pengguna menonton akhir episode
|
||||
dari materi. Layar utama menampilkan informasi
|
||||
promosi atau rangkuman tentang episode berikutnya dalam seri tersebut.</li>
|
||||
<li>Aplikasi Anda bisa menyediakan suatu cara bagi pengguna untuk mengantre materi tambahan selagi
|
||||
mereka menonton video. Video terus dimainkan dalam mode PIP selagi layar
|
||||
utama menampilkan aktivitas pemilihan materi.</li>
|
||||
</ul>
|
||||
|
||||
<p>Jendela PIP memiliki luas 240x135 dp dan ditampilkan di layer paling atas pada salah satu
|
||||
dari empat sudut layar, yang dipilih oleh sistem. Pengguna bisa memunculkan
|
||||
menu PIP yang memungkinkan mereka untuk beralih mode dari jendela PIP ke layar penuh, atau menutup jendela
|
||||
PIP, dengan menekan dan menahan tombol <b>Beranda</b> pada remote. Jika video
|
||||
lain mulai diputar pada layar utama, jendela PIP secara otomatis
|
||||
ditutup. Pengguna juga bisa menutup jendela PIP melalui Recents.</p>
|
||||
|
||||
<img src="{@docRoot}images/android-7.0/pip-active.png" />
|
||||
<p class="img-caption"><strong>Gambar 1.</strong> Video
|
||||
Gambar-dalam-gambar terlihat di sudut layar selagi pengguna menjelajahi materi pada layar
|
||||
utama.</p>
|
||||
|
||||
<p>PIP memanfaatkan API multi-jendela yang tersedia di Android N untuk
|
||||
menyediakan jendela hamparan video yang disematkan. Untuk menambahkan PIP ke aplikasi, Anda harus
|
||||
mendaftarkan aktivitas yang mendukung PIP, mengalihkan aktivitas Anda ke mode PIP bila
|
||||
diperlukan, serta memastikan elemen UI disembunyikan dan pemutaran video berlanjut bila
|
||||
aktivitas dalam mode PIP.</p>
|
||||
|
||||
<h2 id="declaring">Mendeklarasikan Bahwa Aktivitas Anda Mendukung Gambar-dalam-gambar</h2>
|
||||
|
||||
<p>Secara default, sistem tidak secara otomatis mendukung PIP untuk aplikasi.
|
||||
Jika Anda ingin mendukung PIP dalam aplikasi, daftarkan aktivitas
|
||||
video Anda dalam manifes dengan menyetel
|
||||
<code>android:supportsPictureInPicture</code> dan
|
||||
<code>android:resizeableActivity</code> ke <code>true</code>. Juga, tetapkan
|
||||
bahwa aktivitas Anda menangani perubahan konfigurasi layout sehingga aktivitas
|
||||
Anda tidak diluncurkan ulang saat terjadi perubahan layout selama transisi mode PIP.</p>
|
||||
|
||||
<pre>
|
||||
<activity android:name="VideoActivity"
|
||||
android:resizeableActivity="true"
|
||||
android:supportsPictureInPicture="true"
|
||||
android:configChanges=
|
||||
"screenSize|smallestScreenSize|screenLayout|orientation"
|
||||
...
|
||||
</pre>
|
||||
|
||||
<p>Saat mendaftarkan aktivitas Anda, ingatlah bahwa dalam mode PIP aktivitas
|
||||
Anda akan ditampilkan pada jendela hamparan kecil pada layar TV. Aktivitas
|
||||
pemutaran video dengan UI minimal akan memberikan pengalaman pengguna terbaik. Aktivitas yang
|
||||
mengandung elemen UI kecil mungkin tidak memberikan pengalaman pengguna yang baik
|
||||
ketika beralih ke mode PIP, karena pengguna tidak dapat melihat elemen UI secara jelas
|
||||
di jendela PIP.</p>
|
||||
|
||||
<h2 id="pip_button">Mengalihkan Aktivitas Anda ke Gambar-dalam-gambar</h2>
|
||||
|
||||
Bila Anda perlu untuk mengalihkan aktivitas ke mode PIP, panggil
|
||||
<code>Activity.enterPictureInPictureMode()</code>. Contoh berikut mengalihkan
|
||||
ke mode PIP bila pengguna memilih tombol PIP khusus pada baris
|
||||
kontrol media:</p>
|
||||
|
||||
<pre>
|
||||
@Override
|
||||
public void onActionClicked(Action action) {
|
||||
if (action.getId() == R.id.lb_control_picture_in_picture) {
|
||||
getActivity().enterPictureInPictureMode();
|
||||
return;
|
||||
}
|
||||
...
|
||||
</pre>
|
||||
|
||||
<p>Menambahkan tombol PIP ke baris kontrol media Anda akan memungkinkan pengguna dengan mudah beralih
|
||||
ke mode PIP selagi mengontrol pemutaran video.</p>
|
||||
|
||||
<img src="{@docRoot}images/android-7.0/pip-button.png" />
|
||||
<p class="img-caption"><strong>Gambar 1.</strong> Tombol
|
||||
gambar-dalam-gambar pada baris kontrol media.</p>
|
||||
|
||||
<p>Android N menyertakan kelas
|
||||
<code>PlaybackControlsRow.PictureInPictureAction</code> baru yang mendefinisikan
|
||||
tindakan PIP baris kontrol dan menggunakan ikon PIP.</p>
|
||||
|
||||
<h2 id="handling_ui">Menangani UI Selama Gambar-dalam-gambar</h2>
|
||||
|
||||
<p>Bila aktivitas memasuki mode PIP, aktivitas Anda seharusnya hanya menampilkan pemutaran
|
||||
video. Buang elemen UI sebelum aktivitas Anda memasuki PIP,
|
||||
dan pulihkan elemen ini bila aktivitas Anda beralih ke layar penuh lagi.
|
||||
Ganti <code>Activity.onPictureInPictureModeChanged()</code> atau
|
||||
<code>Fragment.onPictureInPictureModeChanged()</code> dan aktifkan atau
|
||||
nonaktifkan elemen UI saat diperlukan, misalnya:</p>
|
||||
|
||||
<pre>
|
||||
@Override
|
||||
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
|
||||
if (isInPictureInPictureMode) {
|
||||
// Hide the controls in picture-in-picture mode.
|
||||
...
|
||||
} else {
|
||||
// Restore the playback UI based on the playback status.
|
||||
...
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2 id="continuing_playback">Melanjutkan Pemutaran Video Saat dalam
|
||||
Gambar-dalam-gambar</h2>
|
||||
|
||||
<p>Bila aktivitas Anda beralih ke PIP, sistem akan menganggap aktivitas tersebut berada dalam
|
||||
keadaan berhenti sementara, dan akan memanggil metode <code>onPause()</code> aktivitas Anda. Pemutaran
|
||||
video tidak boleh berhenti sementara dan harus terus diputar jika aktivitas tersebut
|
||||
berhenti sementara karena mode PIP. Periksa PIP dalam metode
|
||||
<code>onPause()</code> aktivitas Anda dan tangani pemutaran dengan tepat,
|
||||
misalnya:</p>
|
||||
|
||||
<pre>
|
||||
@Override
|
||||
public void onPause() {
|
||||
// If called while in PIP mode, do not pause playback
|
||||
if (isInPictureInPictureMode()) {
|
||||
// Continue playback
|
||||
...
|
||||
}
|
||||
// If paused but not in PIP, pause playback if necessary
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Bila aktivitas meninggalkan mode PIP dan kembali ke mode layar penuh, sistem
|
||||
akan melanjutkan aktivitas Anda dan memanggil metode <code>onResume()</code>.</p>
|
||||
|
||||
<h2 id="single_playback">Menggunakan Aktivitas Pemutaran Tunggal untuk
|
||||
Gambar-dalam-gambar</h2>
|
||||
|
||||
<p>Di aplikasi Anda, seorang pengguna bisa memilih video baru saat menyusuri materi di
|
||||
layar utama, selagi aktivitas pemutaran video dalam mode PIP. Putar
|
||||
video baru di aktivitas pemutaran yang ada dalam mode layar penuh, sebagai ganti
|
||||
meluncurkan aktivitas baru yang dapat membingungkan pengguna.</p>
|
||||
|
||||
<p>Guna memastikan aktivitas tunggal digunakan untuk permintaan pemutaran video dan
|
||||
beralih ke atau dari mode PIP bila dibutuhkan, setel
|
||||
<code>android:launchMode</code> aktivitas ke <code>singleTask</code> dalam manifes Anda:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<activity android:name="VideoActivity"
|
||||
...
|
||||
android:supportsPictureInPicture="true"
|
||||
android:launchMode="singleTask"
|
||||
...
|
||||
</pre>
|
||||
|
||||
<p>Di aktivitas Anda, ganti {@link android.app.Activity#onNewIntent
|
||||
Activity.onNewIntent()} dan tangani video baru, yang akan menghentikan pemutaran video
|
||||
jika diperlukan.</p>
|
||||
|
||||
<h2 id="best">Praktik Terbaik</h2>
|
||||
|
||||
<p>PIP ditujukan untuk aktivitas yang memutar video layar penuh. Saat mengalihkan
|
||||
aktivitas Anda ke mode PIP, hindari menampilkan apa pun selain materi video.
|
||||
Pantau saat aktivitas Anda memasuki mode PIP dan sembunyikan elemen UI, seperti dijelaskan
|
||||
dalam <a href="#handling_ui">Menangani UI Selama Gambar-dalam-gambar</a>.</p>
|
||||
|
||||
<p>Karena jendela PIP ditampilkan sebagai jendela mengambang di sudut
|
||||
layar, Anda harus menghindari menampilkan informasi penting di layar utama
|
||||
di area mana saja yang bisa terhalang oleh jendela PIP.</p>
|
||||
|
||||
<p>Bila aktivitas ada berada dalam mode PIP, secara default aktivitas itu tidak mendapatkan fokus masukan. Untuk
|
||||
menerima kejadian masukan saat dalam mode PIP, gunakan
|
||||
<code>MediaSession.setMediaButtonReceiver()</code>.</p>
|
||||
142
docs/html-intl/intl/id/training/tv/tif/content-recording.jd
Normal file
142
docs/html-intl/intl/id/training/tv/tif/content-recording.jd
Normal file
@@ -0,0 +1,142 @@
|
||||
page.title=Perekaman TV
|
||||
page.keywords=pratinjau,sdk,tv,perekaman
|
||||
page.tags=androidn
|
||||
page.image=images/cards/card-nyc_2x.jpg
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Dalam dokumen ini</h2>
|
||||
<ol>
|
||||
<li><a href="#supporting">Menunjukkan Dukungan untuk Perekaman</a></li>
|
||||
<li><a href="#recording">Merekam Sesi</a></li>
|
||||
<li><a href="#errors">Menangani Kesalahan Perekaman</a></li>
|
||||
<li><a href="#sessions">Mengelola Sesi yang Direkam</a></li>
|
||||
<li><a href="#best">Praktik Terbaik</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Layanan masukan TV memungkinkan pengguna menghentikan sementara dan melanjutkan pemutaran saluran melalui
|
||||
API perekaman. Android N telah berkembang hingga ke perekaman
|
||||
dengan memungkinkan pengguna menyimpan beberapa sesi rekaman.</p>
|
||||
|
||||
<p>Pengguna bisa menjadwalkan rekaman terlebih dahulu, atau memulai rekaman sambil menonton
|
||||
suatu acara. Setelah sistem menyimpan rekaman, pengguna bisa menjelajah, menata,
|
||||
dan memutar kembali rekaman tersebut menggunakan aplikasi TV di sistem.</p>
|
||||
|
||||
<p>Jika Anda ingin menyediakan fungsi perekaman untuk layanan masukan TV,
|
||||
Anda harus menunjukkan pada sistem bahwa aplikasi Anda mendukung perekaman, mengimplementasikan
|
||||
kemampuan merekam program, menangani dan mengomunikasikan kesalahan yang muncul
|
||||
selama perekaman, dan mengelola sesi perekaman Anda.</p>
|
||||
|
||||
<p class="note"><strong>Catatan:</strong> Aplikasi Live Channels belum
|
||||
menyediakan cara bagi pengguna untuk membuat atau mengakses perekaman. Hingga dibuat perubahan
|
||||
di aplikasi Live Channels, mungkin sulit menguji sepenuhnya pengalaman
|
||||
perekaman untuk layanan masukan TV Anda.</p>
|
||||
|
||||
<h2 id="supporting">Menunjukkan Dukungan untuk Perekaman</h2>
|
||||
|
||||
<p>Untuk memberi tahu sistem bahwa layanan masukan TV Anda mendukung perekaman, setel
|
||||
atribut <code>android:canRecord</code> di file XML metadata layanan Anda
|
||||
ke <code>true</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<tv-input xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<b>android:canRecord="true"</b>
|
||||
android:setupActivity="com.example.sampletvinput.SampleTvInputSetupActivity" />
|
||||
</pre>
|
||||
|
||||
<p>Untuk informasi selengkapnya mengenai layanan file metadata, lihat
|
||||
<a href="{@docRoot}training/tv/tif/tvinput.html#manifest">Mendeklarasikan Layanan Masukan TV Anda
|
||||
di Manifes</a>.
|
||||
</p>
|
||||
|
||||
<p>Atau, Anda bisa menunjukkan dukungan perekaman dalam kode Anda menggunakan
|
||||
langkah-langkah ini:</p>
|
||||
|
||||
<ol>
|
||||
<li>Dalam metode <code>TvInputService.onCreate()</code> Anda, buat objek
|
||||
<code>TvInputInfo</code> baru menggunakan kelas <code>TvInputInfo.Builder</code>.
|
||||
</li>
|
||||
<li>Saat membuat objek <code>TvInputInfo</code> baru, panggil
|
||||
<code>setCanRecord(true)</code> sebelum memanggil <code>build()</code> untuk
|
||||
menunjukkan layanan Anda mendukung perekaman.</li>
|
||||
<li>Daftarkan objek <code>TvInputInfo</code> Anda pada sistem dengan memanggil
|
||||
<code>TvInputManager.updateTvInputInfo()</code>.</li>
|
||||
</ol>
|
||||
|
||||
<h2 id="recording">Merekam Sesi</h2>
|
||||
|
||||
<p>Setelah layanan masukan TV Anda mendaftar bahwa mendukung fungsionalitas
|
||||
perekaman, sistem akan memanggil
|
||||
<code>TvInputService.onCreateRecordingSession()</code> bila perlu untuk mengakses
|
||||
implementasi perekaman aplikasi Anda. Implementasikan subkelas
|
||||
<code>TvInputService.RecordingSession</code> Anda sendiri dan kembalikan
|
||||
bila callback <code>onCreateRecordingSession()</code> dipicu.
|
||||
Subkelas ini bertanggung jawab mengalihkan ke saluran data yang benar,
|
||||
merekam data yang diminta, dan memberitahukan status perekaman serta kesalahan ke
|
||||
sistem.</p>
|
||||
|
||||
<p>Bila sistem memanggil <code>RecordingSession.onTune()</code>, dengan meneruskan
|
||||
URI saluran, setel ke saluran yang ditetapkan URI. Beri tahu sistem bahwa
|
||||
aplikasi Anda telah disetel ke saluran yang diinginkan dengan memanggil <code>notifyTuned()</code>,
|
||||
atau, jika aplikasi Anda tidak bisa disetel ke saluran yang tepat, panggil
|
||||
<code>notifyError()</code>.</p>
|
||||
|
||||
<p>Sistem berikutnya akan memanggil callback <code>RecordingSession.onStartRecording()</code>.
|
||||
Aplikasi Anda harus segera mulai merekam. Bila sistem memanggil
|
||||
callback ini, sistem mungkin akan memberikan URI yang berisi informasi tentang program
|
||||
yang akan direkam. Bila perekaman selesai, Anda perlu menyalin data
|
||||
ini ke tabel data <code>RecordedPrograms</code>.</p>
|
||||
|
||||
<p>Terakhir, sistem akan memanggil <code>RecordingSession.onStopRecording()</code>.
|
||||
Pada tahap ini, aplikasi Anda harus segera berhenti merekam. Anda juga perlu
|
||||
membuat entri dalam tabel <code>RecordedPrograms</code>. Entri ini harus
|
||||
menyertakan URI data sesi yang direkam dalam kolom
|
||||
<code>RecordedPrograms.COLUMN_RECORDING_DATA_URI</code>, dan informasi
|
||||
program yang diberikan sistem dalam panggilan awal ke
|
||||
<code>onStartRecording()</code>.</p>
|
||||
|
||||
<p>Untuk detail selengkapnya tentang cara mengakses tabel <code>RecordedPrograms</code>
|
||||
lihat <a href="#sessions">Mengelola Sesi yang Direkam</a>.</p>
|
||||
|
||||
<h2 id="errors">Menangani Kesalahan Perekaman</h2>
|
||||
|
||||
<p>Jika terjadi kesalahan selama perekaman, yang menghasilkan data terekam yang tidak bisa digunakan,
|
||||
beri tahu sistem dengan memanggil <code>RecordingSession.notifyError()</code>.
|
||||
Begitu juga, Anda bisa memanggil <code>notifyError()</code> setelah sesi rekaman dibuat
|
||||
agar sistem mengetahui bahwa aplikasi Anda tidak bisa lagi merekam sesi.</p>
|
||||
|
||||
<p>Jika terjadi kesalahan selama perekaman, namun Anda ingin menyediakan rekaman parsial
|
||||
yang bisa digunakan pengguna untuk pemutaran, panggil
|
||||
<code>RecordingSession.notifyRecordingStopped()</code> untuk memungkinkan sistem
|
||||
menggunakan sesi parsial.</p>
|
||||
|
||||
<h2 id="sessions">Mengelola Sesi yang Direkam</h2>
|
||||
|
||||
<p>Sistem menyimpan informasi untuk semua sesi yang direkam dari semua
|
||||
aplikasi saluran yang mampu merekam dalam tabel penyedia materi <code>TvContract.RecordedPrograms</code>.
|
||||
Informasi ini bisa diakses lewat URI materi
|
||||
<code>RecordedPrograms.Uri</code>. Gunakan API penyedia materi untuk
|
||||
membaca, menambahkan, dan menghapus entri dari tabel ini.</p>
|
||||
|
||||
<p>Untuk informasi selengkapnya tentang menangani data penyedia materi, lihat
|
||||
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
|
||||
Dasar-Dasar Penyedia Materi</a>.</p>
|
||||
|
||||
<h2 id="best">Praktik Terbaik</h2>
|
||||
|
||||
<p>Perangkat TV mungkin memiliki penyimpanan terbatas, jadi pertimbangkan sebaik mungkin saat
|
||||
mengalokasikan penyimpanan untuk menyimpan sesi rekaman. Gunakan
|
||||
<code>RecordingCallback.onError(RECORDING_ERROR_INSUFFICIENT_SPACE)</code> bila
|
||||
tidak cukup ruang untuk menyimpan sesi rekaman.</p>
|
||||
|
||||
<p>Bila pengguna memulai perekaman, Anda harus memulai perekaman data
|
||||
secepatnya. Untuk memfasilitasinya, selesaikan setiap tugas yang memakan waktu di awal,
|
||||
seperti mengakses dan mengalokasikan ruang penyimpanan, saat sistem memanggil callback
|
||||
<code>onCreateRecordingSession()</code>. Hal ini akan memungkinkan Anda memulai
|
||||
perekaman dengan segera bila callback <code>onStartRecording()</code>
|
||||
dipicu.</p>
|
||||
Reference in New Issue
Block a user