blob: b250b15a57c3699f79d8df4edcb8e3e0acacd4d7 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.preference;
18
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +000019import android.annotation.Nullable;
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -070020import android.annotation.SystemApi;
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +010021import android.annotation.UnsupportedAppUsage;
Tor Norbye7b9c9122013-05-30 16:48:33 -070022import android.annotation.XmlRes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.app.Activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.Context;
25import android.content.DialogInterface;
26import android.content.Intent;
27import android.content.SharedPreferences;
28import android.content.pm.ActivityInfo;
29import android.content.pm.PackageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.content.pm.PackageManager.NameNotFoundException;
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -070031import android.content.pm.ResolveInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.content.res.XmlResourceParser;
33import android.os.Bundle;
34import android.util.Log;
35
Amith Yamasani82e7bc12010-09-23 15:07:58 -070036import java.util.ArrayList;
37import java.util.HashSet;
38import java.util.List;
39
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040/**
41 * Used to help create {@link Preference} hierarchies
42 * from activities or XML.
43 * <p>
44 * In most cases, clients should use
45 * {@link PreferenceActivity#addPreferencesFromIntent} or
46 * {@link PreferenceActivity#addPreferencesFromResource(int)}.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +000047 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048 * @see PreferenceActivity
49 */
50public class PreferenceManager {
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +000051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052 private static final String TAG = "PreferenceManager";
53
54 /**
55 * The Activity meta-data key for its XML preference hierarchy.
56 */
57 public static final String METADATA_KEY_PREFERENCES = "android.preference";
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +000058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059 public static final String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +000060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 /**
62 * @see #getActivity()
63 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +000064 @Nullable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 private Activity mActivity;
66
67 /**
Amith Yamasani82e7bc12010-09-23 15:07:58 -070068 * Fragment that owns this instance.
69 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +000070 @Nullable
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +010071 @UnsupportedAppUsage
Amith Yamasani82e7bc12010-09-23 15:07:58 -070072 private PreferenceFragment mFragment;
73
74 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 * The context to use. This should always be set.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +000076 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077 * @see #mActivity
78 */
79 private Context mContext;
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +000080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 /**
82 * The counter for unique IDs.
83 */
84 private long mNextId = 0;
85
86 /**
87 * The counter for unique request codes.
88 */
89 private int mNextRequestCode;
90
91 /**
92 * Cached shared preferences.
93 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +000094 @Nullable
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +010095 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 private SharedPreferences mSharedPreferences;
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +000097
98 /**
Filip Pavlisee3bc342017-03-13 16:58:24 +000099 * Data store to be used by the Preferences or {@code null} if
100 * {@link android.content.SharedPreferences} should be used.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000101 */
102 @Nullable
103 private PreferenceDataStore mPreferenceDataStore;
104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 /**
106 * If in no-commit mode, the shared editor to give out (which will be
107 * committed when exiting no-commit mode).
108 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000109 @Nullable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 private SharedPreferences.Editor mEditor;
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 /**
113 * Blocks commits from happening on the shared editor. This is used when
114 * inflating the hierarchy. Do not set this directly, use {@link #setNoCommit(boolean)}
115 */
116 private boolean mNoCommit;
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 /**
119 * The SharedPreferences name that will be used for all {@link Preference}s
120 * managed by this instance.
121 */
122 private String mSharedPreferencesName;
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 /**
125 * The SharedPreferences mode that will be used for all {@link Preference}s
126 * managed by this instance.
127 */
128 private int mSharedPreferencesMode;
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700129
130 private static final int STORAGE_DEFAULT = 0;
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600131 private static final int STORAGE_DEVICE_PROTECTED = 1;
132 private static final int STORAGE_CREDENTIAL_PROTECTED = 2;
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700133
134 private int mStorage = STORAGE_DEFAULT;
135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 /**
137 * The {@link PreferenceScreen} at the root of the preference hierarchy.
138 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000139 @Nullable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 private PreferenceScreen mPreferenceScreen;
141
142 /**
143 * List of activity result listeners.
144 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000145 @Nullable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 private List<OnActivityResultListener> mActivityResultListeners;
147
148 /**
149 * List of activity stop listeners.
150 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000151 @Nullable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 private List<OnActivityStopListener> mActivityStopListeners;
153
154 /**
155 * List of activity destroy listeners.
156 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000157 @Nullable
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100158 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 private List<OnActivityDestroyListener> mActivityDestroyListeners;
160
161 /**
162 * List of dialogs that should be dismissed when we receive onNewIntent in
163 * our PreferenceActivity.
164 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000165 @Nullable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 private List<DialogInterface> mPreferencesScreens;
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000167
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100168 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 private OnPreferenceTreeClickListener mOnPreferenceTreeClickListener;
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000170
Justin Koh37ae5582012-10-25 15:26:36 -0700171 /**
172 * @hide
173 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100174 @UnsupportedAppUsage
Justin Koh37ae5582012-10-25 15:26:36 -0700175 public PreferenceManager(Activity activity, int firstRequestCode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 mActivity = activity;
177 mNextRequestCode = firstRequestCode;
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 init(activity);
180 }
181
182 /**
183 * This constructor should ONLY be used when getting default values from
184 * an XML preference hierarchy.
185 * <p>
186 * The {@link PreferenceManager#PreferenceManager(Activity)}
187 * should be used ANY time a preference will be displayed, since some preference
188 * types need an Activity for managed queries.
189 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100190 @UnsupportedAppUsage
Deepanshu Gupta10bb1372014-10-05 14:41:17 -0700191 /*package*/ PreferenceManager(Context context) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 init(context);
193 }
194
195 private void init(Context context) {
196 mContext = context;
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 setSharedPreferencesName(getDefaultSharedPreferencesName(context));
199 }
Amith Yamasani82e7bc12010-09-23 15:07:58 -0700200
201 /**
202 * Sets the owning preference fragment
203 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100204 @UnsupportedAppUsage
Amith Yamasani82e7bc12010-09-23 15:07:58 -0700205 void setFragment(PreferenceFragment fragment) {
206 mFragment = fragment;
207 }
208
209 /**
210 * Returns the owning preference fragment, if any.
211 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000212 @Nullable
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100213 @UnsupportedAppUsage
Amith Yamasani82e7bc12010-09-23 15:07:58 -0700214 PreferenceFragment getFragment() {
215 return mFragment;
216 }
217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 /**
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000219 * Sets a {@link PreferenceDataStore} to be used by all Preferences associated with this manager
Filip Pavlisfd596452017-03-01 18:50:00 +0000220 * that don't have a custom {@link PreferenceDataStore} assigned via
221 * {@link Preference#setPreferenceDataStore(PreferenceDataStore)}. Also if the data store is
222 * set, the child preferences won't use {@link android.content.SharedPreferences} as long as
223 * they are assigned to this manager.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000224 *
225 * @param dataStore The {@link PreferenceDataStore} to be used by this manager.
Filip Pavlisfd596452017-03-01 18:50:00 +0000226 * @see Preference#setPreferenceDataStore(PreferenceDataStore)
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000227 */
228 public void setPreferenceDataStore(PreferenceDataStore dataStore) {
229 mPreferenceDataStore = dataStore;
230 }
231
232 /**
233 * Returns the {@link PreferenceDataStore} associated with this manager or {@code null} if
Filip Pavlisfd596452017-03-01 18:50:00 +0000234 * the default {@link android.content.SharedPreferences} are used instead.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000235 *
236 * @return The {@link PreferenceDataStore} associated with this manager or {@code null} if none.
Filip Pavlisfd596452017-03-01 18:50:00 +0000237 * @see #setPreferenceDataStore(PreferenceDataStore)
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000238 */
239 @Nullable
240 public PreferenceDataStore getPreferenceDataStore() {
241 return mPreferenceDataStore;
242 }
243
244 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 * Returns a list of {@link Activity} (indirectly) that match a given
246 * {@link Intent}.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000247 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 * @param queryIntent The Intent to match.
249 * @return The list of {@link ResolveInfo} that point to the matched
250 * activities.
251 */
252 private List<ResolveInfo> queryIntentActivities(Intent queryIntent) {
253 return mContext.getPackageManager().queryIntentActivities(queryIntent,
254 PackageManager.GET_META_DATA);
255 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 /**
258 * Inflates a preference hierarchy from the preference hierarchies of
259 * {@link Activity Activities} that match the given {@link Intent}. An
260 * {@link Activity} defines its preference hierarchy with meta-data using
261 * the {@link #METADATA_KEY_PREFERENCES} key.
262 * <p>
263 * If a preference hierarchy is given, the new preference hierarchies will
264 * be merged in.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000265 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 * @param queryIntent The intent to match activities.
267 * @param rootPreferences Optional existing hierarchy to merge the new
268 * hierarchies into.
269 * @return The root hierarchy (if one was not provided, the new hierarchy's
270 * root).
271 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100272 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 PreferenceScreen inflateFromIntent(Intent queryIntent, PreferenceScreen rootPreferences) {
274 final List<ResolveInfo> activities = queryIntentActivities(queryIntent);
275 final HashSet<String> inflatedRes = new HashSet<String>();
276
277 for (int i = activities.size() - 1; i >= 0; i--) {
278 final ActivityInfo activityInfo = activities.get(i).activityInfo;
279 final Bundle metaData = activityInfo.metaData;
280
281 if ((metaData == null) || !metaData.containsKey(METADATA_KEY_PREFERENCES)) {
282 continue;
283 }
284
285 // Need to concat the package with res ID since the same res ID
286 // can be re-used across contexts
287 final String uniqueResId = activityInfo.packageName + ":"
288 + activityInfo.metaData.getInt(METADATA_KEY_PREFERENCES);
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 if (!inflatedRes.contains(uniqueResId)) {
291 inflatedRes.add(uniqueResId);
292
293 final Context context;
294 try {
295 context = mContext.createPackageContext(activityInfo.packageName, 0);
296 } catch (NameNotFoundException e) {
297 Log.w(TAG, "Could not create context for " + activityInfo.packageName + ": "
Filip Pavlis09557932017-03-03 16:54:22 +0000298 + Log.getStackTraceString(e));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 continue;
300 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 final PreferenceInflater inflater = new PreferenceInflater(context, this);
303 final XmlResourceParser parser = activityInfo.loadXmlMetaData(context
304 .getPackageManager(), METADATA_KEY_PREFERENCES);
305 rootPreferences = (PreferenceScreen) inflater
306 .inflate(parser, rootPreferences, true);
307 parser.close();
308 }
309 }
310
311 rootPreferences.onAttachedToHierarchy(this);
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 return rootPreferences;
314 }
315
316 /**
317 * Inflates a preference hierarchy from XML. If a preference hierarchy is
318 * given, the new preference hierarchies will be merged in.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000319 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 * @param context The context of the resource.
321 * @param resId The resource ID of the XML to inflate.
322 * @param rootPreferences Optional existing hierarchy to merge the new
323 * hierarchies into.
324 * @return The root hierarchy (if one was not provided, the new hierarchy's
325 * root).
Owen Linf9b702e2009-08-27 18:30:05 +0800326 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100328 @UnsupportedAppUsage
Tor Norbye7b9c9122013-05-30 16:48:33 -0700329 public PreferenceScreen inflateFromResource(Context context, @XmlRes int resId,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 PreferenceScreen rootPreferences) {
331 // Block commits
332 setNoCommit(true);
333
334 final PreferenceInflater inflater = new PreferenceInflater(context, this);
335 rootPreferences = (PreferenceScreen) inflater.inflate(resId, rootPreferences, true);
336 rootPreferences.onAttachedToHierarchy(this);
337
338 // Unblock commits
339 setNoCommit(false);
340
341 return rootPreferences;
342 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 public PreferenceScreen createPreferenceScreen(Context context) {
345 final PreferenceScreen preferenceScreen = new PreferenceScreen(context, null);
346 preferenceScreen.onAttachedToHierarchy(this);
347 return preferenceScreen;
348 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 /**
351 * Called by a preference to get a unique ID in its hierarchy.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000352 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 * @return A unique ID.
354 */
355 long getNextId() {
356 synchronized (this) {
357 return mNextId++;
358 }
359 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361 /**
362 * Returns the current name of the SharedPreferences file that preferences managed by
363 * this will use.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000364 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 * @return The name that can be passed to {@link Context#getSharedPreferences(String, int)}.
366 * @see Context#getSharedPreferences(String, int)
367 */
368 public String getSharedPreferencesName() {
369 return mSharedPreferencesName;
370 }
371
372 /**
373 * Sets the name of the SharedPreferences file that preferences managed by this
374 * will use.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000375 *
Filip Pavlisfd596452017-03-01 18:50:00 +0000376 * <p>If custom {@link PreferenceDataStore} is set, this won't override its usage.
377 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 * @param sharedPreferencesName The name of the SharedPreferences file.
379 * @see Context#getSharedPreferences(String, int)
Filip Pavlisfd596452017-03-01 18:50:00 +0000380 * @see #setPreferenceDataStore(PreferenceDataStore)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 */
382 public void setSharedPreferencesName(String sharedPreferencesName) {
383 mSharedPreferencesName = sharedPreferencesName;
384 mSharedPreferences = null;
385 }
386
387 /**
388 * Returns the current mode of the SharedPreferences file that preferences managed by
389 * this will use.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000390 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 * @return The mode that can be passed to {@link Context#getSharedPreferences(String, int)}.
392 * @see Context#getSharedPreferences(String, int)
393 */
394 public int getSharedPreferencesMode() {
395 return mSharedPreferencesMode;
396 }
397
398 /**
399 * Sets the mode of the SharedPreferences file that preferences managed by this
400 * will use.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000401 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 * @param sharedPreferencesMode The mode of the SharedPreferences file.
403 * @see Context#getSharedPreferences(String, int)
404 */
405 public void setSharedPreferencesMode(int sharedPreferencesMode) {
406 mSharedPreferencesMode = sharedPreferencesMode;
407 mSharedPreferences = null;
408 }
409
410 /**
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700411 * Sets the storage location used internally by this class to be the default
412 * provided by the hosting {@link Context}.
413 */
414 public void setStorageDefault() {
415 mStorage = STORAGE_DEFAULT;
416 mSharedPreferences = null;
417 }
418
419 /**
420 * Explicitly set the storage location used internally by this class to be
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600421 * device-protected storage.
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700422 * <p>
Jeff Sharkeycf3f0a12016-03-17 19:57:58 -0600423 * On devices with direct boot, data stored in this location is encrypted
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600424 * with a key tied to the physical device, and it can be accessed
425 * immediately after the device has booted successfully, both
426 * <em>before and after</em> the user has authenticated with their
427 * credentials (such as a lock pattern or PIN).
428 * <p>
429 * Because device-protected data is available without user authentication,
430 * you should carefully limit the data you store using this Context. For
431 * example, storing sensitive authentication tokens or passwords in the
432 * device-protected area is strongly discouraged.
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700433 *
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600434 * @see Context#createDeviceProtectedStorageContext()
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700435 */
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600436 public void setStorageDeviceProtected() {
437 mStorage = STORAGE_DEVICE_PROTECTED;
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700438 mSharedPreferences = null;
439 }
440
441 /**
442 * Explicitly set the storage location used internally by this class to be
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600443 * credential-protected storage. This is the default storage area for apps
444 * unless {@code forceDeviceProtectedStorage} was requested.
445 * <p>
Jeff Sharkeycf3f0a12016-03-17 19:57:58 -0600446 * On devices with direct boot, data stored in this location is encrypted
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600447 * with a key tied to user credentials, which can be accessed
448 * <em>only after</em> the user has entered their credentials (such as a
449 * lock pattern or PIN).
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700450 *
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600451 * @see Context#createCredentialProtectedStorageContext()
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700452 * @hide
453 */
454 @SystemApi
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600455 public void setStorageCredentialProtected() {
456 mStorage = STORAGE_CREDENTIAL_PROTECTED;
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700457 mSharedPreferences = null;
458 }
459
460 /**
Jeff Sharkeyc9a40cd2016-03-27 12:10:38 -0600461 * Indicates if the storage location used internally by this class is the
462 * default provided by the hosting {@link Context}.
463 *
464 * @see #setStorageDefault()
465 * @see #setStorageDeviceProtected()
466 */
467 public boolean isStorageDefault() {
468 return mStorage == STORAGE_DEFAULT;
469 }
470
471 /**
472 * Indicates if the storage location used internally by this class is backed
473 * by device-protected storage.
474 *
475 * @see #setStorageDefault()
476 * @see #setStorageDeviceProtected()
477 */
478 public boolean isStorageDeviceProtected() {
479 return mStorage == STORAGE_DEVICE_PROTECTED;
480 }
481
482 /**
483 * Indicates if the storage location used internally by this class is backed
484 * by credential-protected storage.
485 *
486 * @see #setStorageDefault()
487 * @see #setStorageDeviceProtected()
488 * @hide
489 */
490 @SystemApi
491 public boolean isStorageCredentialProtected() {
492 return mStorage == STORAGE_CREDENTIAL_PROTECTED;
493 }
494
495 /**
Filip Pavlis09557932017-03-03 16:54:22 +0000496 * Gets a {@link SharedPreferences} instance that preferences managed by this will use.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000497 *
Filip Pavlisee3bc342017-03-13 16:58:24 +0000498 * @return a {@link SharedPreferences} instance pointing to the file that contains the values of
499 * preferences that are managed by this PreferenceManager. If a
500 * {@link PreferenceDataStore} has been set, this method returns {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 */
502 public SharedPreferences getSharedPreferences() {
Filip Pavlisee3bc342017-03-13 16:58:24 +0000503 if (mPreferenceDataStore != null) {
504 return null;
505 }
506
507 if (mSharedPreferences == null) {
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700508 final Context storageContext;
509 switch (mStorage) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600510 case STORAGE_DEVICE_PROTECTED:
511 storageContext = mContext.createDeviceProtectedStorageContext();
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700512 break;
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600513 case STORAGE_CREDENTIAL_PROTECTED:
514 storageContext = mContext.createCredentialProtectedStorageContext();
Jeff Sharkeyfd37abe2016-01-28 11:53:48 -0700515 break;
516 default:
517 storageContext = mContext;
518 break;
519 }
520
521 mSharedPreferences = storageContext.getSharedPreferences(mSharedPreferencesName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 mSharedPreferencesMode);
523 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 return mSharedPreferences;
526 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 /**
Filip Pavlis09557932017-03-03 16:54:22 +0000529 * Gets a {@link SharedPreferences} instance that points to the default file that is used by
530 * the preference framework in the given context.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000531 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 * @param context The context of the preferences whose values are wanted.
Filip Pavlis09557932017-03-03 16:54:22 +0000533 * @return A {@link SharedPreferences} instance that can be used to retrieve and listen
534 * to values of the preferences.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 */
536 public static SharedPreferences getDefaultSharedPreferences(Context context) {
537 return context.getSharedPreferences(getDefaultSharedPreferencesName(context),
538 getDefaultSharedPreferencesMode());
539 }
540
Jeff Sharkey6a6cdaf2015-12-07 19:25:19 -0700541 /**
542 * Returns the name used for storing default shared preferences.
543 *
544 * @see #getDefaultSharedPreferences(Context)
545 * @see Context#getSharedPreferencesPath(String)
546 */
547 public static String getDefaultSharedPreferencesName(Context context) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 return context.getPackageName() + "_preferences";
549 }
550
551 private static int getDefaultSharedPreferencesMode() {
552 return Context.MODE_PRIVATE;
553 }
554
555 /**
556 * Returns the root of the preference hierarchy managed by this class.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000557 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 * @return The {@link PreferenceScreen} object that is at the root of the hierarchy.
559 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000560 @Nullable
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100561 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562 PreferenceScreen getPreferenceScreen() {
563 return mPreferenceScreen;
564 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 /**
567 * Sets the root of the preference hierarchy.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000568 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569 * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000570 * @return Whether the {@link PreferenceScreen} given is different than the previous.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100572 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 boolean setPreferences(PreferenceScreen preferenceScreen) {
574 if (preferenceScreen != mPreferenceScreen) {
575 mPreferenceScreen = preferenceScreen;
576 return true;
577 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579 return false;
580 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 /**
583 * Finds a {@link Preference} based on its key.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000584 *
Filip Pavlisee3bc342017-03-13 16:58:24 +0000585 * @param key the key of the preference to retrieve
586 * @return the {@link Preference} with the key, or {@code null}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 * @see PreferenceGroup#findPreference(CharSequence)
588 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000589 @Nullable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 public Preference findPreference(CharSequence key) {
591 if (mPreferenceScreen == null) {
592 return null;
593 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 return mPreferenceScreen.findPreference(key);
596 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 /**
Scott Mainbbb3f412012-03-09 19:10:40 -0800599 * Sets the default values from an XML preference file by reading the values defined
600 * by each {@link Preference} item's {@code android:defaultValue} attribute. This should
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 * be called by the application's main activity.
602 * <p>
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000603 *
Scott Mainbbb3f412012-03-09 19:10:40 -0800604 * @param context The context of the shared preferences.
605 * @param resId The resource ID of the preference XML file.
606 * @param readAgain Whether to re-read the default values.
607 * If false, this method sets the default values only if this
608 * method has never been called in the past (or if the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609 * {@link #KEY_HAS_SET_DEFAULT_VALUES} in the default value shared
610 * preferences file is false). To attempt to set the default values again
611 * bypassing this check, set {@code readAgain} to true.
Scott Mainbbb3f412012-03-09 19:10:40 -0800612 * <p class="note">
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 * Note: this will NOT reset preferences back to their default
614 * values. For that functionality, use
615 * {@link PreferenceManager#getDefaultSharedPreferences(Context)}
616 * and clear it followed by a call to this method with this
617 * parameter set to true.
618 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700619 public static void setDefaultValues(Context context, @XmlRes int resId, boolean readAgain) {
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 // Use the default shared preferences name and mode
622 setDefaultValues(context, getDefaultSharedPreferencesName(context),
623 getDefaultSharedPreferencesMode(), resId, readAgain);
624 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 /**
627 * Similar to {@link #setDefaultValues(Context, int, boolean)} but allows
628 * the client to provide the filename and mode of the shared preferences
629 * file.
Scott Mainbbb3f412012-03-09 19:10:40 -0800630 *
631 * @param context The context of the shared preferences.
632 * @param sharedPreferencesName A custom name for the shared preferences file.
633 * @param sharedPreferencesMode The file creation mode for the shared preferences file, such
634 * as {@link android.content.Context#MODE_PRIVATE} or {@link
635 * android.content.Context#MODE_PRIVATE}
636 * @param resId The resource ID of the preference XML file.
637 * @param readAgain Whether to re-read the default values.
638 * If false, this method will set the default values only if this
639 * method has never been called in the past (or if the
640 * {@link #KEY_HAS_SET_DEFAULT_VALUES} in the default value shared
641 * preferences file is false). To attempt to set the default values again
642 * bypassing this check, set {@code readAgain} to true.
643 * <p class="note">
644 * Note: this will NOT reset preferences back to their default
645 * values. For that functionality, use
646 * {@link PreferenceManager#getDefaultSharedPreferences(Context)}
647 * and clear it followed by a call to this method with this
648 * parameter set to true.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000649 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650 * @see #setDefaultValues(Context, int, boolean)
651 * @see #setSharedPreferencesName(String)
652 * @see #setSharedPreferencesMode(int)
653 */
654 public static void setDefaultValues(Context context, String sharedPreferencesName,
655 int sharedPreferencesMode, int resId, boolean readAgain) {
656 final SharedPreferences defaultValueSp = context.getSharedPreferences(
657 KEY_HAS_SET_DEFAULT_VALUES, Context.MODE_PRIVATE);
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 if (readAgain || !defaultValueSp.getBoolean(KEY_HAS_SET_DEFAULT_VALUES, false)) {
660 final PreferenceManager pm = new PreferenceManager(context);
661 pm.setSharedPreferencesName(sharedPreferencesName);
662 pm.setSharedPreferencesMode(sharedPreferencesMode);
663 pm.inflateFromResource(context, resId, null);
664
Brad Fitzpatrickdd644c12010-10-10 10:58:47 -0700665 SharedPreferences.Editor editor =
666 defaultValueSp.edit().putBoolean(KEY_HAS_SET_DEFAULT_VALUES, true);
667 try {
668 editor.apply();
669 } catch (AbstractMethodError unused) {
670 // The app injected its own pre-Gingerbread
671 // SharedPreferences.Editor implementation without
672 // an apply method.
673 editor.commit();
674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675 }
676 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 /**
679 * Returns an editor to use when modifying the shared preferences.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000680 *
Filip Pavlisee3bc342017-03-13 16:58:24 +0000681 * <p>Do NOT commit unless {@link #shouldCommit()} returns true.
682 *
683 * @return an editor to use to write to shared preferences. If a {@link PreferenceDataStore}
684 * has been set, this method returns {@code null}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 * @see #shouldCommit()
686 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100687 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 SharedPreferences.Editor getEditor() {
Filip Pavlis09557932017-03-03 16:54:22 +0000689 if (mPreferenceDataStore != null) {
690 return null;
691 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 if (mNoCommit) {
694 if (mEditor == null) {
695 mEditor = getSharedPreferences().edit();
696 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698 return mEditor;
699 } else {
700 return getSharedPreferences().edit();
701 }
702 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000703
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 /**
705 * Whether it is the client's responsibility to commit on the
706 * {@link #getEditor()}. This will return false in cases where the writes
707 * should be batched, for example when inflating preferences from XML.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000708 *
Filip Pavlisee3bc342017-03-13 16:58:24 +0000709 * <p>If preferences are using {@link PreferenceDataStore} this value is irrelevant.
710 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 * @return Whether the client should commit.
712 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100713 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 boolean shouldCommit() {
715 return !mNoCommit;
716 }
Brad Fitzpatrickdd644c12010-10-10 10:58:47 -0700717
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100718 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 private void setNoCommit(boolean noCommit) {
720 if (!noCommit && mEditor != null) {
Brad Fitzpatrickdd644c12010-10-10 10:58:47 -0700721 try {
722 mEditor.apply();
723 } catch (AbstractMethodError unused) {
724 // The app injected its own pre-Gingerbread
725 // SharedPreferences.Editor implementation without
726 // an apply method.
727 mEditor.commit();
728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800730 mNoCommit = noCommit;
731 }
Brad Fitzpatrickdd644c12010-10-10 10:58:47 -0700732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 /**
734 * Returns the activity that shows the preferences. This is useful for doing
735 * managed queries, but in most cases the use of {@link #getContext()} is
736 * preferred.
Filip Pavlisee3bc342017-03-13 16:58:24 +0000737 *
738 * <p>This will return {@code null} if this class was instantiated with a Context
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 * instead of Activity. For example, when setting the default values.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000740 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 * @return The activity that shows the preferences.
742 * @see #mContext
743 */
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000744 @Nullable
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100745 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 Activity getActivity() {
747 return mActivity;
748 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 /**
751 * Returns the context. This is preferred over {@link #getActivity()} when
752 * possible.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000753 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 * @return The context.
755 */
756 Context getContext() {
757 return mContext;
758 }
759
760 /**
761 * Registers a listener.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000762 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 * @see OnActivityResultListener
764 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100765 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 void registerOnActivityResultListener(OnActivityResultListener listener) {
767 synchronized (this) {
768 if (mActivityResultListeners == null) {
769 mActivityResultListeners = new ArrayList<OnActivityResultListener>();
770 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 if (!mActivityResultListeners.contains(listener)) {
773 mActivityResultListeners.add(listener);
774 }
775 }
776 }
777
778 /**
779 * Unregisters a listener.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000780 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 * @see OnActivityResultListener
782 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100783 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 void unregisterOnActivityResultListener(OnActivityResultListener listener) {
785 synchronized (this) {
786 if (mActivityResultListeners != null) {
787 mActivityResultListeners.remove(listener);
788 }
789 }
790 }
791
792 /**
793 * Called by the {@link PreferenceManager} to dispatch a subactivity result.
794 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100795 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 void dispatchActivityResult(int requestCode, int resultCode, Intent data) {
797 List<OnActivityResultListener> list;
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 synchronized (this) {
800 if (mActivityResultListeners == null) return;
801 list = new ArrayList<OnActivityResultListener>(mActivityResultListeners);
802 }
803
804 final int N = list.size();
805 for (int i = 0; i < N; i++) {
806 if (list.get(i).onActivityResult(requestCode, resultCode, data)) {
807 break;
808 }
809 }
810 }
811
812 /**
813 * Registers a listener.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000814 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 * @see OnActivityStopListener
John Spurlock74a2e062014-05-16 21:03:29 -0400816 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100818 @UnsupportedAppUsage
John Spurlock74a2e062014-05-16 21:03:29 -0400819 public void registerOnActivityStopListener(OnActivityStopListener listener) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 synchronized (this) {
821 if (mActivityStopListeners == null) {
822 mActivityStopListeners = new ArrayList<OnActivityStopListener>();
823 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 if (!mActivityStopListeners.contains(listener)) {
826 mActivityStopListeners.add(listener);
827 }
828 }
829 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 /**
832 * Unregisters a listener.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000833 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 * @see OnActivityStopListener
John Spurlock74a2e062014-05-16 21:03:29 -0400835 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100837 @UnsupportedAppUsage
John Spurlock74a2e062014-05-16 21:03:29 -0400838 public void unregisterOnActivityStopListener(OnActivityStopListener listener) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 synchronized (this) {
840 if (mActivityStopListeners != null) {
841 mActivityStopListeners.remove(listener);
842 }
843 }
844 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 /**
847 * Called by the {@link PreferenceManager} to dispatch the activity stop
848 * event.
849 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100850 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800851 void dispatchActivityStop() {
852 List<OnActivityStopListener> list;
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854 synchronized (this) {
855 if (mActivityStopListeners == null) return;
856 list = new ArrayList<OnActivityStopListener>(mActivityStopListeners);
857 }
858
859 final int N = list.size();
860 for (int i = 0; i < N; i++) {
861 list.get(i).onActivityStop();
862 }
863 }
864
865 /**
866 * Registers a listener.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000867 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 * @see OnActivityDestroyListener
869 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100870 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800871 void registerOnActivityDestroyListener(OnActivityDestroyListener listener) {
872 synchronized (this) {
873 if (mActivityDestroyListeners == null) {
874 mActivityDestroyListeners = new ArrayList<OnActivityDestroyListener>();
875 }
876
877 if (!mActivityDestroyListeners.contains(listener)) {
878 mActivityDestroyListeners.add(listener);
879 }
880 }
881 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 /**
884 * Unregisters a listener.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000885 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 * @see OnActivityDestroyListener
887 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100888 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800889 void unregisterOnActivityDestroyListener(OnActivityDestroyListener listener) {
890 synchronized (this) {
891 if (mActivityDestroyListeners != null) {
892 mActivityDestroyListeners.remove(listener);
893 }
894 }
895 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 /**
898 * Called by the {@link PreferenceManager} to dispatch the activity destroy
899 * event.
900 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100901 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 void dispatchActivityDestroy() {
903 List<OnActivityDestroyListener> list = null;
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 synchronized (this) {
906 if (mActivityDestroyListeners != null) {
907 list = new ArrayList<OnActivityDestroyListener>(mActivityDestroyListeners);
908 }
909 }
910
911 if (list != null) {
912 final int N = list.size();
913 for (int i = 0; i < N; i++) {
914 list.get(i).onActivityDestroy();
915 }
916 }
917
918 // Dismiss any PreferenceScreens still showing
919 dismissAllScreens();
920 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 /**
923 * Returns a request code that is unique for the activity. Each subsequent
924 * call to this method should return another unique request code.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000925 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 * @return A unique request code that will never be used by anyone other
927 * than the caller of this method.
928 */
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +0100929 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 int getNextRequestCode() {
931 synchronized (this) {
932 return mNextRequestCode++;
933 }
934 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 void addPreferencesScreen(DialogInterface screen) {
937 synchronized (this) {
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 if (mPreferencesScreens == null) {
940 mPreferencesScreens = new ArrayList<DialogInterface>();
941 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943 mPreferencesScreens.add(screen);
944 }
945 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 void removePreferencesScreen(DialogInterface screen) {
948 synchronized (this) {
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 if (mPreferencesScreens == null) {
951 return;
952 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 mPreferencesScreens.remove(screen);
955 }
956 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000957
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 /**
959 * Called by {@link PreferenceActivity} to dispatch the new Intent event.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000960 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 * @param intent The new Intent.
962 */
963 void dispatchNewIntent(Intent intent) {
964 dismissAllScreens();
965 }
966
967 private void dismissAllScreens() {
968 // Remove any of the previously shown preferences screens
969 ArrayList<DialogInterface> screensToDismiss;
970
971 synchronized (this) {
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 if (mPreferencesScreens == null) {
974 return;
975 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000976
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 screensToDismiss = new ArrayList<DialogInterface>(mPreferencesScreens);
978 mPreferencesScreens.clear();
979 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 for (int i = screensToDismiss.size() - 1; i >= 0; i--) {
982 screensToDismiss.get(i).dismiss();
983 }
984 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 /**
987 * Sets the callback to be invoked when a {@link Preference} in the
988 * hierarchy rooted at this {@link PreferenceManager} is clicked.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000989 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990 * @param listener The callback to be invoked.
991 */
992 void setOnPreferenceTreeClickListener(OnPreferenceTreeClickListener listener) {
993 mOnPreferenceTreeClickListener = listener;
994 }
995
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +0000996 @Nullable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 OnPreferenceTreeClickListener getOnPreferenceTreeClickListener() {
998 return mOnPreferenceTreeClickListener;
999 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +00001000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 /**
1002 * Interface definition for a callback to be invoked when a
1003 * {@link Preference} in the hierarchy rooted at this {@link PreferenceScreen} is
1004 * clicked.
Fabrice Di Meglioad2fcfe2014-01-20 11:10:52 -08001005 *
1006 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 */
Fabrice Di Meglioad2fcfe2014-01-20 11:10:52 -08001008 public interface OnPreferenceTreeClickListener {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 /**
1010 * Called when a preference in the tree rooted at this
1011 * {@link PreferenceScreen} has been clicked.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +00001012 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 * @param preferenceScreen The {@link PreferenceScreen} that the
1014 * preference is located in.
1015 * @param preference The preference that was clicked.
1016 * @return Whether the click was handled.
1017 */
1018 boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference);
1019 }
1020
1021 /**
1022 * Interface definition for a class that will be called when the container's activity
1023 * receives an activity result.
1024 */
1025 public interface OnActivityResultListener {
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +00001026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027 /**
1028 * See Activity's onActivityResult.
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +00001029 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 * @return Whether the request code was handled (in which case
1031 * subsequent listeners will not be called.
1032 */
1033 boolean onActivityResult(int requestCode, int resultCode, Intent data);
1034 }
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +00001035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001036 /**
1037 * Interface definition for a class that will be called when the container's activity
1038 * is stopped.
1039 */
1040 public interface OnActivityStopListener {
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +00001041
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 /**
1043 * See Activity's onStop.
1044 */
1045 void onActivityStop();
1046 }
1047
1048 /**
1049 * Interface definition for a class that will be called when the container's activity
1050 * is destroyed.
1051 */
1052 public interface OnActivityDestroyListener {
Filip Pavlis0b0c6cb2016-11-16 15:58:28 +00001053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 /**
1055 * See Activity's onDestroy.
1056 */
1057 void onActivityDestroy();
1058 }
1059
1060}