Aplikasi sering kali menyertakan setelan yang memungkinkan pengguna memodifikasi fitur dan perilaku aplikasi. Misalnya, beberapa aplikasi memungkinkan pengguna untuk menetapkan apakah notifikasi diaktifkan atau menetapkan seberapa sering aplikasi menyinkronkan data dengan awan.
Jika ingin menyediakan setelan untuk aplikasi, Anda harus menggunakan
Preference Android API untuk membangun antarmuka yang konsisten dengan
pengalaman pengguna di aplikasi Android yang lain (termasuk setelan sistem). Dokumen ini menjelaskan
cara membangun setelan aplikasi Anda menggunakan Preference API.
Desain Setelan
Untuk informasi tentang cara mendesain setelan Anda, bacalah panduan desain Setelan.
Gambar 1. Tangkapan layar dari setelan aplikasi
Perpesanan Android. Memilih item yang didefinisikan oleh Preference
akan membuka antarmuka untuk mengubah setelan.
Ringkasan
Sebagai ganti menggunakan objek View untuk membangun antarmuka pengguna, setelan
dibangun menggunakan berbagai subkelas dari kelas Preference yang Anda
deklarasikan dalam file XML.
Objek Preference adalah blok pembangun untuk setelan
tunggal. Setiap Preference muncul sebagai item dalam daftar dan menyediakan UI
yang sesuai bagi pengguna untuk memodifikasi setelan. Misalnya, CheckBoxPreference membuat item daftar yang menampilkan kotak centang, dan ListPreference membuat item yang membuka dialog berisi daftar pilihan.
Setiap Preference yang Anda tambahkan memiliki pasangan nilai-kunci yang sesuai yang
digunakan sistem untuk menyimpan setelan dalam file SharedPreferences
default untuk setelan aplikasi Anda. Bila pengguna mengubah setelan, sistem akan memperbarui nilai
yang bersangkutan dalam file SharedPreferences untuk Anda. Satu-satunya saat di mana Anda harus
berinteraksi langsung dengan file SharedPreferences yang terkait adalah bila Anda
perlu membaca nilai untuk menentukan perilaku aplikasi berdasarkan setelan pengguna.
Nilai yang tersimpan di SharedPreferences untuk setiap setelan bisa berupa
tipe data berikut:
- Boolean
- Float
- Int
- Long
- String
- String
Set
Oleh karena UI setelan aplikasi Anda dibangun menggunakan objek Preference
sebagai ganti
objek View, Anda perlu menggunakan Activity khusus atau
subkelas Fragment untuk menampilkan setelan daftar:
- Jika aplikasi Anda mendukung versi Android yang lebih lama dari 3.0 (API level 10 dan yang lebih rendah), Anda harus
membangun aktivitas sebagai ekstensi dari kelas
PreferenceActivity. - Pada Android 3.0 dan yang lebih baru, sebaiknya Anda menggunakan
Activitybiasa yang menjadi hostPreferenceFragmentyang menampilkan setelan aplikasi Anda. Akan tetapi, Anda juga bisa menggunakanPreferenceActivityuntuk membuat layout dua panel bagi layar besar bila Anda memiliki beberapa grup setelan.
Cara menyiapkan PreferenceActivity Anda dan instance PreferenceFragment dibahas di bagian tentang Membuat Aktivitas Preferensi dan Menggunakan
Fragmen Preferensi.
Preferensi
Setiap setelan untuk aplikasi Anda diwakili oleh subkelas spesifik dari kelas Preference. Setiap subkelas menyertakan seperangkat properti utama yang memungkinkan Anda
untuk menetapkan berbagai hal seperti judul setelan dan nilai default. Setiap subkelas juga menyediakan
antarmuka pengguna dan properti khusus miliknya sendiri. Misalnya, gambar 1 menampilkan tangkapan layar dari
setelan aplikasi Perpesanan. Setiap item daftar dalam layar setelan didukung oleh objek Preference berbeda.
Beberapa preferensi yang paling umum adalah:
CheckBoxPreference- Menampilkan item dengan kotak centang untuk setelan yang diaktifkan atau dinonaktifkan. Nilai
tersimpan adalah boolean (
truejika diberi tanda cek). ListPreference- Membuka dialog berisi daftar tombol radio. Nilai tersimpan bisa berupa tipe nilai apa pun yang didukung (tercantum di atas).
EditTextPreference- Membuka dialog berisi widget
EditText. Nilai tersimpan adalahString.
Lihat kelas Preference untuk mengetahui daftar subkelas lain dan
propertinya.
Tentu saja, kelas bawaan tidak mengakomodasi setiap kebutuhan dan aplikasi Anda mungkin memerlukan
sesuatu yang lebih khusus. Misalnya, platform saat ini tidak menyediakan kelas Preference untuk memilih angka atau tanggal. Anda mungkin perlu mendefinisikan
subkelas Preference sendiri. Untuk bantuan melakukannya, lihat bagian tentang Membangun Preferensi Khusus.
Mendefinisikan Preferensi dalam XML
Meskipun bisa membuat instance objek Preference baru saat waktu proses, Anda
harus mendefinisikan daftar setelan dalam XML dengan hierarki objek Preference.
Menggunakan file XML untuk mendefinisikan sekumpulan setelan lebih disukai karena file
menyediakan struktur yang mudah dibaca dan diperbarui. Selain itu, setelan aplikasi Anda
umumnya telah ditetapkan sebelumnya, meskipun Anda masih bisa memodifikasi kumpulan tersebut saat waktu proses.
Setiap subkelas Preference bisa dideklarasikan bersama elemen XML yang
cocok dengan nama kelas, misalnya <CheckBoxPreference>.
Anda harus menyimpan file XML dalam direktori res/xml/. Walaupun bisa memberi nama file
sesuka Anda, biasanya file diberi nama preferences.xml. Biasanya Anda hanya memerlukan satu file,
karena cabang di hierarki (yang membuka daftar setelannya sendiri) dideklarasikan menggunakan instance
tersarang PreferenceScreen.
Catatan: Jika ingin membuat layout multipanel untuk setelan, Anda memerlukan file XML terpisah untuk setiap fragmen.
Simpul akar untuk file XML harus berupa elemen <PreferenceScreen>. Dalam elemen inilah Anda menambahkan setiap Preference. Setiap anak yang Anda tambahkan dalam elemen
<PreferenceScreen> akan tampak sebagai item
tunggal dalam daftar setelan.
Misalnya:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="pref_sync"
android:title="@string/pref_sync"
android:summary="@string/pref_sync_summ"
android:defaultValue="true" />
<ListPreference
android:dependency="pref_sync"
android:key="pref_syncConnectionType"
android:title="@string/pref_syncConnectionType"
android:dialogTitle="@string/pref_syncConnectionType"
android:entries="@array/pref_syncConnectionTypes_entries"
android:entryValues="@array/pref_syncConnectionTypes_values"
android:defaultValue="@string/pref_syncConnectionTypes_default" />
</PreferenceScreen>
Dalam contoh ini, terdapat CheckBoxPreference dan ListPreference. Kedua item tersebut menyertakan tiga atribut berikut:
android:key- Atribut ini diperlukan untuk preferensi yang mempertahankan nilai data. Ini menetapkan kunci
unik (string) yang digunakan sistem saat menyimpan nilai setelan ini dalam
SharedPreferences.Instance satu-satunya yang tidak memerlukan atribut ini adalah bila preferensi berupa
PreferenceCategoryatauPreferenceScreen, atau preferensi menetapkanIntentuntuk dipanggil (bersama elemen<intent>) atauFragmentuntuk ditampilkan (bersama atributandroid:fragment). android:title- Ini menyediakan nama setelan yang bisa dilihat oleh pengguna.
android:defaultValue- Ini menetapkan nilai awal yang harus disetel sistem dalam file
SharedPreferences. Anda harus memberikan nilai default untuk semua setelan.
Untuk informasi tentang semua atribut lain yang didukung, lihat dokumentasi Preference (dan subkelas masing-masing).
Gambar 2. Menyetel kategori
dengan judul.
1. Kategori ditetapkan oleh elemen <PreferenceCategory>.
2. Judul
ditetapkan dengan atribut android:title.
Bila daftar setelan Anda melebihi sekitar 10 item, Anda mungkin perlu menambahkan judul untuk mendefinisikan grup setelan atau menampilkan grup tersebut di layar terpisah. Opsi ini dijelaskan di bagian berikut.
Membuat grup setelan
Jika Anda menampilkan daftar 10 setelan atau lebih, pengguna mungkin akan kesulitan dalam memindai, memahami dan memprosesnya. Anda bisa mengatasinya dengan membagi sebagian atau semua setelan ke dalam beberapa grup, yang secara efektif akan mengubah satu daftar panjang menjadi beberapa daftar yang lebih pendek. Suatu grup setelan terkait bisa ditampilkan dalam salah satu dari dua cara:
Anda bisa menggunakan salah satu atau keduanya untuk mengelola setelan aplikasi Anda. Saat memutuskan mana yang akan digunakan dan cara membagi setelan, Anda harus mengikuti pedoman dalam Panduan Setelan Desain Android.
Menggunakan judul
Jika ingin menyediakan pembagi dengan heading di antara kelompok setelan (seperti yang ditampilkan dalam gambar 2),
tempatkan setiap kelompok objek Preference di dalam PreferenceCategory.
Misalnya:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/pref_sms_storage_title"
android:key="pref_key_storage_settings">
<CheckBoxPreference
android:key="pref_key_auto_delete"
android:summary="@string/pref_summary_auto_delete"
android:title="@string/pref_title_auto_delete"
android:defaultValue="false"... />
<Preference
android:key="pref_key_sms_delete_limit"
android:dependency="pref_key_auto_delete"
android:summary="@string/pref_summary_delete_limit"
android:title="@string/pref_title_sms_delete"... />
<Preference
android:key="pref_key_mms_delete_limit"
android:dependency="pref_key_auto_delete"
android:summary="@string/pref_summary_delete_limit"
android:title="@string/pref_title_mms_delete" ... />
</PreferenceCategory>
...
</PreferenceScreen>
Menggunakan sublayar
Jika ingin menempatkan kelompok setelan ke dalam sublayar (seperti yang ditampilkan dalam gambar 3), tempatkan kelompok
objek Preference di dalam PreferenceScreen.
Gambar 3. Menyetel sublayar. Elemen <PreferenceScreen>
membuat item yang, bila dipilih, akan membuka daftar terpisah untuk menampilkan setelan tersarang.
Misalnya:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!-- opens a subscreen of settings -->
<PreferenceScreen
android:key="button_voicemail_category_key"
android:title="@string/voicemail"
android:persistent="false">
<ListPreference
android:key="button_voicemail_provider_key"
android:title="@string/voicemail_provider" ... />
<!-- opens another nested subscreen -->
<PreferenceScreen
android:key="button_voicemail_setting_key"
android:title="@string/voicemail_settings"
android:persistent="false">
...
</PreferenceScreen>
<RingtonePreference
android:key="button_voicemail_ringtone_key"
android:title="@string/voicemail_ringtone_title"
android:ringtoneType="notification" ... />
...
</PreferenceScreen>
...
</PreferenceScreen>
Menggunakan maksud
Dalam beberapa kasus, Anda mungkin ingin item preferensi untuk membuka beberapa aktivitas sebagai ganti
layar setelan, seperti browser web untuk melihat laman web. Untuk memanggil Intent bila pengguna memilih item preferensi, tambahkan elemen <intent>
sebagai anak elemen <Preference> yang bersangkutan.
Misalnya, berikut ini cara menggunakan item preferensi untuk membuka laman web:
<Preference android:title="@string/prefs_web_page" >
<intent android:action="android.intent.action.VIEW"
android:data="http://www.example.com" />
</Preference>
Anda bisa membuat maksud implisit maupun eksplisit menggunakan atribut berikut:
android:action- Aksi yang akan ditetapkan, sesuai metode
setAction(). android:data- Data yang akan ditetapkan, sesuai metode
setData(). android:mimeType- Tipe MIME yang akan ditetapkan, sesuai metode
setType(). android:targetClass- Bagian kelas dari nama komponen, sesuai metode
setComponent(). android:targetPackage- Bagian paket dari nama komponen, sesuai metode
setComponent().
Membuat Aktivitas Preferensi
Untuk menampilkan setelan Anda dalam suatu aktivitas, perluas kelas PreferenceActivity. Ini adalah ekstensi dari kelas Activity biasa yang menampilkan daftar setelan berdasarkan hierarki objek Preference. PreferenceActivity
secara otomatis mempertahankan setelan yang dikaitkan dengan setiap Preference bila pengguna membuat perubahan.
Catatan: Jika Anda mengembangkan aplikasi untuk Android 3.0 dan
yang lebih tinggi, sebaiknya gunakan PreferenceFragment. Pindah ke bagian
berikutnya tentang Menggunakan Fragmen Preferensi.
Hal paling penting untuk diingat adalah jangan memuat layout tampilan selama callback onCreate(). Sebagai gantinya, panggil addPreferencesFromResource() untuk
menambahkan preferensi yang telah Anda deklarasikan dalam file XML ke aktivitas. Misalnya, berikut ini adalah kode minimum
polos yang diperlukan untuk PreferenceActivity fungsional:
public class SettingsActivity extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
Ini sebenarnya kode yang cukup untuk beberapa aplikasi, karena segera setelah pengguna memodifikasi preferensi,
sistem akan menyimpan perubahan tersebut ke file SharedPreferences default yang
bisa dibaca oleh komponen aplikasi Anda lainnya bila Anda perlu memeriksa setelan pengguna. Akan tetapi,
banyak aplikasi, yang memerlukan kode lebih sedikit untuk mendengarkan perubahan yang terjadi pada preferensi.
Untuk informasi tentang mendengarkan perubahan di file SharedPreferences,
lihat bagian tentang Preferensi Membaca.
Menggunakan Fragmen Preferensi
Jika Anda mengembangkan Android 3.0 (API level 11) dan yang lebih tinggi, Anda harus menggunakan PreferenceFragment untuk menampilkan daftar objek Preference
Anda. Anda bisa menambahkan PreferenceFragment ke aktivitas apa pun,—Anda tidak
perlu menggunakan PreferenceActivity.
Fragmen menyediakan arsitektur yang lebih
fleksibel untuk aplikasi Anda, dibandingkan hanya menggunakan aktivitas, apa pun jenis
aktivitas yang Anda bangun. Dengan sendirinya, kami menyarankan Anda menggunakan PreferenceFragment untuk mengontrol tampilan setelan sebagai ganti PreferenceActivity bila memungkinkan.
Implementasi PreferenceFragment Anda bisa semudah
mendefinisikan metode onCreate() untuk memuat
file preferensi dengan addPreferencesFromResource(). Misalnya:
public static class SettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
...
}
Anda nanti bisa menambahkan fragmen ini ke Activity seperti yang Anda lakukan untuk
Fragment lainnya. Misalnya:
public class SettingsActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
}
Catatan: PreferenceFragment tidak memiliki
objek Context sendiri. Jika memerlukan objek Context
, Anda bisa memanggil getActivity(). Akan tetapi, berhati-hatilah untuk memanggil
getActivity() hanya bila fragmen telah dikaitkan dengan aktivitas. Bila
fragmen belum dilampirkan, atau telah dilepas selama akhir daur hidupnya, getActivity() akan mengembalikan nol.
Menyetel Nilai Default
Preferensi yang Anda buat mungkin mendefinisikan beberapa perilaku penting untuk aplikasi, jadi Anda
perlu melakukan inisialisasi file SharedPreferences yang terkait dengan
nilai default untuk setiap Preference bila pengguna menggunakan aplikasi
Anda untuk pertama kali.
Hal pertama yang harus Anda lakukan adalah menetapkan nilai default untuk setiap objek Preference
di file XML dengan menggunakan atribut android:defaultValue. Nilainya bisa berupa tipe data
apa saja yang sesuai untuk objek Preference bersangkutan. Misalnya
:
<!-- default value is a boolean -->
<CheckBoxPreference
android:defaultValue="true"
... />
<!-- default value is a string -->
<ListPreference
android:defaultValue="@string/pref_syncConnectionTypes_default"
... />
Kemudian, dari metode onCreate() dalam aktivitas utama aplikasi
Anda—dan dalam aktivitas lainnya yang digunakan pengguna untuk masuk ke aplikasi Anda untuk pertama kali
—panggil setDefaultValues():
PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);
Memanggil ini selama onCreate() akan memastikan
Anda melakukan inisialisasi aplikasi dengan setelan default, yang mungkin perlu
dibaca oleh aplikasi Anda untuk menentukan beberapa perilaku (seperti apakah akan mengunduh data pada
jaringan seluler).
Metode ini membutuhkan tiga argumen:
Contextaplikasi Anda.- ID sumber daya untuk file XML preferensi yang ingin Anda atur nilai defaultnya.
- Boolean menunjukkan apakah nilai default harus diatur lebih dari satu kali.
Bila
false, sistem akan mengatur nilai default hanya jika metode ini belum pernah dipanggil sebelumnya (atauKEY_HAS_SET_DEFAULT_VALUESdalam file preferensi berbagi nilai default salah).
Selama Anda menyetel argumen ketiga ke false, Anda bisa dengan aman memanggil metode ini
setiap kali aktivitas Anda memulai tanpa mengesampingkan preferensi tersimpan pengguna dengan menyetel ulang preferensi tersebut ke
default. Akan tetapi, jika mengatur ke true, Anda akan mengganti nilai
sebelumnya dengan default.
Menggunakan Header Preferensi
Dalam kasus yang jarang terjadi, Anda mungkin perlu mendesain setelan agar layar pertama
hanya menampilkan daftar sublayar (seperti dalam aplikasi Setting pada sistem,
seperti yang ditampilkan dalam gambar 4 dan 5). Bila mengembangkan desain seperti itu untuk Android 3.0 dan yang lebih tinggi, Anda
harus menggunakan fitur "header", sebagai ganti membangun sublayar dengan elemen
PreferenceScreen tersarang.
Untuk membangun setelan dengan header, Anda perlu:
- Memisahkan setiap kelompok setelan ke dalam beberapa instance
PreferenceFragmentterpisah. Ini berarti, setiap grup setelan memerlukan file XML terpisah. - Membuat file header XML yang mencantumkan daftar setiap grup setelan dan mendeklarasikan fragmen mana yang berisi daftar setelan yang sesuai.
- Memperluas kelas
PreferenceActivityuntuk menjadi host setelan Anda. - Mengimplementasikan callback
onBuildHeaders()untuk menetapkan file header.
Manfaat besar dalam menggunakan desain ini adalah karena PreferenceActivity
secara otomatis akan menampilkan layout dua panel yang ditampilkan dalam gambar 4 bila dijalankan pada layar besar.
Bahkan jika aplikasi Anda mendukung versi Android yang lebih lama dari 3.0, Anda bisa membangun
aplikasi untuk menggunakan PreferenceFragment bagi presentasi dua panel pada perangkat
yang lebih baru sementara tetap mendukung hierarki multilayar biasa pada perangkat
yang lebih lama (lihat bagian tentang Mendukung versi yang lebih lama dengan
header preferensi).
Gambar 4. Layout dua panel dengan header.
1. Header
didefinisikan dengan file header XML.
2. Setiap kelompok setelan didefinisikan oleh
PreferenceFragment yang ditetapkan oleh elemen <header> dalam
file header.
Gambar 5. Perangkat handset dengan header setelan. Bila sebuah
item dipilih, PreferenceFragment terkait akan menggantikan
header.
Membuat file header
Setiap kelompok setelan dalam daftar header Anda ditetapkan oleh elemen <header>
tunggal dalam elemen <preference-headers> akar. Misalnya:
<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
<header
android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
android:title="@string/prefs_category_one"
android:summary="@string/prefs_summ_category_one" />
<header
android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
android:title="@string/prefs_category_two"
android:summary="@string/prefs_summ_category_two" >
<!-- key/value pairs can be included as arguments for the fragment. -->
<extra android:name="someKey" android:value="someHeaderValue" />
</header>
</preference-headers>
Bersama atribut android:fragment, setiap header mendeklarasikan instance PreferenceFragment yang harus terbuka saat pengguna memilih header.
Elemen <extras> memungkinkan Anda meneruskan pasangan nilai-kunci ke fragmen di Bundle. Fragmen bisa mengambil argumen dengan memanggil getArguments(). Anda bisa meneruskan argumen ke fragmen dengan berbagai
alasan, namun satu alasan yang baik adalah untuk menggunakan kembali subkelas yang sama dari PreferenceFragment bagi setiap kelompok dan menggunakan argumen untuk menetapkan file
XML preferensi yang harus dimuat fragmen.
Misalnya, inilah fragmen yang bisa digunakan kembali untuk berbagai kelompok setelan, bila setiap
header mendefinisikan argumen <extra> bersama kunci "settings":
public static class SettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String settings = getArguments().getString("settings");
if ("notifications".equals(settings)) {
addPreferencesFromResource(R.xml.settings_wifi);
} else if ("sync".equals(settings)) {
addPreferencesFromResource(R.xml.settings_sync);
}
}
}
Menampilkan header
Untuk menampilkan header preferensi, Anda harus mengimplementasikan metode callback onBuildHeaders() dan memanggil
loadHeadersFromResource(). Misalnya:
public class SettingsActivity extends PreferenceActivity {
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
}
Bila pengguna memilih item dari daftar header, sistem akan membuka PreferenceFragment terkait.
Catatan: Saat menggunakan header preferensi, subkelas PreferenceActivity Anda tidak perlu mengimplementasikan metode onCreate(), karena satu-satunya tugas
yang diperlukan untuk aktivitas adalah memuat header.
Mendukung versi yang lebih lama dengan header preferensi
Jika aplikasi Anda mendukung versi Android yang lebih lama dari 3.0, Anda tetap bisa menggunakan header untuk
menyediakan layout dua panel saat berjalan pada Android 3.0 dan yang lebih tinggi. Anda hanya perlu membuat
file XML preferensi tambahan yang menggunakan elemen <Preference> dasar yang berperilaku seperti item header (untuk digunakan oleh Android
versi yang lebih lama).
Akan tetapi, sebagai ganti membuka PreferenceScreen baru, setiap elemen <Preference> mengirimkan Intent ke
PreferenceActivity yang menetapkan file XML preferensi yang
akan dimuat.
Misalnya, inilah file XML untuk header preferensi yang menggunakan Android 3.0
dan yang lebih tinggi (res/xml/preference_headers.xml):
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
<header
android:fragment="com.example.prefs.SettingsFragmentOne"
android:title="@string/prefs_category_one"
android:summary="@string/prefs_summ_category_one" />
<header
android:fragment="com.example.prefs.SettingsFragmentTwo"
android:title="@string/prefs_category_two"
android:summary="@string/prefs_summ_category_two" />
</preference-headers>
Dan inilah file preferensi yang menyediakan header yang sama untuk versi yang lebih lama dari
Android 3.0 (res/xml/preference_headers_legacy.xml):
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:title="@string/prefs_category_one"
android:summary="@string/prefs_summ_category_one" >
<intent
android:targetPackage="com.example.prefs"
android:targetClass="com.example.prefs.SettingsActivity"
android:action="com.example.prefs.PREFS_ONE" />
</Preference>
<Preference
android:title="@string/prefs_category_two"
android:summary="@string/prefs_summ_category_two" >
<intent
android:targetPackage="com.example.prefs"
android:targetClass="com.example.prefs.SettingsActivity"
android:action="com.example.prefs.PREFS_TWO" />
</Preference>
</PreferenceScreen>
Karena dukungan untuk <preference-headers> telah ditambahkan di Android 3.0, sistem akan memanggil
onBuildHeaders() di PreferenceActivity hanya saat berjalan pada Android 3.0 atau yang lebih tinggi. Untuk memuat
file header "lawas" (preference_headers_legacy.xml), Anda harus memeriksa versi Android
dan, jika versi tersebut lebih lama dari Android 3.0 (HONEYCOMB), panggil addPreferencesFromResource() untuk
memuat file header lawas. Misalnya:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
// Load the legacy preferences headers
addPreferencesFromResource(R.xml.preference_headers_legacy);
}
}
// Called only on Honeycomb and later
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
Satu-satunya hal yang perlu dilakukan adalah menangani Intent yang diteruskan ke
aktivitas untuk mengidentifikasi file preferensi yang akan dimuat. Jadi ambillah aksi maksud dan bandingkan dengan
string aksi yang diketahui; yang telah Anda gunakan dalam tag <intent> XML preferensi:
final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE";
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String action = getIntent().getAction();
if (action != null && action.equals(ACTION_PREFS_ONE)) {
addPreferencesFromResource(R.xml.preferences);
}
...
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
// Load the legacy preferences headers
addPreferencesFromResource(R.xml.preference_headers_legacy);
}
}
Ketahuilah bahwa panggilan berturut-turut ke addPreferencesFromResource() akan
menumpuk semua preferensi ke dalam satu daftar, jadi pastikan bahwa ini hanya dipanggil sekali dengan merangkai ketentuan
bersama pernyataan else-if.
Preferensi Membaca
Secara default, semua preferensi aplikasi Anda disimpan ke file yang bisa diakses dari mana saja
di dalam aplikasi dengan memanggil metode statis PreferenceManager.getDefaultSharedPreferences(). Ini akan mengembalikan objek SharedPreferences berisi semua pasangan nilai-kunci yang terkait
dengan objek Preference yang digunakan di PreferenceActivity Anda.
Misalnya, inilah cara membaca salah satu nilai preferensi dari aktivitas lain dalam aplikasi Anda:
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, "");
Mendengarkan perubahan preferensi
Ada beberapa alasan yang membuat Anda perlu mendapatkan pemberitahuan segera setelah pengguna mengubah salah satu
preferensi. Untuk menerima callback saat perubahan terjadi pada salah satu preferensi,
implementasikan antarmuka SharedPreference.OnSharedPreferenceChangeListener dan daftarkan listener untuk objek
SharedPreferences dengan memanggil registerOnSharedPreferenceChangeListener().
Antarmuka tersebut hanya memiliki satu metode callback, onSharedPreferenceChanged(), dan mungkin lebih mudah mengimplementasikan antarmuka sebagai bagian dari
aktivitas Anda. Misalnya:
public class SettingsActivity extends PreferenceActivity
implements OnSharedPreferenceChangeListener {
public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType";
...
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key.equals(KEY_PREF_SYNC_CONN)) {
Preference connectionPref = findPreference(key);
// Set summary to be the user-description for the selected value
connectionPref.setSummary(sharedPreferences.getString(key, ""));
}
}
}
Dalam contoh ini, metode akan memeriksa apakah setelan yang diubah adalah untuk kunci preferensi yang diketahui. Ini akan
memanggil findPreference() untuk mendapatkan objek
Preference yang diubah agar bisa memodifikasi rangkuman item
menjadi keterangan pada pilihan pengguna. Yakni, bila setelannya adalah ListPreference atau setelan multipilihan lain, Anda harus memanggil setSummary() bila setelan berubah untuk menampilkan
status saat ini (misalnya setelan Tidur yang ditampilkan dalam gambar 5).
Catatan: Seperti dijelaskan dalam dokumen Desain Android tentang Setelan, kami merekomendasikan Anda untuk memperbarui
rangkuman ListPreference setiap kali pengguna mengubah preferensi untuk
menjelaskan setelan saat ini.
Untuk manajemen daur hidup yang baik di aktivitas, kami menyarankan Anda untuk mendaftarkan dan mencabut pendaftaran
SharedPreferences.OnSharedPreferenceChangeListener selama callback onResume() dan onPause():
@Override
protected void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
@Override
protected void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
Perhatian: Bila Anda memanggil registerOnSharedPreferenceChangeListener(), pengelola preferensi saat ini tidak akan
menyimpan referensi kuat ke listener. Anda harus menyimpan referensi
kuat bagi listener, atau referensi akan rentan terhadap pengumpulan sampah. Kami
merekomendasikan Anda untuk mempertahankan referensi bagi listener dalam data instance objek
yang akan ada selama Anda memerlukan listener tersebut.
Misalnya, dalam kode berikut, pemanggil tidak menyimpan referensi ke listener. Akibatnya, listener akan dikenakan pengumpulan sampah, dan suatu saat nanti akan gagal:
prefs.registerOnSharedPreferenceChangeListener(
// Bad! The listener is subject to garbage collection!
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
// listener implementation
}
});
Sebagai gantinya, simpan referensi ke listener dalam bidang data instance objek yang akan ada selama listener dibutuhkan:
SharedPreferences.OnSharedPreferenceChangeListener listener =
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
// listener implementation
}
};
prefs.registerOnSharedPreferenceChangeListener(listener);
Mengelola Penggunaan Jaringan
Mulai Android 4.0, aplikasi Settings untuk sistem memungkinkan pengguna melihat seberapa besar data jaringan yang digunakan aplikasi mereka saat berada di latar depan dan latar belakang. Kemudian pengguna bisa menonaktifkan penggunaan data latar belakang untuk aplikasi individual. Agar pengguna tidak menonaktifkan akses aplikasi ke data dari latar belakang, Anda harus menggunakan koneksi data secara efisien dan mengizinkan pengguna untuk menyaring penggunaan data aplikasi melalui setelan aplikasi Anda.
Misalnya, Anda bisa mengizinkan pengguna untuk mengontrol seberapa sering aplikasi menyinkronkan data, apakah aplikasi hanya melakukan unggahan/unduhan bila ada Wi-Fi, apakah aplikasi menggunakan data saat roaming, dll. Dengan tersedianya kontrol ini bagi pengguna, mereka kemungkinan besar tidak akan menonaktifkan akses aplikasi ke data saat mendekati batas yang mereka tetapkan dalam Settings pada sistem, karena mereka bisa mengontrol secara tepat seberapa besar data yang digunakan aplikasi Anda.
Setelah menambahkan preferensi yang diperlukan dalam PreferenceActivity
Anda untuk mengontrol kebiasaan data aplikasi, Anda harus menambahkan filter maksud untuk ACTION_MANAGE_NETWORK_USAGE dalam file manifes. Misalnya:
<activity android:name="SettingsActivity" ... >
<intent-filter>
<action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Filter maksud ini menunjukkan pada sistem bahwa ini adalah aktivitas yang mengontrol penggunaan
data aplikasi Anda. Jadi, saat pengguna memeriksa seberapa banyak data yang digunakan oleh aplikasi dari
aplikasi Settings pada sistem, tombol View application settings akan tersedia dan menjalankan
PreferenceActivity sehingga pengguna bisa menyaring seberapa besar data yang digunakan
aplikasi Anda.
Membangun Preferensi Khusus
Kerangka kerja Android menyertakan berbagai subkelas Preference yang
memungkinkan Anda membangun UI untuk beberapa macam tipe setelan.
Akan tetapi, Anda dapat mencari setelan yang diperlukan bila tidak ada solusi bawaan, seperti
picker nomor atau picker tanggal. Dalam hal demikian, Anda akan perlu membuat preferensi khusus dengan memperluas
kelas Preference atau salah satu subkelas lainnya.
Bila memperluas kelas Preference, ada beberapa hal
penting yang perlu Anda lakukan:
- Menetapkan antarmuka pengguna yang akan muncul saat pengguna memilih setelan.
- Menyimpan nilai setelan bila perlu.
- Melakukan inisialisasi
Preferencedengan nilai saat ini (atau default) bila muncul di tampilan. - Menyediakan nilai default bila diminta oleh sistem.
- Jika
Preferencemenyediakan UI sendiri (seperti dialog), simpan dan pulihkan status untuk menangani perubahan daur hidup (seperti saat pengguna memutar layar).
Bagian berikut menjelaskan cara melakukan setiap tugas ini.
Menetapkan antarmuka pengguna
Jika secara langsung memperluas kelas Preference, Anda perlu mengimplementasikan
onClick() untuk mendefinisikan aksi yang terjadi bila pengguna
memilih item tersebut. Akan tetapi, sebagian besar setelan khusus memperluas DialogPreference untuk
menampilkan dialog, sehingga menyederhanakan prosedur. Bila memperluas DialogPreference, Anda harus memanggil setDialogLayoutResourcs() selama di
konstruktor kelas untuk menetapkan layout dialog.
Misalnya, inilah konstruktor untuk DialogPreference khusus yang mendeklarasikan layout dan menetapkan teks untuk tombol dialog
negatif dan positif default:
public class NumberPickerPreference extends DialogPreference {
public NumberPickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setDialogLayoutResource(R.layout.numberpicker_dialog);
setPositiveButtonText(android.R.string.ok);
setNegativeButtonText(android.R.string.cancel);
setDialogIcon(null);
}
...
}
Menyimpan nilai setelan
Anda bisa menyimpan nilai setelan kapan saja dengan memanggil salah satu metode persist*() kelas Preference, misalnya persistInt() jika nilai setelan adalah integer atau
persistBoolean() untuk menyimpan boolean.
Catatan: Setiap Preference hanya bisa menyimpan satu
tipe data, jadi Anda harus menggunakan metode persist*() yang tepat untuk tipe data yang digunakan
oleh Preference khusus Anda.
Bila Anda memilih untuk mempertahankannya, setelan bisa bergantung pada kelas Preference yang Anda perluas. Jika Anda memperluas DialogPreference, maka Anda harus mempertahankan nilai hanya bila dialog
ditutup karena hasil positif (pengguna memilih tombol "OK").
Bila DialogPreference ditutup, sistem akan memanggil metode onDialogClosed(). Metode mencakup argumen
boolean yang menetapkan apakah hasil pengguna "positif"—jika nilainya
true, maka pengguna memilih tombol positif dan Anda harus menyimpan nilai baru. Misalnya:
@Override
protected void onDialogClosed(boolean positiveResult) {
// When the user selects "OK", persist the new value
if (positiveResult) {
persistInt(mNewValue);
}
}
Dalam contoh ini, mNewValue adalah anggota kelas yang menampung nilai
setelan saat ini. Memanggil persistInt() akan menyimpan nilai
ke file SharedPreferences (secara otomatis menggunakan kunci yang
ditetapkan dalam file XML untuk Preference ini).
Menginisialisasi nilai saat ini
Bila sistem menambahkan Preference Anda ke layar, ia
akan memanggil onSetInitialValue() untuk memberi tahu
Anda apakah setelan memiliki nilai yang dipertahankan. Jika tidak ada nilai yang dipertahankan, panggilan ini
akan menyediakan nilai default bagi Anda.
Metode onSetInitialValue() akan meneruskan
boolean, restorePersistedValue, untuk menunjukkan apakah nilai dipertahankan
untuk setelan. Jika true, maka Anda harus mengambil nilai yang dipertahankan dengan memanggil
salah satu metode getPersisted*() kelas Preference, misalnya getPersistedInt() untuk nilai integer. Anda biasanya
perlu mengambil nilai yang dipertahankan agar bisa memperbarui UI dengan benar untuk merefleksikan
nilai yang tersimpan sebelumnya.
Jika restorePersistedValue adalah false, maka Anda
harus menggunakan nilai default yang diteruskan dalam argumen kedua.
@Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
if (restorePersistedValue) {
// Restore existing state
mCurrentValue = this.getPersistedInt(DEFAULT_VALUE);
} else {
// Set default state from the XML attribute
mCurrentValue = (Integer) defaultValue;
persistInt(mCurrentValue);
}
}
Setiap metode getPersisted*() mengambil satu argumen yang menetapkan
nilai default yang akan digunakan jika tidak ada nilai yang dipertahankan atau kunci tidak ada. Dalam contoh
di atas, konstanta lokal yang digunakan untuk menetapkan nilai default jika getPersistedInt() tidak bisa mengembalikan nilai yang dipertahankan.
Perhatian: Anda tidak bisa menggunakan
defaultValue sebagai nilai default dalam metode getPersisted*(), karena
nilainya selalu nol bila restorePersistedValue adalah true.
Menyediakan nilai default
Jika instance kelas Preference Anda menetapkan nilai default
(dengan atribut android:defaultValue), maka
sistem akan memanggil onGetDefaultValue() bila ia membuat instance objek untuk mengambil nilai. Anda harus mengimplementasikan
metode ini agar sistem bisa menyimpan nilai default dalam SharedPreferences. Misalnya:
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getInteger(index, DEFAULT_VALUE);
}
Argumen metode menyediakan semua hal yang Anda perlukan: larik atribut dan posisi
indeks android:defaultValue, yang harus Anda ambil. Alasan Anda harus
mengimplementasikan metode ini untuk mengekstrak nilai default dari atribut adalah karena Anda harus menetapkan
nilai default lokal untuk atribut jika nilai tidak didefinisikan.
Menyimpan dan memulihkan status Preferensi
Seperti halnya View di layout, subkelas Preference
Anda bertanggung jawab menyimpan dan memulihkan statusnya jika aktivitas atau fragmen
dimulai ulang (seperti saat pengguna memutar layar). Untuk menyimpan
dan memulihkan status kelas Preference dengan benar, Anda harus mengimplementasikan
metode callback daur hidup onSaveInstanceState() dan onRestoreInstanceState().
Status Preference Anda didefinisikan oleh objek yang mengimplementasikan
antarmuka Parcelable. Kerangka kerja Android menyediakan objek seperti itu untuk Anda gunakan
sebagai titik mulai dalam mendefinisikan objek status: kelas Preference.BaseSavedState.
Untuk mendefinisikan cara kelas Preference menyimpan statusnya, Anda harus
memperluas kelas Preference.BaseSavedState. Anda hanya perlu mengganti
beberapa metode dan mendefinisikan objek CREATOR
.
Untuk sebagian besar aplikasi, Anda bisa menyalin implementasi berikut dan tinggal mengubah baris yang
menangani value jika subkelas Preference Anda menyimpan tipe
data selain integer.
private static class SavedState extends BaseSavedState {
// Member that holds the setting's value
// Change this data type to match the type saved by your Preference
int value;
public SavedState(Parcelable superState) {
super(superState);
}
public SavedState(Parcel source) {
super(source);
// Get the current preference's value
value = source.readInt(); // Change this to read the appropriate data type
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
// Write the preference's value
dest.writeInt(value); // Change this to write the appropriate data type
}
// Standard creator object using an instance of this class
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
Dengan implementasi Preference.BaseSavedState di atas yang ditambahkan
ke aplikasi Anda (biasanya sebagai subkelas dari subkelas Preference), Anda
nanti perlu mengimplementasikan metode onSaveInstanceState() dan onRestoreInstanceState() untuk subkelas
Preference Anda.
Misalnya:
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
// Check whether this Preference is persistent (continually saved)
if (isPersistent()) {
// No need to save instance state since it's persistent,
// use superclass state
return superState;
}
// Create instance of custom BaseSavedState
final SavedState myState = new SavedState(superState);
// Set the state's value with the class member that holds current
// setting value
myState.value = mNewValue;
return myState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
// Check whether we saved the state in onSaveInstanceState
if (state == null || !state.getClass().equals(SavedState.class)) {
// Didn't save the state, so call superclass
super.onRestoreInstanceState(state);
return;
}
// Cast state to custom BaseSavedState and pass to superclass
SavedState myState = (SavedState) state;
super.onRestoreInstanceState(myState.getSuperState());
// Set this Preference's widget to reflect the restored state
mNumberPicker.setValue(myState.value);
}