1 /* 2 * Copyright (C) 2010 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 17 package com.android.settings; 18 19 import android.app.Activity; 20 import android.app.Dialog; 21 import android.app.admin.DevicePolicyManager; 22 import android.content.ContentResolver; 23 import android.content.Context; 24 import android.content.DialogInterface; 25 import android.content.Intent; 26 import android.content.pm.PackageManager; 27 import android.os.Bundle; 28 import android.text.TextUtils; 29 import android.util.ArrayMap; 30 import android.util.Log; 31 import android.view.LayoutInflater; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.widget.Button; 35 36 import androidx.annotation.VisibleForTesting; 37 import androidx.annotation.XmlRes; 38 import androidx.fragment.app.DialogFragment; 39 import androidx.fragment.app.Fragment; 40 import androidx.preference.Preference; 41 import androidx.preference.PreferenceGroup; 42 import androidx.preference.PreferenceScreen; 43 import androidx.recyclerview.widget.LinearLayoutManager; 44 import androidx.recyclerview.widget.RecyclerView; 45 46 import com.android.settings.core.InstrumentedPreferenceFragment; 47 import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 48 import com.android.settings.support.actionbar.HelpResourceProvider; 49 import com.android.settings.widget.HighlightablePreferenceGroupAdapter; 50 import com.android.settings.widget.LoadingViewController; 51 import com.android.settingslib.CustomDialogPreferenceCompat; 52 import com.android.settingslib.CustomEditTextPreferenceCompat; 53 import com.android.settingslib.core.instrumentation.Instrumentable; 54 import com.android.settingslib.search.Indexable; 55 import com.android.settingslib.widget.LayoutPreference; 56 57 import com.google.android.material.appbar.AppBarLayout; 58 import com.google.android.setupcompat.util.WizardManagerHelper; 59 60 import java.util.UUID; 61 62 /** 63 * Base class for Settings fragments, with some helper functions and dialog management. 64 */ 65 public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceFragment 66 implements DialogCreatable, HelpResourceProvider, Indexable { 67 68 private static final String TAG = "SettingsPreferenceFragment"; 69 70 private static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted"; 71 72 private static final int ORDER_FIRST = -1; 73 74 protected DevicePolicyManager mDevicePolicyManager; 75 private SettingsDialogFragment mDialogFragment; 76 // Cache the content resolver for async callbacks 77 private ContentResolver mContentResolver; 78 79 private RecyclerView.Adapter mCurrentRootAdapter; 80 private boolean mIsDataSetObserverRegistered = false; 81 private RecyclerView.AdapterDataObserver mDataSetObserver = 82 new RecyclerView.AdapterDataObserver() { 83 @Override 84 public void onChanged() { 85 onDataSetChanged(); 86 } 87 88 @Override 89 public void onItemRangeChanged(int positionStart, int itemCount) { 90 onDataSetChanged(); 91 } 92 93 @Override 94 public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { 95 onDataSetChanged(); 96 } 97 98 @Override 99 public void onItemRangeInserted(int positionStart, int itemCount) { 100 onDataSetChanged(); 101 } 102 103 @Override 104 public void onItemRangeRemoved(int positionStart, int itemCount) { 105 onDataSetChanged(); 106 } 107 108 @Override 109 public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { 110 onDataSetChanged(); 111 } 112 }; 113 114 @VisibleForTesting 115 ViewGroup mPinnedHeaderFrameLayout; 116 private AppBarLayout mAppBarLayout; 117 private LayoutPreference mHeader; 118 private View mEmptyView; 119 private LinearLayoutManager mLayoutManager; 120 private ArrayMap<String, Preference> mPreferenceCache; 121 private boolean mAnimationAllowed; 122 123 @VisibleForTesting 124 public HighlightablePreferenceGroupAdapter mAdapter; 125 private boolean mPreferenceHighlighted = false; 126 127 @Override onAttach(Context context)128 public void onAttach(Context context) { 129 if (shouldSkipForInitialSUW() && !WizardManagerHelper.isDeviceProvisioned(getContext())) { 130 Log.w(TAG, "Skip " + getClass().getSimpleName() + " before SUW completed."); 131 finish(); 132 } 133 super.onAttach(context); 134 } 135 136 @Override onCreate(Bundle icicle)137 public void onCreate(Bundle icicle) { 138 super.onCreate(icicle); 139 140 mDevicePolicyManager = getContext().getSystemService(DevicePolicyManager.class); 141 if (icicle != null) { 142 mPreferenceHighlighted = icicle.getBoolean(SAVE_HIGHLIGHTED_KEY); 143 } 144 HighlightablePreferenceGroupAdapter.adjustInitialExpandedChildCount(this /* host */); 145 } 146 147 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)148 public View onCreateView(LayoutInflater inflater, ViewGroup container, 149 Bundle savedInstanceState) { 150 final View root = super.onCreateView(inflater, container, savedInstanceState); 151 mPinnedHeaderFrameLayout = root.findViewById(R.id.pinned_header); 152 mAppBarLayout = getActivity().findViewById(R.id.app_bar); 153 return root; 154 } 155 156 @Override addPreferencesFromResource(@mlRes int preferencesResId)157 public void addPreferencesFromResource(@XmlRes int preferencesResId) { 158 super.addPreferencesFromResource(preferencesResId); 159 checkAvailablePrefs(getPreferenceScreen()); 160 } 161 162 @VisibleForTesting checkAvailablePrefs(PreferenceGroup preferenceGroup)163 void checkAvailablePrefs(PreferenceGroup preferenceGroup) { 164 if (preferenceGroup == null) return; 165 for (int i = 0; i < preferenceGroup.getPreferenceCount(); i++) { 166 Preference pref = preferenceGroup.getPreference(i); 167 if (pref instanceof SelfAvailablePreference 168 && !((SelfAvailablePreference) pref).isAvailable(getContext())) { 169 pref.setVisible(false); 170 } else if (pref instanceof PreferenceGroup) { 171 checkAvailablePrefs((PreferenceGroup) pref); 172 } 173 } 174 } 175 setPinnedHeaderView(int layoutResId)176 public View setPinnedHeaderView(int layoutResId) { 177 final LayoutInflater inflater = getActivity().getLayoutInflater(); 178 final View pinnedHeader = 179 inflater.inflate(layoutResId, mPinnedHeaderFrameLayout, false); 180 setPinnedHeaderView(pinnedHeader); 181 return pinnedHeader; 182 } 183 setPinnedHeaderView(View pinnedHeader)184 public void setPinnedHeaderView(View pinnedHeader) { 185 mPinnedHeaderFrameLayout.addView(pinnedHeader); 186 mPinnedHeaderFrameLayout.setVisibility(View.VISIBLE); 187 } 188 showPinnedHeader(boolean show)189 public void showPinnedHeader(boolean show) { 190 mPinnedHeaderFrameLayout.setVisibility(show ? View.VISIBLE : View.INVISIBLE); 191 } 192 193 @Override onSaveInstanceState(Bundle outState)194 public void onSaveInstanceState(Bundle outState) { 195 super.onSaveInstanceState(outState); 196 197 if (mAdapter != null) { 198 outState.putBoolean(SAVE_HIGHLIGHTED_KEY, mAdapter.isHighlightRequested()); 199 } 200 } 201 202 @Override onActivityCreated(Bundle savedInstanceState)203 public void onActivityCreated(Bundle savedInstanceState) { 204 super.onActivityCreated(savedInstanceState); 205 setHasOptionsMenu(true); 206 } 207 208 @Override onResume()209 public void onResume() { 210 super.onResume(); 211 highlightPreferenceIfNeeded(); 212 } 213 214 @Override onBindPreferences()215 protected void onBindPreferences() { 216 registerObserverIfNeeded(); 217 } 218 219 @Override onUnbindPreferences()220 protected void onUnbindPreferences() { 221 unregisterObserverIfNeeded(); 222 } 223 setLoading(boolean loading, boolean animate)224 public void setLoading(boolean loading, boolean animate) { 225 View loadingContainer = getView().findViewById(R.id.loading_container); 226 LoadingViewController.handleLoadingContainer(loadingContainer, getListView(), 227 !loading /* done */, 228 animate); 229 } 230 registerObserverIfNeeded()231 public void registerObserverIfNeeded() { 232 if (!mIsDataSetObserverRegistered) { 233 if (mCurrentRootAdapter != null) { 234 mCurrentRootAdapter.unregisterAdapterDataObserver(mDataSetObserver); 235 } 236 mCurrentRootAdapter = getListView().getAdapter(); 237 mCurrentRootAdapter.registerAdapterDataObserver(mDataSetObserver); 238 mIsDataSetObserverRegistered = true; 239 onDataSetChanged(); 240 } 241 } 242 unregisterObserverIfNeeded()243 public void unregisterObserverIfNeeded() { 244 if (mIsDataSetObserverRegistered) { 245 if (mCurrentRootAdapter != null) { 246 mCurrentRootAdapter.unregisterAdapterDataObserver(mDataSetObserver); 247 mCurrentRootAdapter = null; 248 } 249 mIsDataSetObserverRegistered = false; 250 } 251 } 252 highlightPreferenceIfNeeded()253 public void highlightPreferenceIfNeeded() { 254 if (!isAdded()) { 255 return; 256 } 257 if (mAdapter != null) { 258 mAdapter.requestHighlight(getView(), getListView(), mAppBarLayout); 259 } 260 } 261 262 /** 263 * Returns initial expanded child count. 264 * <p/> 265 * Only override this method if the initial expanded child must be determined at run time. 266 */ getInitialExpandedChildCount()267 public int getInitialExpandedChildCount() { 268 return 0; 269 } 270 271 /** 272 * Whether preference is allowing to be displayed to the user. 273 * 274 * @param preference to check if it can be displayed to the user (not hidding in expand area). 275 * @return {@code true} when preference is allowing to be displayed to the user. 276 * {@code false} when preference is hidden in expand area and not been displayed to the user. 277 */ isPreferenceExpanded(Preference preference)278 protected boolean isPreferenceExpanded(Preference preference) { 279 return ((mAdapter == null) 280 || (mAdapter.getPreferenceAdapterPosition(preference) != RecyclerView.NO_POSITION)); 281 } 282 283 /** 284 * Whether UI should be skipped in the initial SUW flow. 285 * 286 * @return {@code true} when UI should be skipped in the initial SUW flow. 287 * {@code false} when UI should not be skipped in the initial SUW flow. 288 */ shouldSkipForInitialSUW()289 protected boolean shouldSkipForInitialSUW() { 290 return false; 291 } 292 onDataSetChanged()293 protected void onDataSetChanged() { 294 highlightPreferenceIfNeeded(); 295 updateEmptyView(); 296 } 297 getHeaderView()298 public LayoutPreference getHeaderView() { 299 return mHeader; 300 } 301 setHeaderView(int resource)302 protected void setHeaderView(int resource) { 303 mHeader = new LayoutPreference(getPrefContext(), resource); 304 mHeader.setSelectable(false); 305 addPreferenceToTop(mHeader); 306 } 307 setHeaderView(View view)308 protected void setHeaderView(View view) { 309 mHeader = new LayoutPreference(getPrefContext(), view); 310 mHeader.setSelectable(false); 311 addPreferenceToTop(mHeader); 312 } 313 addPreferenceToTop(LayoutPreference preference)314 private void addPreferenceToTop(LayoutPreference preference) { 315 preference.setOrder(ORDER_FIRST); 316 if (getPreferenceScreen() != null) { 317 getPreferenceScreen().addPreference(preference); 318 } 319 } 320 321 @Override setPreferenceScreen(PreferenceScreen preferenceScreen)322 public void setPreferenceScreen(PreferenceScreen preferenceScreen) { 323 if (preferenceScreen != null && !preferenceScreen.isAttached()) { 324 // Without ids generated, the RecyclerView won't animate changes to the preferences. 325 preferenceScreen.setShouldUseGeneratedIds(mAnimationAllowed); 326 } 327 super.setPreferenceScreen(preferenceScreen); 328 if (preferenceScreen != null) { 329 if (mHeader != null) { 330 preferenceScreen.addPreference(mHeader); 331 } 332 } 333 } 334 335 @VisibleForTesting updateEmptyView()336 void updateEmptyView() { 337 if (mEmptyView == null) return; 338 if (getPreferenceScreen() != null) { 339 final View listContainer = getActivity().findViewById(android.R.id.list_container); 340 boolean show = (getPreferenceScreen().getPreferenceCount() 341 - (mHeader != null ? 1 : 0)) <= 0 342 || (listContainer != null && listContainer.getVisibility() != View.VISIBLE); 343 mEmptyView.setVisibility(show ? View.VISIBLE : View.GONE); 344 } else { 345 mEmptyView.setVisibility(View.VISIBLE); 346 } 347 } 348 setEmptyView(View v)349 public void setEmptyView(View v) { 350 if (mEmptyView != null) { 351 mEmptyView.setVisibility(View.GONE); 352 } 353 mEmptyView = v; 354 updateEmptyView(); 355 } 356 getEmptyView()357 public View getEmptyView() { 358 return mEmptyView; 359 } 360 361 @Override onCreateLayoutManager()362 public RecyclerView.LayoutManager onCreateLayoutManager() { 363 mLayoutManager = new LinearLayoutManager(getContext()); 364 return mLayoutManager; 365 } 366 367 @Override onCreateAdapter(PreferenceScreen preferenceScreen)368 protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) { 369 final Bundle arguments = getArguments(); 370 mAdapter = new HighlightablePreferenceGroupAdapter(preferenceScreen, 371 arguments == null 372 ? null : arguments.getString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY), 373 mPreferenceHighlighted); 374 return mAdapter; 375 } 376 setAnimationAllowed(boolean animationAllowed)377 protected void setAnimationAllowed(boolean animationAllowed) { 378 mAnimationAllowed = animationAllowed; 379 } 380 cacheRemoveAllPrefs(PreferenceGroup group)381 protected void cacheRemoveAllPrefs(PreferenceGroup group) { 382 mPreferenceCache = new ArrayMap<>(); 383 final int N = group.getPreferenceCount(); 384 for (int i = 0; i < N; i++) { 385 Preference p = group.getPreference(i); 386 if (TextUtils.isEmpty(p.getKey())) { 387 continue; 388 } 389 mPreferenceCache.put(p.getKey(), p); 390 } 391 } 392 getCachedPreference(String key)393 protected Preference getCachedPreference(String key) { 394 return mPreferenceCache != null ? mPreferenceCache.remove(key) : null; 395 } 396 removeCachedPrefs(PreferenceGroup group)397 protected void removeCachedPrefs(PreferenceGroup group) { 398 for (Preference p : mPreferenceCache.values()) { 399 group.removePreference(p); 400 } 401 mPreferenceCache = null; 402 } 403 getCachedCount()404 protected int getCachedCount() { 405 return mPreferenceCache != null ? mPreferenceCache.size() : 0; 406 } 407 408 @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) removePreference(String key)409 public boolean removePreference(String key) { 410 return removePreference(getPreferenceScreen(), key); 411 } 412 413 @VisibleForTesting removePreference(PreferenceGroup group, String key)414 boolean removePreference(PreferenceGroup group, String key) { 415 final int preferenceCount = group.getPreferenceCount(); 416 for (int i = 0; i < preferenceCount; i++) { 417 final Preference preference = group.getPreference(i); 418 final String curKey = preference.getKey(); 419 420 if (TextUtils.equals(curKey, key)) { 421 return group.removePreference(preference); 422 } 423 424 if (preference instanceof PreferenceGroup) { 425 if (removePreference((PreferenceGroup) preference, key)) { 426 return true; 427 } 428 } 429 } 430 return false; 431 } 432 433 /* 434 * The name is intentionally made different from Activity#finish(), so that 435 * users won't misunderstand its meaning. 436 */ finishFragment()437 public final void finishFragment() { 438 getActivity().onBackPressed(); 439 } 440 441 // Some helpers for functions used by the settings fragments when they were activities 442 443 /** 444 * Returns the ContentResolver from the owning Activity. 445 */ getContentResolver()446 protected ContentResolver getContentResolver() { 447 Context context = getActivity(); 448 if (context != null) { 449 mContentResolver = context.getContentResolver(); 450 } 451 return mContentResolver; 452 } 453 454 /** 455 * Returns the specified system service from the owning Activity. 456 */ getSystemService(final String name)457 protected Object getSystemService(final String name) { 458 return getActivity().getSystemService(name); 459 } 460 461 /** 462 * Returns the specified system service from the owning Activity. 463 */ getSystemService(final Class<T> serviceClass)464 protected <T> T getSystemService(final Class<T> serviceClass) { 465 return getActivity().getSystemService(serviceClass); 466 } 467 468 /** 469 * Returns the PackageManager from the owning Activity. 470 */ getPackageManager()471 protected PackageManager getPackageManager() { 472 return getActivity().getPackageManager(); 473 } 474 475 @Override onDetach()476 public void onDetach() { 477 if (isRemoving()) { 478 if (mDialogFragment != null) { 479 mDialogFragment.dismiss(); 480 mDialogFragment = null; 481 } 482 RecyclerView view = getListView(); 483 if (view != null) { 484 view.clearOnScrollListeners(); 485 } 486 } 487 super.onDetach(); 488 } 489 490 // Dialog management 491 showDialog(int dialogId)492 protected void showDialog(int dialogId) { 493 if (mDialogFragment != null) { 494 Log.e(TAG, "Old dialog fragment not null!"); 495 } 496 mDialogFragment = SettingsDialogFragment.newInstance(this, dialogId); 497 mDialogFragment.show(getChildFragmentManager(), Integer.toString(dialogId)); 498 } 499 500 @Override onCreateDialog(int dialogId)501 public Dialog onCreateDialog(int dialogId) { 502 return null; 503 } 504 505 @Override getDialogMetricsCategory(int dialogId)506 public int getDialogMetricsCategory(int dialogId) { 507 return 0; 508 } 509 removeDialog(int dialogId)510 protected void removeDialog(int dialogId) { 511 // mDialogFragment may not be visible yet in parent fragment's onResume(). 512 // To be able to dismiss dialog at that time, don't check 513 // mDialogFragment.isVisible(). 514 if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId) { 515 mDialogFragment.dismissAllowingStateLoss(); 516 } 517 mDialogFragment = null; 518 } 519 520 /** 521 * Sets the OnCancelListener of the dialog shown. This method can only be 522 * called after showDialog(int) and before removeDialog(int). The method 523 * does nothing otherwise. 524 */ setOnCancelListener(DialogInterface.OnCancelListener listener)525 protected void setOnCancelListener(DialogInterface.OnCancelListener listener) { 526 if (mDialogFragment != null) { 527 mDialogFragment.mOnCancelListener = listener; 528 } 529 } 530 531 /** 532 * Sets the OnDismissListener of the dialog shown. This method can only be 533 * called after showDialog(int) and before removeDialog(int). The method 534 * does nothing otherwise. 535 */ setOnDismissListener(DialogInterface.OnDismissListener listener)536 protected void setOnDismissListener(DialogInterface.OnDismissListener listener) { 537 if (mDialogFragment != null) { 538 mDialogFragment.mOnDismissListener = listener; 539 } 540 } 541 onDialogShowing()542 public void onDialogShowing() { 543 // override in subclass to attach a dismiss listener, for instance 544 } 545 546 @Override onDisplayPreferenceDialog(Preference preference)547 public void onDisplayPreferenceDialog(Preference preference) { 548 if (preference.getKey() == null) { 549 // Auto-key preferences that don't have a key, so the dialog can find them. 550 preference.setKey(UUID.randomUUID().toString()); 551 } 552 DialogFragment f = null; 553 if (preference instanceof RestrictedListPreference) { 554 f = RestrictedListPreference.RestrictedListPreferenceDialogFragment 555 .newInstance(preference.getKey()); 556 } else if (preference instanceof CustomListPreference) { 557 f = CustomListPreference.CustomListPreferenceDialogFragment 558 .newInstance(preference.getKey()); 559 } else if (preference instanceof CustomDialogPreferenceCompat) { 560 f = CustomDialogPreferenceCompat.CustomPreferenceDialogFragment 561 .newInstance(preference.getKey()); 562 } else if (preference instanceof CustomEditTextPreferenceCompat) { 563 f = CustomEditTextPreferenceCompat.CustomPreferenceDialogFragment 564 .newInstance(preference.getKey()); 565 } else { 566 super.onDisplayPreferenceDialog(preference); 567 return; 568 } 569 f.setTargetFragment(this, 0); 570 f.show(getFragmentManager(), "dialog_preference"); 571 onDialogShowing(); 572 } 573 574 public static class SettingsDialogFragment extends InstrumentedDialogFragment { 575 private static final String KEY_DIALOG_ID = "key_dialog_id"; 576 private static final String KEY_PARENT_FRAGMENT_ID = "key_parent_fragment_id"; 577 578 private Fragment mParentFragment; 579 580 private DialogInterface.OnCancelListener mOnCancelListener; 581 private DialogInterface.OnDismissListener mOnDismissListener; 582 newInstance(DialogCreatable fragment, int dialogId)583 public static SettingsDialogFragment newInstance(DialogCreatable fragment, int dialogId) { 584 if (!(fragment instanceof Fragment)) { 585 throw new IllegalArgumentException("fragment argument must be an instance of " 586 + Fragment.class.getName()); 587 } 588 589 final SettingsDialogFragment settingsDialogFragment = new SettingsDialogFragment(); 590 settingsDialogFragment.setParentFragment(fragment); 591 settingsDialogFragment.setDialogId(dialogId); 592 593 return settingsDialogFragment; 594 } 595 596 @Override getMetricsCategory()597 public int getMetricsCategory() { 598 if (mParentFragment == null) { 599 return Instrumentable.METRICS_CATEGORY_UNKNOWN; 600 } 601 final int metricsCategory = 602 ((DialogCreatable) mParentFragment).getDialogMetricsCategory(mDialogId); 603 if (metricsCategory <= 0) { 604 throw new IllegalStateException("Dialog must provide a metrics category"); 605 } 606 return metricsCategory; 607 } 608 609 @Override onSaveInstanceState(Bundle outState)610 public void onSaveInstanceState(Bundle outState) { 611 super.onSaveInstanceState(outState); 612 if (mParentFragment != null) { 613 outState.putInt(KEY_DIALOG_ID, mDialogId); 614 outState.putInt(KEY_PARENT_FRAGMENT_ID, mParentFragment.getId()); 615 } 616 } 617 618 @Override onStart()619 public void onStart() { 620 super.onStart(); 621 622 if (mParentFragment != null && mParentFragment instanceof SettingsPreferenceFragment) { 623 ((SettingsPreferenceFragment) mParentFragment).onDialogShowing(); 624 } 625 } 626 627 @Override onCreateDialog(Bundle savedInstanceState)628 public Dialog onCreateDialog(Bundle savedInstanceState) { 629 if (savedInstanceState != null) { 630 mDialogId = savedInstanceState.getInt(KEY_DIALOG_ID, 0); 631 mParentFragment = getParentFragment(); 632 int mParentFragmentId = savedInstanceState.getInt(KEY_PARENT_FRAGMENT_ID, -1); 633 if (mParentFragment == null) { 634 mParentFragment = getFragmentManager().findFragmentById(mParentFragmentId); 635 } 636 if (!(mParentFragment instanceof DialogCreatable)) { 637 throw new IllegalArgumentException( 638 (mParentFragment != null 639 ? mParentFragment.getClass().getName() 640 : mParentFragmentId) 641 + " must implement " 642 + DialogCreatable.class.getName()); 643 } 644 // This dialog fragment could be created from non-SettingsPreferenceFragment 645 if (mParentFragment instanceof SettingsPreferenceFragment) { 646 // restore mDialogFragment in mParentFragment 647 ((SettingsPreferenceFragment) mParentFragment).mDialogFragment = this; 648 } 649 } 650 return ((DialogCreatable) mParentFragment).onCreateDialog(mDialogId); 651 } 652 653 @Override onCancel(DialogInterface dialog)654 public void onCancel(DialogInterface dialog) { 655 super.onCancel(dialog); 656 if (mOnCancelListener != null) { 657 mOnCancelListener.onCancel(dialog); 658 } 659 } 660 661 @Override onDismiss(DialogInterface dialog)662 public void onDismiss(DialogInterface dialog) { 663 super.onDismiss(dialog); 664 if (mOnDismissListener != null) { 665 mOnDismissListener.onDismiss(dialog); 666 } 667 } 668 getDialogId()669 public int getDialogId() { 670 return mDialogId; 671 } 672 673 @Override onDetach()674 public void onDetach() { 675 super.onDetach(); 676 677 // This dialog fragment could be created from non-SettingsPreferenceFragment 678 if (mParentFragment instanceof SettingsPreferenceFragment) { 679 // in case the dialog is not explicitly removed by removeDialog() 680 if (((SettingsPreferenceFragment) mParentFragment).mDialogFragment == this) { 681 ((SettingsPreferenceFragment) mParentFragment).mDialogFragment = null; 682 } 683 } 684 } 685 setParentFragment(DialogCreatable fragment)686 private void setParentFragment(DialogCreatable fragment) { 687 mParentFragment = (Fragment) fragment; 688 } 689 setDialogId(int dialogId)690 private void setDialogId(int dialogId) { 691 mDialogId = dialogId; 692 } 693 } 694 hasNextButton()695 protected boolean hasNextButton() { 696 return ((ButtonBarHandler) getActivity()).hasNextButton(); 697 } 698 getNextButton()699 protected Button getNextButton() { 700 return ((ButtonBarHandler) getActivity()).getNextButton(); 701 } 702 finish()703 public void finish() { 704 Activity activity = getActivity(); 705 if (activity == null) return; 706 if (getFragmentManager().getBackStackEntryCount() > 0) { 707 getFragmentManager().popBackStack(); 708 } else { 709 activity.finish(); 710 } 711 } 712 getIntent()713 protected Intent getIntent() { 714 if (getActivity() == null) { 715 return null; 716 } 717 return getActivity().getIntent(); 718 } 719 setResult(int result, Intent intent)720 protected void setResult(int result, Intent intent) { 721 if (getActivity() == null) { 722 return; 723 } 724 getActivity().setResult(result, intent); 725 } 726 setResult(int result)727 protected void setResult(int result) { 728 if (getActivity() == null) { 729 return; 730 } 731 getActivity().setResult(result); 732 } 733 isFinishingOrDestroyed()734 protected boolean isFinishingOrDestroyed() { 735 final Activity activity = getActivity(); 736 return activity == null || activity.isFinishing() || activity.isDestroyed(); 737 } 738 replaceEnterprisePreferenceScreenTitle(String overrideKey, int resource)739 protected void replaceEnterprisePreferenceScreenTitle(String overrideKey, int resource) { 740 getActivity().setTitle(mDevicePolicyManager.getResources().getString( 741 overrideKey, () -> getString(resource))); 742 } 743 replaceEnterpriseStringSummary( String preferenceKey, String overrideKey, int resource)744 public void replaceEnterpriseStringSummary( 745 String preferenceKey, String overrideKey, int resource) { 746 Preference preference = findPreference(preferenceKey); 747 if (preference == null) { 748 Log.d(TAG, "Could not find enterprise preference " + preferenceKey); 749 return; 750 } 751 752 preference.setSummary( 753 mDevicePolicyManager.getResources().getString(overrideKey, 754 () -> getString(resource))); 755 } 756 replaceEnterpriseStringTitle( String preferenceKey, String overrideKey, int resource)757 public void replaceEnterpriseStringTitle( 758 String preferenceKey, String overrideKey, int resource) { 759 Preference preference = findPreference(preferenceKey); 760 if (preference == null) { 761 Log.d(TAG, "Could not find enterprise preference " + preferenceKey); 762 return; 763 } 764 765 preference.setTitle( 766 mDevicePolicyManager.getResources().getString(overrideKey, 767 () -> getString(resource))); 768 } 769 } 770