1page.title=설정 2page.tags=preference,preferenceactivity,preferencefragment 3 4@jd:body 5 6 7<div id="qv-wrapper"> 8<div id="qv"> 9 10<h2>이 문서의 내용</h2> 11<ol> 12 <li><a href="#Overview">개요</a> 13 <ol> 14 <li><a href="#SettingTypes">기본 설정</a></li> 15 </ol> 16 </li> 17 <li><a href="#DefiningPrefs">XML로 기본 설정 정의하기</a> 18 <ol> 19 <li><a href="#Groups">설정 그룹 만들기</a></li> 20 <li><a href="#Intents">인텐트 사용하기</a></li> 21 </ol> 22 </li> 23 <li><a href="#Activity">기본 설정 액티비티 만들기</a></li> 24 <li><a href="#Fragment">기본 설정 프래그먼트 사용하기</a></li> 25 <li><a href="#Defaults">설정 기본 값</a></li> 26 <li><a href="#PreferenceHeaders">기본 설정 헤더 사용하기</a> 27 <ol> 28 <li><a href="#CreateHeaders">헤더 파일 만들기</a></li> 29 <li><a href="#DisplayHeaders">헤더 표시하기</a></li> 30 <li><a href="#BackCompatHeaders">기본 설정 헤더로 이전 버전 지원하기</a></li> 31 </ol> 32 </li> 33 <li><a href="#ReadingPrefs">기본 설정 읽기</a> 34 <ol> 35 <li><a href="#Listening">기본 설정 변경 수신 대기</a></li> 36 </ol> 37 </li> 38 <li><a href="#NetworkUsage">네트워크 사용량 관리하기</a></li> 39 <li><a href="#Custom">사용자 지정 기본 설정 구축하기</a> 40 <ol> 41 <li><a href="#CustomSelected">사용자 인터페이스 지정하기</a></li> 42 <li><a href="#CustomSave">설정의 값 저장하기</a></li> 43 <li><a href="#CustomInitialize">현재 값 초기화하기</a></li> 44 <li><a href="#CustomDefault">기본 값 제공하기</a></li> 45 <li><a href="#CustomSaveState">기본 설정의 상태 저장 및 복원하기</a></li> 46 </ol> 47 </li> 48</ol> 49 50<h2>Key 클래스</h2> 51<ol> 52 <li>{@link android.preference.Preference}</li> 53 <li>{@link android.preference.PreferenceActivity}</li> 54 <li>{@link android.preference.PreferenceFragment}</li> 55</ol> 56 57 58<h2>참고 항목</h2> 59<ol> 60 <li><a href="{@docRoot}design/patterns/settings.html">설정 디자인 가이드</a></li> 61</ol> 62</div> 63</div> 64 65 66 67 68<p>애플리케이션에는 종종 설정이 포함되어 있어 사용자가 앱 기능과 행동을 수정할 수 있게 해줍니다. 예를 들어 69몇몇 앱은 사용자에게 알림을 활성화할지 여부를 지정하거나 애플리케이션이 70클라우드와 데이터를 동기화할 빈도를 지정할 수 있게 해줍니다.</p> 71 72<p>자신의 앱에 설정을 제공하고자 하는 경우, Android의 73{@link android.preference.Preference} API를 사용하여 다른 Android 앱(시스템 설정 포함)의 사용자 환경과 74일관성을 유지하는 인터페이스를 구축할 수 있게 해야 합니다. 이 문서에서는 75{@link android.preference.Preference} API를 사용하여 앱 설정을 구축하는 방법을 설명합니다.</p> 76 77<div class="note design"> 78<p><strong>설정 디자인</strong></p> 79 <p>설정을 디자인하는 방법에 관련된 정보는 <a href="{@docRoot}design/patterns/settings.html">설정</a> 디자인 가이드를 읽어보십시오.</p> 80</div> 81 82 83<img src="{@docRoot}images/ui/settings/settings.png" alt="" width="435" /> 84<p class="img-caption"><strong>그림 1.</strong> Android 메시지 앱의 설정에서 가져온 85스크린샷입니다. {@link android.preference.Preference}가 정의한 항목을 선택하면 86인터페이스가 열려 설정을 변경할 수 있게 됩니다.</p> 87 88 89 90 91<h2 id="Overview">개요</h2> 92 93<p>사용자 인터페이스를 구축할 때에는 {@link android.view.View} 객체를 사용하지만, 설정은 그 대신 94{@link android.preference.Preference} 클래스의 다양한 하위 클래스를 사용하여 구축합니다. 95이와 같은 하위 클래스는 XML 파일에서 선언합니다.</p> 96 97<p>{@link android.preference.Preference} 객체는 하나의 설정을 이루는 기본 98단위입니다. 각각의 {@link android.preference.Preference}는 목록의 항목으로 99나타나며 사용자가 설정을 수정하기에 적절한 UI를 제공합니다. 예를 들어 {@link 100android.preference.CheckBoxPreference}는 확인란을 표시하는 목록 항목을 만들고, {@link 101android.preference.ListPreference}는 선택 목록이 있는 대화를 여는 항목을 만듭니다.</p> 102 103<p>각각의 {@link android.preference.Preference}를 추가할 때마다 상응하는 키-값 쌍이 있어 104시스템이 이를 사용하여 해당 설정을 앱의 설정에 대한 기본 {@link android.content.SharedPreferences} 105파일에 저장합니다. 사용자가 설정을 변경하면 시스템이 106{@link android.content.SharedPreferences} 파일에 있는 상응하는 값을 개발자 대신 업데이트합니다. 개발자가 직접 107연관된 {@link android.content.SharedPreferences} 파일과 상호 작용을 해야 하는 경우는 108사용자의 설정을 기반으로 앱의 동작을 결정하기 위해 값을 읽어야 할 때뿐입니다.</p> 109 110<p>각 설정에 대하여 {@link android.content.SharedPreferences}에 저장된 값은 다음과 같은 111데이터 유형 중 한 가지를 취할 수 있습니다.</p> 112 113<ul> 114 <li>Boolean</li> 115 <li>Float</li> 116 <li>Int</li> 117 <li>Long</li> 118 <li>String</li> 119 <li>String {@link java.util.Set}</li> 120</ul> 121 122<p>앱의 설정 UI는 123{@link android.view.View} 객체 대신 124{@link android.preference.Preference} 객체를 사용하여 구축되기 때문에, 목록 설정을 표시하려면 특수 {@link android.app.Activity} 또는 125{@link android.app.Fragment} 하위 클래스를 사용해야 합니다.</p> 126 127<ul> 128 <li>앱이 Android 3.0 이전 버전(API 레벨 10 이하)을 지원하는 경우, 액티비티를 구축할 때 129{@link android.preference.PreferenceActivity} 클래스의 확장으로 구축해야 합니다.</li> 130 <li>Android 3.0 이후의 경우에는 대신 기존의 {@link android.app.Activity}를 131사용해야 합니다. 이것은 앱 설정을 표시하는 {@link android.preference.PreferenceFragment}를 호스팅합니다. 132하지만, 여러 개의 설정 그룹이 있는 경우 {@link android.preference.PreferenceActivity}를 사용하여 133대형 화면에 맞는 창 두 개짜리 레이아웃을 만들 수도 있습니다.</li> 134</ul> 135 136<p>{@link android.preference.PreferenceActivity}와 {@link 137android.preference.PreferenceFragment}의 인스턴스를 설정하는 방법은 <a href="#Activity">기본 설정 액티비티 만들기</a>와 <a href="#Fragment">기본 설정 138프래그먼트 사용하기</a>에 관련된 섹션에서 논합니다.</p> 139 140 141<h3 id="SettingTypes">기본 설정</h3> 142 143<p>앱에 대한 설정은 모두 {@link 144android.preference.Preference} 클래스의 특정 하위 클래스로 표현됩니다. 각 하위 클래스에 핵심 속성이 한 세트씩 포함되어 있어 145설정의 제목과 기본 값 등과 같은 것을 지정할 수 있게 해줍니다. 각 하위 클래스는 또한 자신만의 146특수 속성과 사용자 인터페이스도 제공합니다. 예를 들어, 그림 1에서는 메시지 앱의 설정에서 147가져온 스크린샷을 나타낸 것입니다. 설정 화면에 있는 각 목록 항목은 각기 서로 다른 {@link 148android.preference.Preference} 객체로 지원됩니다.</p> 149 150<p>가장 보편적인 기본 설정을 몇 가지만 소개하면 다음과 같습니다.</p> 151 152<dl> 153 <dt>{@link android.preference.CheckBoxPreference}</dt> 154 <dd>활성화되었거나 비활성화된 설정에 대한 확인란이 있는 항목을 표시합니다. 저장된 값은 155부울입니다(확인란이 선택된 경우 <code>true</code>).</dd> 156 157 <dt>{@link android.preference.ListPreference}</dt> 158 <dd>무선 버튼 목록이 있는 대화를 엽니다. 저장된 값은 159지원되는 값 유형(위에 목록으로 나열) 중 어느 것이라도 될 수 있습니다.</dd> 160 161 <dt>{@link android.preference.EditTextPreference}</dt> 162 <dd>{@link android.widget.EditText} 위젯이 있는 대화를 엽니다. 저장된 값은 {@link 163java.lang.String}입니다.</dd> 164</dl> 165 166<p>다른 모든 하위 클래스와 이에 상응하는 속성의 목록을 보려면 {@link android.preference.Preference} 167 클래스를 참조하십시오.</p> 168 169<p>물론 기본 제공 클래스만으로는 필요한 것을 모두 충족할 수 없고 앱에 무언가 좀 더 특수한 것이 170필요할 수도 있습니다. 예를 들어 플랫폼은 현재 숫자나 날짜를 선택할 수 있는 {@link 171android.preference.Preference} 클래스를 제공하지 않습니다. 따라서 개발자 나름대로 172{@link android.preference.Preference} 하위 클래스를 정의해야 할 수도 있습니다. 이 작업을 수행하는 데 유용한 내용인 <a href="#Custom">사용자 지정 기본 설정 구축하기</a>에 관한 섹션을 참조하십시오.</p> 173 174 175 176<h2 id="DefiningPrefs">XML로 기본 설정 정의하기</h2> 177 178<p>새로운 {@link android.preference.Preference} 객체를 런타임에 인스턴트화하는 것도 가능하지만, 179설정 목록을 정의할 때에는 {@link android.preference.Preference} 180객체의 계층과 함께 XML을 사용해야 합니다. 설정 컬렉션을 정의하는 데 XM 파일을 사용하는 것이 선호되는 이유는 이 파일이 181읽기 쉬운 구조를 제공하여 업데이트가 단순하기 때문입니다. 또한, 앱의 설정은 보통 182미리 정의되어 있습니다. 다만 개발자도 여전히 런타임에 설정 컬렉션을 수정할 수 있습니다.</p> 183 184<p>각 {@link android.preference.Preference} 하위 클래스는 클래스 이름에 일치하는 XML 요소로 185선언하면 됩니다. 예를 들면 {@code <CheckBoxPreference>}가 이에 해당됩니다.</p> 186 187<p>이 XML 파일은 반드시 {@code res/xml/} 디렉터리에 저장해야 합니다. 파일의 이름은 무엇이든 원하는 대로 지정할 수 있지만, 188일반적으로는 {@code preferences.xml}이라고 명명합니다. 파일은 하나만 필요한 것이 보통입니다. 189왜냐하면 계층에 있는 분기(자신만의 설정 목록을 엶)는 190{@link android.preference.PreferenceScreen}의 중첩된 인스턴스를 사용하여 선언되기 때문입니다.</p> 191 192<p class="note"><strong>참고:</strong> 설정에 다중 창 레이아웃을 만들고자 하는 경우, 193각 프래그먼트에 대해 별도의 XML 파일이 필요합니다.</p> 194 195<p>XML 파일의 루트 노드는 반드시 {@link android.preference.PreferenceScreen 196<PreferenceScreen>} 요소여야 합니다. 바로 이 요소 내에 각 {@link 197android.preference.Preference}를 추가하는 것입니다. 198{@link android.preference.PreferenceScreen <PreferenceScreen>} 요소 내에 추가하는 각 하위는 설정 목록에서 199각기 항목 하나씩으로 나타납니다.</p> 200 201<p>예:</p> 202 203<pre> 204<?xml version="1.0" encoding="utf-8"?> 205<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 206 <CheckBoxPreference 207 android:key="pref_sync" 208 android:title="@string/pref_sync" 209 android:summary="@string/pref_sync_summ" 210 android:defaultValue="true" /> 211 <ListPreference 212 android:dependency="pref_sync" 213 android:key="pref_syncConnectionType" 214 android:title="@string/pref_syncConnectionType" 215 android:dialogTitle="@string/pref_syncConnectionType" 216 android:entries="@array/pref_syncConnectionTypes_entries" 217 android:entryValues="@array/pref_syncConnectionTypes_values" 218 android:defaultValue="@string/pref_syncConnectionTypes_default" /> 219</PreferenceScreen> 220</pre> 221 222<p>이 예시에서는 {@link android.preference.CheckBoxPreference}와 {@link 223android.preference.ListPreference}가 하나씩 있습니다. 두 항목 모두 다음과 같은 세 가지 속성을 포함하고 있습니다.</p> 224 225<dl> 226 <dt>{@code android:key}</dt> 227 <dd>이 속성은 데이터 값을 유지하는 기본 설정에 필수입니다. 이것은 고유키(문자)를 228나타내며, 시스템이 이것을 사용하여 이 설정의 값을 {@link 229android.content.SharedPreferences}에 저장합니다. 230 <p>이 속성이 <em>필요하지 않은</em> 인스턴스는 기본 설정이 231{@link android.preference.PreferenceCategory} 또는 {@link android.preference.PreferenceScreen}인 경우, 또는 232기본 설정이 {@link android.content.Intent}를 호출할 것을 나타내거나(<a href="#Intents">{@code <intent>}</a> 요소로) {@link android.app.Fragment}를 표시하도록 지정하는 경우(<a href="{@docRoot}reference/android/preference/Preference.html#attr_android:fragment">{@code 233android:fragment}</a> 속성으로)뿐입니다.</p> 234 </dd> 235 <dt>{@code android:title}</dt> 236 <dd>이것은 설정에 대하여 사용자가 볼 수 있는 이름을 제공합니다.</dd> 237 <dt>{@code android:defaultValue}</dt> 238 <dd>이것은 시스템이 {@link 239android.content.SharedPreferences} 파일에 설정해야 하는 초기 값을 나타냅니다. 모든 설정에 기본 값을 제공해야 240합니다.</dd> 241</dl> 242 243<p>다른 모든 지원되는 속성에 대해서는 {@link 244android.preference.Preference}(및 각각의 하위 클래스) 관련 문서를 참조하십시오.</p> 245 246 247<div class="figure" style="width:300px"> 248 <img src="{@docRoot}images/ui/settings/settings-titles.png" alt="" /> 249 <p class="img-caption"><strong>그림 2.</strong> 제목이 있는 설정 250카테고리입니다. <br/><b>1.</b> 카테고리는 {@link 251android.preference.PreferenceCategory <PreferenceCategory>} 요소가 지정합니다. <br/><b>2.</b> 제목은 252{@code android:title} 속성으로 지정합니다.</p> 253</div> 254 255 256<p>설정 목록이 약 10개 항목을 초과하면 제목을 추가하여 257설정 그룹을 정의하거나, 해당 그룹을 별도의 258화면에 표시하는 것이 좋을 수도 있습니다. 이러한 옵션은 다음 섹션에 설명되어 있습니다.</p> 259 260 261<h3 id="Groups">설정 그룹 만들기</h3> 262 263<p>10개 이상의 설정 목록을 제시하는 경우, 사용자가 264이들을 둘러보고 이해하며 처리하는 데 어려움을 겪을 수 있습니다. 이 문제를 해결하려면 265설정의 일부 또는 모두를 그룹으로 나누어 사실상 하나의 긴 목록을 여러 개의 더 짧은 목록으로 266바꿔주면 됩니다. 관련된 설정 그룹 하나를 나타낼 때에는 다음과 같은 두 가지 방식 중 하나를 택하면 됩니다.</p> 267 268<ul> 269 <li><a href="#Titles">제목 사용하기</a></li> 270 <li><a href="#Subscreens">보조 화면 사용하기</a></li> 271</ul> 272 273<p>이와 같은 그룹화 기법 중 하나 또는 둘 모두를 사용하여 앱의 설정을 조직화할 수 있습니다. 어느 것을 274사용할지, 설정을 어떻게 나눌지 결정할 때에는 Android 275디자인의 <a href="{@docRoot}design/patterns/settings.html">설정</a> 가이드에 있는 지침을 따라야 합니다.</p> 276 277 278<h4 id="Titles">제목 사용하기</h4> 279 280<p>여러 개의 설정 그룹 사이에 구분선과 제목을 제공하고자 하는 경우(그림 2에 표시된 것과 같이), 281각 {@link android.preference.Preference} 객체 그룹을 {@link 282android.preference.PreferenceCategory} 내부에 배치합니다.</p> 283 284<p>예:</p> 285 286<pre> 287<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 288 <PreferenceCategory 289 android:title="@string/pref_sms_storage_title" 290 android:key="pref_key_storage_settings"> 291 <CheckBoxPreference 292 android:key="pref_key_auto_delete" 293 android:summary="@string/pref_summary_auto_delete" 294 android:title="@string/pref_title_auto_delete" 295 android:defaultValue="false"... /> 296 <Preference 297 android:key="pref_key_sms_delete_limit" 298 android:dependency="pref_key_auto_delete" 299 android:summary="@string/pref_summary_delete_limit" 300 android:title="@string/pref_title_sms_delete"... /> 301 <Preference 302 android:key="pref_key_mms_delete_limit" 303 android:dependency="pref_key_auto_delete" 304 android:summary="@string/pref_summary_delete_limit" 305 android:title="@string/pref_title_mms_delete" ... /> 306 </PreferenceCategory> 307 ... 308</PreferenceScreen> 309</pre> 310 311 312<h4 id="Subscreens">보조 화면 사용하기</h4> 313 314<p>설정 그룹 여러 개를 보조 화면에 배치하고자 하는 경우(그림 3에 표시된 것과 같이), 해당 315{@link android.preference.Preference} 객체 그룹을 {@link 316android.preference.PreferenceScreen} 안에 배치합니다.</p> 317 318<img src="{@docRoot}images/ui/settings/settings-subscreen.png" alt="" /> 319<p class="img-caption"><strong>그림 3.</strong> 설정 보조 화면입니다. {@code 320<PreferenceScreen>} 요소가 321항목을 만들며, 이 항목이 선택되면 별도의 목록이 열려 중첩된 설정을 표시합니다.</p> 322 323<p>예:</p> 324 325<pre> 326<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 327 <!-- opens a subscreen of settings --> 328 <PreferenceScreen 329 android:key="button_voicemail_category_key" 330 android:title="@string/voicemail" 331 android:persistent="false"> 332 <ListPreference 333 android:key="button_voicemail_provider_key" 334 android:title="@string/voicemail_provider" ... /> 335 <!-- opens another nested subscreen --> 336 <PreferenceScreen 337 android:key="button_voicemail_setting_key" 338 android:title="@string/voicemail_settings" 339 android:persistent="false"> 340 ... 341 </PreferenceScreen> 342 <RingtonePreference 343 android:key="button_voicemail_ringtone_key" 344 android:title="@string/voicemail_ringtone_title" 345 android:ringtoneType="notification" ... /> 346 ... 347 </PreferenceScreen> 348 ... 349</PreferenceScreen> 350</pre> 351 352 353<h3 id="Intents">인텐트 사용하기</h3> 354 355<p>어떤 경우에는 기본 설정 항목을 사용하여 설정 화면 대신 여러 가지 액티비티를 356열고자 할 수도 있습니다. 예를 들어 웹 브라우저를 열어 웹 페이지를 보는 것이 이에 해당됩니다. 사용자가 기본 설정 항목을 선택할 때 {@link 357android.content.Intent}를 호출하도록 하려면, {@code <intent>} 358요소를 상응하는 {@code <Preference>} 요소의 하위로 추가하면 됩니다.</p> 359 360<p>예를 들어 다음은 기본 설정 항목을 사용하여 웹 페이지를 열도록 하는 방법입니다.</p> 361 362<pre> 363<Preference android:title="@string/prefs_web_page" > 364 <intent android:action="android.intent.action.VIEW" 365 android:data="http://www.example.com" /> 366</Preference> 367</pre> 368 369<p>다음 속성을 사용하여 명시적 인텐트와 암시적 인텐트 두 가지를 모두 만들 수 있습니다.</p> 370 371<dl> 372 <dt>{@code android:action}</dt> 373 <dd>할당할 작업이며, {@link android.content.Intent#setAction setAction()} 374메서드를 따릅니다.</dd> 375 <dt>{@code android:data}</dt> 376 <dd>할당할 데이터이며, {@link android.content.Intent#setData setData()} 메서드를 따릅니다.</dd> 377 <dt>{@code android:mimeType}</dt> 378 <dd>할당할 MIME 유형이며, {@link android.content.Intent#setType setType()} 379메서드를 따릅니다.</dd> 380 <dt>{@code android:targetClass}</dt> 381 <dd>구성 요소 이름의 클래스 부분이며, {@link android.content.Intent#setComponent 382setComponent()} 메서드를 따릅니다.</dd> 383 <dt>{@code android:targetPackage}</dt> 384 <dd>구성 요소 이름의 패키지 부분이며, {@link 385android.content.Intent#setComponent setComponent()} 메서드를 따릅니다.</dd> 386</dl> 387 388 389 390<h2 id="Activity">기본 설정 액티비티 만들기</h2> 391 392<p>설정을 액티비티에서 표시하려면 {@link 393android.preference.PreferenceActivity} 클래스를 확장하면 됩니다. 이것은 일반적인 {@link 394android.app.Activity} 클래스 확장의 일종입니다. 이는 {@link 395android.preference.Preference} 객체의 계층에 기반한 설정 목록을 표시합니다. {@link android.preference.PreferenceActivity}는 396사용자가 변경 작업을 하면 각 {@link 397android.preference.Preference}와 연관된 설정을 유지합니다.</p> 398 399<p class="note"><strong>참고:</strong> Android 3.0 이상에 맞춰 애플리케이션을 개발하는 경우, 400대신 {@link android.preference.PreferenceFragment}를 사용해야 합니다. 다음 섹션의 401<a href="#Fragment">기본 설정 프래그먼트 사용하기</a> 관련 내용을 참조하십시오.</p> 402 403<p>여기서 기억해야 할 가장 중요한 점은 {@link 404android.preference.PreferenceActivity#onCreate onCreate()} 콜백 중에 보기 레이아웃을 로딩해서는 안 된다는 것입니다. 그 대신 {@link 405android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()}를 호출하여 406XML 파일에서 선언한 기본 설정을 액티비티에 추가합니다. 예를 들어 다음은 기능적인 407{@link android.preference.PreferenceActivity}에 필요한 가장 최소한의 코드를 나타낸 것입니다.</p> 408 409<pre> 410public class SettingsActivity extends PreferenceActivity { 411 @Override 412 public void onCreate(Bundle savedInstanceState) { 413 super.onCreate(savedInstanceState); 414 addPreferencesFromResource(R.xml.preferences); 415 } 416} 417</pre> 418 419<p>사실 이 코드만으로 몇몇 앱에는 충분합니다. 사용자가 기본 설정을 수정하자마자 420시스템이 해당 변경을 기본 {@link android.content.SharedPreferences} 파일에 저장하여, 421사용자의 설정을 확인해야 할 때 다른 애플리케이션 구성 요소가 이를 읽을 수 있도록 하기 때문입니다. 하지만 422대다수의 앱은 기본 설정에 일어나는 변경을 수신 대기하기 위해 약간의 코드가 더 필요합니다. 423{@link android.content.SharedPreferences} 파일에 일어나는 변경을 수신 대기하는 데 관한 424자세한 정보는 <a href="#ReadingPrefs">기본 설정 읽기</a>에 관한 섹션을 참조하십시오.</p> 425 426 427 428 429<h2 id="Fragment">기본 설정 프래그먼트 사용하기</h2> 430 431<p>Android 3.0(API 레벨 11) 이상에 맞춰 개발하는 경우, {@link 432android.preference.PreferenceFragment}를 사용하여 {@link android.preference.Preference} 433객체 목록을 표시해야 합니다. {@link android.preference.PreferenceFragment}는 모든 액티비티에 추가할 수 있습니다. 즉, 434{@link android.preference.PreferenceActivity}를 사용하지 않아도 됩니다.</p> 435 436<p><a href="{@docRoot}guide/components/fragments.html">프래그먼트</a>는 액티비티만 437사용하는 것에 비해 애플리케이션에 보다 유연한 아키텍처를 제공하며, 이는 구축하는 438액티비티의 종류와 무관하게 적용됩니다. 따라서 설정 표시를 제어하는 데에는 {@link 439android.preference.PreferenceFragment}를 {@link 440android.preference.PreferenceActivity} 대신 사용하는 방안을 권장합니다(가능한 경우).</p> 441 442<p>{@link android.preference.PreferenceFragment} 구현은 매우 간단합니다. 443{@link android.preference.PreferenceFragment#onCreate onCreate()} 메서드를 정의하여 기본 설정 파일을 444{@link android.preference.PreferenceFragment#addPreferencesFromResource 445addPreferencesFromResource()}로 로딩하도록 하기만 하면 됩니다. 예:</p> 446 447<pre> 448public static class SettingsFragment extends PreferenceFragment { 449 @Override 450 public void onCreate(Bundle savedInstanceState) { 451 super.onCreate(savedInstanceState); 452 453 // Load the preferences from an XML resource 454 addPreferencesFromResource(R.xml.preferences); 455 } 456 ... 457} 458</pre> 459 460<p>그런 다음 이 프래그먼트를 {@link android.app.Activity}에 추가하기만 하면 되고, 이는 다른 모든 461{@link android.app.Fragment}에서와 마찬가지입니다. 예:</p> 462 463<pre> 464public class SettingsActivity extends Activity { 465 @Override 466 protected void onCreate(Bundle savedInstanceState) { 467 super.onCreate(savedInstanceState); 468 469 // Display the fragment as the main content. 470 getFragmentManager().beginTransaction() 471 .replace(android.R.id.content, new SettingsFragment()) 472 .commit(); 473 } 474} 475</pre> 476 477<p class="note"><strong>참고:</strong> {@link android.preference.PreferenceFragment}에는 자신만의 478{@link android.content.Context} 객체가 없습니다. {@link android.content.Context} 479객체가 필요한 경우, {@link android.app.Fragment#getActivity()}를 호출하면 됩니다. 하지만, 480{@link android.app.Fragment#getActivity()}를 호출하는 것은 프래그먼트가 액티비티에 첨부되어 있는 경우만으로 국한시켜야 한다는 점을 유의하십시오. 프래그먼트가 481아직 첨부되지 않았거나 수명 주기가 끝날 무렵 분리된 경우, {@link 482android.app.Fragment#getActivity()}가 null을 반환합니다.</p> 483 484 485<h2 id="Defaults">설정 기본 값</h2> 486 487<p>여러분이 만드는 기본 설정은 애플리케이션에 중요한 동작을 정의하는 경우가 많을 것입니다. 따라서 488연관된 {@link android.content.SharedPreferences} 파일을 489각 {@link android.preference.Preference}에 대한 기본 값으로 초기화하여 사용자가 애플리케이션을 처음 열 때 490적용하는 것이 중요합니다.</p> 491 492<p>가장 먼저 해야 할 일은 XML 파일 내의 각 {@link 493android.preference.Preference} 494객체에 대해 기본 값을 지정하는 것입니다. 이때 {@code android:defaultValue} 속성을 사용합니다. 이 값은 상응하는 495{@link android.preference.Preference} 객체에 대해 적절한 어느 데이터 유형이라도 될 수 있습니다. 예: 496</p> 497 498<pre> 499<!-- default value is a boolean --> 500<CheckBoxPreference 501 android:defaultValue="true" 502 ... /> 503 504<!-- default value is a string --> 505<ListPreference 506 android:defaultValue="@string/pref_syncConnectionTypes_default" 507 ... /> 508</pre> 509 510<p>그런 다음, 애플리케이션의 기본 액티비티에 있는 {@link android.app.Activity#onCreate onCreate()} 511메서드로부터—또한 사용자가 애플리케이션에 처음으로 들어올 통로가 될 수 있는 512다른 모든 액티비티도 포함—{@link android.preference.PreferenceManager#setDefaultValues 513setDefaultValues()}를 호출합니다.</p> 514 515<pre> 516PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false); 517</pre> 518 519<p>이것을 {@link android.app.Activity#onCreate onCreate()} 중에 호출하면 520애플리케이션이 기본 설정으로 적절히 초기화되도록 보장할 수 있습니다. 이것은 애플리케이션이 521몇 가지 동작을 결정하기 위해 읽어야 할 수도 있습니다(예를 들어 셀룰러 네트워크에서 데이터를 522다운로드할지 여부 등).</p> 523 524<p>이 메서드는 다음과 같은 세 개의 인수를 취합니다.</p> 525<ul> 526 <li>애플리케이션 {@link android.content.Context}.</li> 527 <li>기본 값을 설정하고자 하는 기본 설정 XML 파일에 대한 리소스 ID입니다.</li> 528 <li>기본 값을 한 번 이상 설정해야 하는지 여부를 나타내는 부울 값입니다. 529<p><code>false</code>인 경우, 시스템은 이 메서드가 전에 한 번도 호출된 적이 없을 경우에만 530기본 값을 설정합니다(아니면 기본 값을 공유한 기본 설정 파일에 있는 {@link android.preference.PreferenceManager#KEY_HAS_SET_DEFAULT_VALUES} 531가 안전합니다).</p></li> 532</ul> 533 534<p>세 번째 인수를 <code>false</code>로 설정해 두는 한 이 메서드를 액티비티가 시작될 때마다 535안전하게 호출할 수 있으며, 그렇게 해도 사용자의 저장된 기본 설정을 기본값으로 초기화하여 536재정의하지 않습니다. 하지만 이를 <code>true</code>로 설정하면, 이전의 모든 값을 537기본 값으로 재정의하게 됩니다.</p> 538 539 540 541<h2 id="PreferenceHeaders">기본 설정 헤더 사용하기</h2> 542 543<p>드문 경우지만 설정을 디자인할 때 첫 화면에는 544<a href="#Subscreens">보조 화면</a> 목록만 표시하도록 하고자 할 수도 있습니다(예: 시스템 설정 앱, 545그림 4와 5 참조). 그러한 디자인을 Android 3.0 이상을 대상으로 개발하는 경우, Android 3.0에 있는 546새로운 "헤더" 기능을 사용해야 합니다. 이것이 중첩된 547{@link android.preference.PreferenceScreen} 요소를 사용하여 보조 화면을 구축하는 방안을 대신합니다.</p> 548 549<p>헤더를 사용하여 설정을 구축하려면 다음과 같이 해야 합니다.</p> 550<ol> 551 <li>각 설정 그룹을 별개의 {@link 552android.preference.PreferenceFragment} 인스턴스로 구분합니다. 다시 말해, 설정 그룹마다 별도의 XML 파일이 하나씩 있어야 한다는 553뜻입니다.</li> 554 <li>각 설정 그룹을 목록으로 나열하는 XML 헤더 파일을 생성하고 어느 프래그먼트에 555상응하는 설정 목록이 들어있는지 선언합니다.</li> 556 <li>{@link android.preference.PreferenceActivity} 클래스를 확장하여 설정을 호스팅하도록 합니다.</li> 557 <li>{@link 558android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} 콜백을 구현하여 헤더 파일을 559나타냅니다.</li> 560</ol> 561 562<p>이 디자인을 사용하는 데 있어 커다란 이점은 {@link android.preference.PreferenceActivity}가 563(앱이) 대형 화면에서 실행될 때 그림 4에서 나타낸 것과 같이 창 두 개짜리 레이아웃을 자동으로 표시한다는 것입니다.</p> 564 565<p>애플리케이션이 Android 3.0 이전 버전을 지원한다 하더라도 애플리케이션이 566{@link android.preference.PreferenceFragment}를 사용하여 567신형 기기에서 창 두 개짜리 표시를 지원하도록 하면서도 구형 기기에서는 일반적인 다중 화면 계층을 568여전히 지원하도록 할 수도 있습니다(<a href="#BackCompatHeaders">기본 설정 헤더로 569이전 버전 지원하기</a>를 참조하십시오).</p> 570 571<img src="{@docRoot}images/ui/settings/settings-headers-tablet.png" alt="" /> 572<p class="img-caption"><strong>그림 4.</strong> 헤더가 있는 창 두 개짜리 레이아웃입니다. <br/><b>1.</b> 헤더는 573XML 헤더 파일로 정의됩니다. <br/><b>2.</b> 각 설정 그룹은 574{@link android.preference.PreferenceFragment}가 정의하며, 이는 헤더 파일에 있는 {@code <header>} 요소가 575지정합니다.</p> 576 577<img src="{@docRoot}images/ui/settings/settings-headers-handset.png" alt="" /> 578<p class="img-caption"><strong>그림 5.</strong> 설정 헤더가 있는 핸드셋 기기입니다. 항목을 선택하면 579연관된 {@link android.preference.PreferenceFragment}가 헤더를 580대체합니다.</p> 581 582 583<h3 id="CreateHeaders" style="clear:left">헤더 파일 만들기</h3> 584 585<p>헤더 목록에 있는 각 설정 그룹은 루트 {@code <preference-headers>} 586요소 안에 있는 {@code <header>} 요소 하나로 나타냅니다. 예:</p> 587 588<pre> 589<?xml version="1.0" encoding="utf-8"?> 590<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> 591 <header 592 android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne" 593 android:title="@string/prefs_category_one" 594 android:summary="@string/prefs_summ_category_one" /> 595 <header 596 android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo" 597 android:title="@string/prefs_category_two" 598 android:summary="@string/prefs_summ_category_two" > 599 <!-- key/value pairs can be included as arguments for the fragment. --> 600 <extra android:name="someKey" android:value="someHeaderValue" /> 601 </header> 602</preference-headers> 603</pre> 604 605<p>각 헤더는 {@code android:fragment} 속성으로 {@link 606android.preference.PreferenceFragment} 예를 선언하며 이는 사용자가 헤더를 선택하면 열려야 합니다.</p> 607 608<p>{@code <extras>} 요소를 사용하면 키-값 쌍을 {@link 609android.os.Bundle} 내의 프래그먼트에 전달할 수 있게 해줍니다. 이 프래그먼트가 인수를 검색하려면 {@link 610android.app.Fragment#getArguments()}를 호출하면 됩니다. 인수를 프래그먼트에 전달하는 데에는 여러 가지 이유가 있을 수 있지만, 611한 가지 중요한 이유를 예로 들면 각 그룹에 대해 {@link 612android.preference.PreferenceFragment}의 같은 하위 클래스를 재사용하고, 이 인수를 사용하여 해당 프래그먼트가 로딩해야 하는 613기본 설정 XML 파일이 무엇인지 나타낼 수 있다는 점입니다.</p> 614 615<p>예를 들어 다음은 여러 가지 설정 그룹에 재사용할 수 있는 프래그먼트입니다. 이것은 616각 헤더가 {@code "settings"} 키로 {@code <extra>} 인수를 정의하는 경우를 나타낸 것입니다.</p> 617 618<pre> 619public static class SettingsFragment extends PreferenceFragment { 620 @Override 621 public void onCreate(Bundle savedInstanceState) { 622 super.onCreate(savedInstanceState); 623 624 String settings = getArguments().getString("settings"); 625 if ("notifications".equals(settings)) { 626 addPreferencesFromResource(R.xml.settings_wifi); 627 } else if ("sync".equals(settings)) { 628 addPreferencesFromResource(R.xml.settings_sync); 629 } 630 } 631} 632</pre> 633 634 635 636<h3 id="DisplayHeaders">헤더 표시하기</h3> 637 638<p>기본 설정 헤더를 표시하려면 {@link 639android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} 콜백 메서드를 구현하고 640{@link android.preference.PreferenceActivity#loadHeadersFromResource 641loadHeadersFromResource()}를 호출해야 합니다. 예:</p> 642 643<pre> 644public class SettingsActivity extends PreferenceActivity { 645 @Override 646 public void onBuildHeaders(List<Header> target) { 647 loadHeadersFromResource(R.xml.preference_headers, target); 648 } 649} 650</pre> 651 652<p>사용자가 헤더 목록에서 항목을 하나 선택하면 시스템이 연관된 {@link 653android.preference.PreferenceFragment}를 엽니다.</p> 654 655<p class="note"><strong>참고:</strong> 기본 설정 헤더를 사용하는 경우, {@link 656android.preference.PreferenceActivity}의 하위 클래스가 {@link 657android.preference.PreferenceActivity#onCreate onCreate()} 메서드를 구현하지 않아도 됩니다. 액티비티에 대한 필수 작업은 658헤더를 로딩하는 것뿐이기 때문입니다.</p> 659 660 661<h3 id="BackCompatHeaders">기본 설정 헤더로 이전 버전 지원하기</h3> 662 663<p>애플리케이션이 Android 3.0 이전 버전을 지원하는 경우에도 여전히 헤더를 사용하여 664Android 3.0 이상에서 창 두 개짜리 레이아웃을 제공하도록 할 수 있습니다. 개발자가 해야 할 일은 추가로 기본 설정 XML 파일을 665생성하는 것뿐입니다. 이 파일은 마치 헤더 항목처럼 동작하는 기본적인 {@link android.preference.Preference 666<Preference>} 요소를 사용합니다(이것을 이전 Android 버전이 사용하도록 667할 예정).</p> 668 669<p>하지만 새로운 {@link android.preference.PreferenceScreen}을 여는 대신 각 {@link 670android.preference.Preference <Preference>} 요소가 {@link android.content.Intent}를 하나씩 671{@link android.preference.PreferenceActivity}에 전송합니다. 이것이 로딩할 XML 파일이 무엇인지를 672나타냅니다.</p> 673 674<p>예를 들어 다음은 Android 3.0 이상에서 사용되는 기본 설정 헤더에 대한 675XML 파일입니다({@code res/xml/preference_headers.xml}).</p> 676 677<pre> 678<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> 679 <header 680 android:fragment="com.example.prefs.SettingsFragmentOne" 681 android:title="@string/prefs_category_one" 682 android:summary="@string/prefs_summ_category_one" /> 683 <header 684 android:fragment="com.example.prefs.SettingsFragmentTwo" 685 android:title="@string/prefs_category_two" 686 android:summary="@string/prefs_summ_category_two" /> 687</preference-headers> 688</pre> 689 690<p>그리고 다음은, Android 3.0 이전 버전에 같은 헤더를 제공하는 기본 설정 691파일입니다({@code res/xml/preference_headers_legacy.xml}).</p> 692 693<pre> 694<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 695 <Preference 696 android:title="@string/prefs_category_one" 697 android:summary="@string/prefs_summ_category_one" > 698 <intent 699 android:targetPackage="com.example.prefs" 700 android:targetClass="com.example.prefs.SettingsActivity" 701 android:action="com.example.prefs.PREFS_ONE" /> 702 </Preference> 703 <Preference 704 android:title="@string/prefs_category_two" 705 android:summary="@string/prefs_summ_category_two" > 706 <intent 707 android:targetPackage="com.example.prefs" 708 android:targetClass="com.example.prefs.SettingsActivity" 709 android:action="com.example.prefs.PREFS_TWO" /> 710 </Preference> 711</PreferenceScreen> 712</pre> 713 714<p>{@code <preference-headers>}에 대한 지원이 Android 3.0에서 추가되었기 때문에 시스템이 715{@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()}를 {@link 716android.preference.PreferenceActivity}에서 호출하는 것은 Android 3.0 이상에서 실행될 때뿐입니다. "레거시" 헤더 파일을 717로딩하려면({@code preference_headers_legacy.xml}) 반드시 Android 718버전을 확인해야 하며, 해당 버전이 Android 3.0 이전인 경우({@link 719android.os.Build.VERSION_CODES#HONEYCOMB}), {@link 720android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()}를 호출하여 721레거시 헤더 파일을 로딩해야 합니다. 예:</p> 722 723<pre> 724@Override 725public void onCreate(Bundle savedInstanceState) { 726 super.onCreate(savedInstanceState); 727 ... 728 729 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 730 // Load the legacy preferences headers 731 addPreferencesFromResource(R.xml.preference_headers_legacy); 732 } 733} 734 735// Called only on Honeycomb and later 736@Override 737public void onBuildHeaders(List<Header> target) { 738 loadHeadersFromResource(R.xml.preference_headers, target); 739} 740</pre> 741 742<p>이제 남은 할 일이라고는 {@link android.content.Intent}를 처리하는 것뿐입니다. 이것은 743액티비티로 전달되어 어느 기본 설정 파일을 로딩해야 하는지 식별하는 데 쓰입니다. 그럼 이제 인텐트의 작업을 검색하여 기본 설정 XML의 744{@code <intent>} 태그에서 사용한 알려진 작업 문자열에 비교해보겠습니다.</p> 745 746<pre> 747final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE"; 748... 749 750@Override 751public void onCreate(Bundle savedInstanceState) { 752 super.onCreate(savedInstanceState); 753 754 String action = getIntent().getAction(); 755 if (action != null && action.equals(ACTION_PREFS_ONE)) { 756 addPreferencesFromResource(R.xml.preferences); 757 } 758 ... 759 760 else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 761 // Load the legacy preferences headers 762 addPreferencesFromResource(R.xml.preference_headers_legacy); 763 } 764} 765</pre> 766 767<p>{@link 768android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()}를 연이어 호출하면 769모든 기본 설정을 하나의 목록에 쌓게 된다는 점을 유의하십시오. 따라서 이것은 'Else-if' 문이 있는 조건을 변경하여 딱 한 번만 770호출하도록 주의해야 합니다.</p> 771 772 773 774 775 776<h2 id="ReadingPrefs">기본 설정 읽기</h2> 777 778<p>기본적으로 앱의 기본 설정은 모두 779애플리케이션 내의 어디서든 정적 메서드 {@link 780android.preference.PreferenceManager#getDefaultSharedPreferences 781PreferenceManager.getDefaultSharedPreferences()}를 호출하면 액세스할 수 있는 파일에 저장됩니다. 이것은 {@link 782android.content.SharedPreferences} 객체를 반환하며, 여기에 {@link 783android.preference.PreferenceActivity}에서 사용한 {@link android.preference.Preference} 객체와 784연관된 모든 키-값 쌍이 들어있습니다.</p> 785 786<p>예를 들어 다음은 기본 설정 값 중 하나를 애플리케이션 내의 다른 모든 액티비티에서 읽는 방법을 787나타낸 것입니다.</p> 788 789<pre> 790SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); 791String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, ""); 792</pre> 793 794 795 796<h3 id="Listening">기본 설정 변경 수신 대기</h3> 797 798<p>사용자가 기본 설정 중 하나를 변경하자마자 이에 대해 알림을 받는 것이 좋은 데에는 몇 가지 799이유가 있습니다. 기본 설정 중 어느 하나에라도 변경이 발생했을 때 콜백을 받으려면, 800{@link android.content.SharedPreferences.OnSharedPreferenceChangeListener 801SharedPreference.OnSharedPreferenceChangeListener} 인터페이스를 구현하고 802{@link android.content.SharedPreferences} 객체에 대한 수신기를 등록합니다. 이때 {@link 803android.content.SharedPreferences#registerOnSharedPreferenceChangeListener 804registerOnSharedPreferenceChangeListener()}를 호출하면 됩니다.</p> 805 806<p>이 인터페이스에는 콜백 메서드가 {@link 807android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged 808onSharedPreferenceChanged()} 하나뿐이며, 인터페이스를 액티비티의 일부분으로 구현하는 것이 809가장 쉬운 방법일 공산이 큽니다. 예:</p> 810 811<pre> 812public class SettingsActivity extends PreferenceActivity 813 implements OnSharedPreferenceChangeListener { 814 public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType"; 815 ... 816 817 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, 818 String key) { 819 if (key.equals(KEY_PREF_SYNC_CONN)) { 820 Preference connectionPref = findPreference(key); 821 // Set summary to be the user-description for the selected value 822 connectionPref.setSummary(sharedPreferences.getString(key, "")); 823 } 824 } 825} 826</pre> 827 828<p>이 예시에서 메서드는 변경된 설정이 알려진 기본 설정 키에 대한 것인지 여부를 확인합니다. 이것은 829{@link android.preference.PreferenceActivity#findPreference findPreference()}를 호출하여 830변경된 {@link android.preference.Preference} 객체를 가져오는데, 이렇게 해야 항목의 요약을 수정하여 831사용자의 선택에 대한 설명이 되도록 할 수 있습니다. 다시 말해, 설정이 {@link 832android.preference.ListPreference} 또는 다른 다중 선택 설정인 경우, 설정이 변경되어 현재 상태를 표시하도록 하면 {@link 833android.preference.Preference#setSummary setSummary()}를 호출해야 한다는 뜻입니다(예를 들어 834그림 5에 표시된 절전 모드 설정과 같음).</p> 835 836<p class="note"><strong>참고:</strong> Android 디자인 문서의 <a href="{@docRoot}design/patterns/settings.html">설정</a> 관련 내용에서 설명한 바와 같이, 사용자가 기본 설정을 변경할 때마다 837{@link android.preference.ListPreference}의 요약을 업데이트하는 것을 권장합니다. 이렇게 하여 현재 설정을 838나타내는 것입니다.</p> 839 840<p>액티비티에서 적절한 수명 주기 관리를 수행하려면 841{@link android.content.SharedPreferences.OnSharedPreferenceChangeListener}를 등록하고 등록 해제하는 작업은 각각 {@link 842android.app.Activity#onResume} 및 {@link android.app.Activity#onPause} 콜백 중에 수행하는 것을 권장합니다.</p> 843 844<pre> 845@Override 846protected void onResume() { 847 super.onResume(); 848 getPreferenceScreen().getSharedPreferences() 849 .registerOnSharedPreferenceChangeListener(this); 850} 851 852@Override 853protected void onPause() { 854 super.onPause(); 855 getPreferenceScreen().getSharedPreferences() 856 .unregisterOnSharedPreferenceChangeListener(this); 857} 858</pre> 859 860<p class="caution"><strong>주의:</strong> {@link 861android.content.SharedPreferences#registerOnSharedPreferenceChangeListener 862registerOnSharedPreferenceChangeListener()}를 호출하면 863현재의 경우, 기본 설정 관리자가 수신기에 대한 강력한 참조를 저장하지 않습니다. 반드시 수신기에 대한 강력한 864참조를 저장해야 합니다. 그렇지 않으면 가비지 수집의 대상이 될 가능성이 높습니다. 권장 사항으로는 865수신기를 객체의 인스턴스 데이터 안에 보관하는 것을 추천합니다. 이 객체는 866수신기를 필요로 하는 기간만큼 오래 존재할 것이 확실해야 합니다.</p> 867 868<p>예를 들어 다음 코드에서 발신자는 수신기에 대한 참조를 869보관하지 않습니다. 그 결과 해당 수신기가 가비지 수집의 대상이 되며 870향후 언젠가 알 수 없는 시점에 고장을 일으키게 될 것입니다.</p> 871 872<pre> 873prefs.registerOnSharedPreferenceChangeListener( 874 // Bad! The listener is subject to garbage collection! 875 new SharedPreferences.OnSharedPreferenceChangeListener() { 876 public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { 877 // listener implementation 878 } 879}); 880</pre> 881 882<p>대신, 수신기에 대한 참조를 수신기가 필요한 기간만큼 오래 존재할 것이 확실한 객체의 883인스턴스 데이터 필드에 저장하십시오.</p> 884 885<pre> 886SharedPreferences.OnSharedPreferenceChangeListener listener = 887 new SharedPreferences.OnSharedPreferenceChangeListener() { 888 public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { 889 // listener implementation 890 } 891}; 892prefs.registerOnSharedPreferenceChangeListener(listener); 893</pre> 894 895<h2 id="NetworkUsage">네트워크 사용량 관리하기</h2> 896 897 898<p>Android 4.0부터 시스템의 설정 애플리케이션을 사용하면 사용자가 899애플리케이션이 전경과 배경에 있는 동안 각각 얼마나 많은 네트워크 데이터를 사용하는지 알아볼 수 있게 되었습니다. 그런 다음 900사용자는 각각의 앱에 대해 배경 데이터 사용을 비활성화할 수 있습니다. 사용자가 여러분의 앱이 배경에서 901데이터에 액세스하는 기능을 비활성화하는 사태를 피하려면 데이터 연결을 효율적으로 사용하고 902사용자가 애플리케이션 설정을 통하여 앱의 데이터 사용량을 미세 조정할 수 있도록 허용해야 합니다.<p> 903 904<p>예를 들어 사용자에게 앱의 데이터 동기화 빈도를 제어하도록 허용할 수 있습니다. 앱이 Wi-Fi에 있을 때에만 905업로드/다운로드를 수행하도록 할지 여부, 앱이 로밍 중에 데이터를 사용하도록 할지 여부 등을 이렇게 조절합니다. 사용자가 906이러한 제어 기능을 사용할 수 있게 되면 시스템 설정에서 설정한 한도에 가까워지고 907있을 때 앱의 데이터 액세스를 비활성화할 가능성이 낮아집니다. 그 대신 앱이 사용하는 데이터 양을 908정밀하게 제어할 수 있기 때문입니다.</p> 909 910<p>일단 필요한 기본 설정을 {@link android.preference.PreferenceActivity}에 911추가하여 앱의 데이터 습관을 제어하도록 했으면, 다음으로 매니페스트 파일에 있는 {@link 912android.content.Intent#ACTION_MANAGE_NETWORK_USAGE}에 대한 인텐트 필터를 추가해야 합니다. 예:</p> 913 914<pre> 915<activity android:name="SettingsActivity" ... > 916 <intent-filter> 917 <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" /> 918 <category android:name="android.intent.category.DEFAULT" /> 919 </intent-filter> 920</activity> 921</pre> 922 923<p>이 인텐트 필터는 이것이 애플리케이션의 데이터 사용량을 제어하는 액티비티라는 924사실을 시스템에 나타내는 역할을 합니다. 따라서, 사용자가 시스템의 설정 앱에서 여러분의 앱이 925얼마나 많은 데이터를 사용하는지 알아볼 때면 <em>애플리케이션 설정 보기</em> 버튼을 사용할 수 있어 926{@link android.preference.PreferenceActivity}를 시작하게 됩니다. 그러면 사용자는 927앱이 사용할 데이터 양을 미세하게 조정할 수 있습니다.</p> 928 929 930 931 932 933 934 935<h2 id="Custom">사용자 지정 기본 설정 구축하기</h2> 936 937<p>Android 프레임워크에는 다양한 {@link android.preference.Preference} 하위 클래스가 포함되어 있어 938여러 가지 설정 유형에 맞게 UI를 구축할 수 있습니다. 939하지만, 기본 제공 솔루션이 없는 설정이 필요하게 되는 경우도 있습니다. 예를 들어 숫자 선택기 또는 940날짜 선택기 등이 이에 해당됩니다. 그러한 경우에는 사용자 지정 기본 설정을 만들어야 합니다. 이때 941{@link android.preference.Preference} 클래스 또는 다른 하위 클래스 중 하나를 확장하는 방법을 씁니다.</p> 942 943<p>{@link android.preference.Preference} 클래스를 확장하는 경우, 다음과 같이 944몇 가지 중요한 해야 할 일이 있습니다.</p> 945 946<ul> 947 <li>사용자가 설정을 선택하면 나타나는 사용자 인터페이스를 지정합니다.</li> 948 <li>필요에 따라 설정의 값을 저장합니다.</li> 949 <li>{@link android.preference.Preference}가 보이게 되면 950이를 현재(또는 기본) 값으로 초기화합니다.</li> 951 <li>시스템이 요청하는 경우 기본 값을 제공합니다.</li> 952 <li>{@link android.preference.Preference}가 나름의 UI(예: 대화)를 제공하는 경우, 상태를 953저장하고 복원하여 수명 주기 변경을 처리할 수 있도록 합니다(예: 사용자가 화면을 돌리는 경우).</li> 954</ul> 955 956<p>다음 섹션에서는 이와 같은 각각의 작업을 수행하는 방법을 설명합니다.</p> 957 958 959 960<h3 id="CustomSelected">사용자 인터페이스 지정하기</h3> 961 962 <p>{@link android.preference.Preference} 클래스를 직접 확장하는 경우, 963{@link android.preference.Preference#onClick()}을 구현하여 사용자가 964항목을 선택할 때 일어날 동작을 정의해야 합니다. 그러나, 대부분의 사용자 지정 설정은 {@link android.preference.DialogPreference}를 확장하여 965대화를 표시하도록 합니다. 이렇게 하면 절차가 단순해집니다. {@link 966android.preference.DialogPreference}를 확장하는 경우에는 클래스 생성자 중에 반드시 {@link 967android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()}를 호출하여 968대화에 대한 레이아웃을 지정해야 합니다.</p> 969 970 <p>예를 들어 다음은 레이아웃을 선언하는 사용자 지정 {@link 971android.preference.DialogPreference}와 기본 972긍정적 및 부정적 대화 버튼에 대한 텍스트를 지정하는 생성자입니다.</p> 973 974<pre> 975public class NumberPickerPreference extends DialogPreference { 976 public NumberPickerPreference(Context context, AttributeSet attrs) { 977 super(context, attrs); 978 979 setDialogLayoutResource(R.layout.numberpicker_dialog); 980 setPositiveButtonText(android.R.string.ok); 981 setNegativeButtonText(android.R.string.cancel); 982 983 setDialogIcon(null); 984 } 985 ... 986} 987</pre> 988 989 990 991<h3 id="CustomSave">설정의 값 저장하기</h3> 992 993<p>설정에 대한 값은 언제든 저장할 수 있습니다. {@link 994android.preference.Preference} 클래스의 {@code persist*()} 메서드 중 하나를 호출하기만 하면 됩니다. 예를 들어 설정의 값이 정수인 경우 {@link 995android.preference.Preference#persistInt persistInt()}를, 부울을 저장하려면 996{@link android.preference.Preference#persistBoolean persistBoolean()}을 호출하십시오.</p> 997 998<p class="note"><strong>참고:</strong> 각각의 {@link android.preference.Preference}는 데이터 유형 하나씩만 999저장할 수 있으므로, 사용자 지정 1000{@link android.preference.Preference}에서 사용한 데이터 유형에 적절한 {@code persist*()} 메서드를 사용해야 합니다.</p> 1001 1002<p>설정을 유지하기로 선택하는 시점은 확장하는 지점이 {@link 1003android.preference.Preference} 클래스인지에 좌우될 수 있습니다. {@link 1004android.preference.DialogPreference}를 확장하면 값을 유지하는 것은 대화가 긍정적인 결과로 인해 1005닫히는 경우만으로 국한해야 합니다(사용자가 "확인(OK)" 버튼을 선택하는 경우).</p> 1006 1007<p>{@link android.preference.DialogPreference}가 닫히면 시스템이 {@link 1008android.preference.DialogPreference#onDialogClosed onDialogClosed()} 메서드를 호출합니다. 이 메서드에는 1009부울 인수가 포함되어 있어 사용자의 결과가 "긍정적"인지 아닌지를 나타냅니다. 이 값이 1010<code>true</code>인 경우, 사용자가 긍정적 버튼을 선택한 것이고 새 값을 저장해야 합니다. 예: 1011</p> 1012 1013<pre> 1014@Override 1015protected void onDialogClosed(boolean positiveResult) { 1016 // When the user selects "OK", persist the new value 1017 if (positiveResult) { 1018 persistInt(mNewValue); 1019 } 1020} 1021</pre> 1022 1023<p>이 예시에서 <code>mNewValue</code>는 설정의 현재 값을 보유한 클래스 1024구성원입니다. {@link android.preference.Preference#persistInt persistInt()}를 호출하면 1025{@link android.content.SharedPreferences} 파일에 대한 값을 저장합니다(이 1026{@link android.preference.Preference}에 대하여 XML 파일에 지정된 키를 자동으로 사용합니다).</p> 1027 1028 1029<h3 id="CustomInitialize">현재 값 초기화하기</h3> 1030 1031<p>시스템이 {@link android.preference.Preference}를 화면에 추가하는 경우, 이는 1032{@link android.preference.Preference#onSetInitialValue onSetInitialValue()}를 호출하여 1033설정에 유지된 값이 있는지 없는지를 알립니다. 유지된 값이 없는 경우, 이 호출은 기본 값을 1034제공합니다.</p> 1035 1036<p>{@link android.preference.Preference#onSetInitialValue onSetInitialValue()} 메서드는 1037부울 값 <code>restorePersistedValue</code>를 전달하여 해당 설정에 대해 이미 어떤 값이 유지되었는지 1038아닌지를 나타냅니다. 만일 이것이 <code>true</code>라면, 유지된 값을 검색하되 1039{@link 1040android.preference.Preference} 클래스의 {@code getPersisted*()} 메서드 중 하나를 호출하는 방법을 써야 합니다. 예를 들어 정수 값이라면 {@link 1041android.preference.Preference#getPersistedInt getPersistedInt()}를 사용합니다. 보통은 1042유지된 값을 검색하여, UI에 이전에 저장된 값을 반영하여 이를 적절하게 업데이트할 수 1043있도록 하는 것이 좋습니다.</p> 1044 1045<p><code>restorePersistedValue</code>가 <code>false</code>인 경우, 1046두 번째 인수로 전달된 기본 값을 사용해야 합니다.</p> 1047 1048<pre> 1049@Override 1050protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { 1051 if (restorePersistedValue) { 1052 // Restore existing state 1053 mCurrentValue = this.getPersistedInt(DEFAULT_VALUE); 1054 } else { 1055 // Set default state from the XML attribute 1056 mCurrentValue = (Integer) defaultValue; 1057 persistInt(mCurrentValue); 1058 } 1059} 1060</pre> 1061 1062<p>각 {@code getPersisted*()} 메서드는 기본 값을 나타내는 인수를 취하여 1063사실은 유지된 값이 전혀 없거나 키 자체가 존재하지 않는 경우 사용하도록 합니다. 위의 1064예시에서는 혹시 {@link 1065android.preference.Preference#getPersistedInt getPersistedInt()}가 유지된 값을 반환할 수 없는 경우에 사용하도록 기본 값을 나타내는 데 로컬 상수를 사용하였습니다.</p> 1066 1067<p class="caution"><strong>주의:</strong> {@code getPersisted*()} 메서드에서는 1068<code>defaultValue</code>를 기본 값으로 사용하면 <strong>안 됩니다</strong>. 이것의 값은 1069<code>restorePersistedValue</code>가 <code>true</code>이면 항상 null이기 때문입니다.</p> 1070 1071 1072<h3 id="CustomDefault">기본 값 제공하기</h3> 1073 1074<p>{@link android.preference.Preference} 클래스의 인스턴스가 기본 값을 나타내는 경우 1075({@code android:defaultValue} 속성으로), 시스템은 1076값을 검색하기 위해 객체를 인스턴트화할 때 {@link android.preference.Preference#onGetDefaultValue 1077onGetDefaultValue()}를 호출합니다. 이 메서드를 구현해야 1078시스템이 {@link 1079android.content.SharedPreferences}에 있는 기본 값을 저장할 수 있습니다. 예:</p> 1080 1081<pre> 1082@Override 1083protected Object onGetDefaultValue(TypedArray a, int index) { 1084 return a.getInteger(index, DEFAULT_VALUE); 1085} 1086</pre> 1087 1088<p>이 메서드 인수가 여러분에게 필요한 모든 것을 제공합니다. 즉 속성 배열과 1089{@code android:defaultValue}의 위치로, 이는 반드시 검색해야 합니다. 이 메서드를 1090반드시 구현하여 속성에서 기본 값을 추출해야만 하는 이유는 값이 정의되지 않은 경우, 속성에 대한 1091로컬 기본 값을 꼭 지정해야 하기 때문입니다.</p> 1092 1093 1094 1095<h3 id="CustomSaveState">기본 설정의 상태 저장 및 복원하기</h3> 1096 1097<p>레이아웃에서의 {@link android.view.View}와 마찬가지로 {@link android.preference.Preference} 1098하위 클래스가 액티비티 또는 프래그먼트가 재시작했을 때 1099그 상태를 저장하고 복원하는 역할을 맡습니다(예를 들어 사용자가 화면을 돌리는 경우 등). 1100{@link android.preference.Preference} 클래스의 상태를 적절하게 저장하고 복원하려면, 1101수명 주기 콜백 메서드 {@link android.preference.Preference#onSaveInstanceState 1102onSaveInstanceState()} 및 {@link 1103android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}를 구현해야 합니다.</p> 1104 1105<p>{@link android.preference.Preference}의 상태를 정의하는 것은 1106{@link android.os.Parcelable} 인터페이스를 구현하는 객체입니다. Android 프레임워크는 1107그러한 객체를 제공하여 상태 객체를 정의하는 데 일종의 시작 지점으로 사용하도록 하고 있습니다. 즉 {@link 1108android.preference.Preference.BaseSavedState} 클래스가 이에 해당됩니다.</p> 1109 1110<p>{@link android.preference.Preference} 클래스가 자신의 상태를 저장하는 방법을 정의하려면 1111{@link android.preference.Preference.BaseSavedState} 클래스를 확장해야 합니다. 아주 약간의 메서드를 재정의하고 1112{@link android.preference.Preference.BaseSavedState#CREATOR} 1113객체를 정의해야 합니다.</p> 1114 1115<p>대부분의 앱에서는 다음과 같은 구현을 복사한 다음, 1116{@code value}를 처리하는 줄만 변경하면 됩니다. 이는 {@link android.preference.Preference} 하위 클래스가 정수보다는 데이터 1117유형을 저장하는 경우 해당됩니다.</p> 1118 1119<pre> 1120private static class SavedState extends BaseSavedState { 1121 // Member that holds the setting's value 1122 // Change this data type to match the type saved by your Preference 1123 int value; 1124 1125 public SavedState(Parcelable superState) { 1126 super(superState); 1127 } 1128 1129 public SavedState(Parcel source) { 1130 super(source); 1131 // Get the current preference's value 1132 value = source.readInt(); // Change this to read the appropriate data type 1133 } 1134 1135 @Override 1136 public void writeToParcel(Parcel dest, int flags) { 1137 super.writeToParcel(dest, flags); 1138 // Write the preference's value 1139 dest.writeInt(value); // Change this to write the appropriate data type 1140 } 1141 1142 // Standard creator object using an instance of this class 1143 public static final Parcelable.Creator<SavedState> CREATOR = 1144 new Parcelable.Creator<SavedState>() { 1145 1146 public SavedState createFromParcel(Parcel in) { 1147 return new SavedState(in); 1148 } 1149 1150 public SavedState[] newArray(int size) { 1151 return new SavedState[size]; 1152 } 1153 }; 1154} 1155</pre> 1156 1157<p>위의 {@link android.preference.Preference.BaseSavedState} 구현을 앱에 1158추가하고 나면(주로 {@link android.preference.Preference} 하위 클래스의 하위 클래스로), 이제 1159{@link android.preference.Preference#onSaveInstanceState 1160onSaveInstanceState()} 및 {@link 1161android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} 메서드를 구현해야 합니다. 이것은 1162{@link android.preference.Preference} 하위 클래스를 위한 것입니다.</p> 1163 1164<p>예:</p> 1165 1166<pre> 1167@Override 1168protected Parcelable onSaveInstanceState() { 1169 final Parcelable superState = super.onSaveInstanceState(); 1170 // Check whether this Preference is persistent (continually saved) 1171 if (isPersistent()) { 1172 // No need to save instance state since it's persistent, 1173 // use superclass state 1174 return superState; 1175 } 1176 1177 // Create instance of custom BaseSavedState 1178 final SavedState myState = new SavedState(superState); 1179 // Set the state's value with the class member that holds current 1180 // setting value 1181 myState.value = mNewValue; 1182 return myState; 1183} 1184 1185@Override 1186protected void onRestoreInstanceState(Parcelable state) { 1187 // Check whether we saved the state in onSaveInstanceState 1188 if (state == null || !state.getClass().equals(SavedState.class)) { 1189 // Didn't save the state, so call superclass 1190 super.onRestoreInstanceState(state); 1191 return; 1192 } 1193 1194 // Cast state to custom BaseSavedState and pass to superclass 1195 SavedState myState = (SavedState) state; 1196 super.onRestoreInstanceState(myState.getSuperState()); 1197 1198 // Set this Preference's widget to reflect the restored state 1199 mNumberPicker.setValue(myState.value); 1200} 1201</pre> 1202 1203