lightbulb_outline Help shape the future of the Google Play Console, Android Studio, and Firebase. Start survey

Setelan

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 Activity biasa yang menjadi host PreferenceFragment yang menampilkan setelan aplikasi Anda. Akan tetapi, Anda juga bisa menggunakan PreferenceActivity untuk 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 (true jika 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 adalah String.

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 PreferenceCategory atau PreferenceScreen, atau preferensi menetapkan Intent untuk dipanggil (bersama elemen <intent>) atau Fragment untuk ditampilkan (bersama atribut android: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 metodesetAction().
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:

  • Context aplikasi 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 (atau KEY_HAS_SET_DEFAULT_VALUES dalam 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:

  1. Memisahkan setiap kelompok setelan ke dalam beberapa instance PreferenceFragment terpisah. Ini berarti, setiap grup setelan memerlukan file XML terpisah.
  2. Membuat file header XML yang mencantumkan daftar setiap grup setelan dan mendeklarasikan fragmen mana yang berisi daftar setelan yang sesuai.
  3. Memperluas kelas PreferenceActivity untuk menjadi host setelan Anda.
  4. 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 Preference dengan nilai saat ini (atau default) bila muncul di tampilan.
  • Menyediakan nilai default bila diminta oleh sistem.
  • Jika Preference menyediakan 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);
}