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 } 483 super.onDetach(); 484 } 485 486 // Dialog management 487 showDialog(int dialogId)488 protected void showDialog(int dialogId) { 489 if (mDialogFragment != null) { 490 Log.e(TAG, "Old dialog fragment not null!"); 491 } 492 mDialogFragment = SettingsDialogFragment.newInstance(this, dialogId); 493 mDialogFragment.show(getChildFragmentManager(), Integer.toString(dialogId)); 494 } 495 496 @Override onCreateDialog(int dialogId)497 public Dialog onCreateDialog(int dialogId) { 498 return null; 499 } 500 501 @Override getDialogMetricsCategory(int dialogId)502 public int getDialogMetricsCategory(int dialogId) { 503 return 0; 504 } 505 removeDialog(int dialogId)506 protected void removeDialog(int dialogId) { 507 // mDialogFragment may not be visible yet in parent fragment's onResume(). 508 // To be able to dismiss dialog at that time, don't check 509 // mDialogFragment.isVisible(). 510 if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId) { 511 mDialogFragment.dismissAllowingStateLoss(); 512 } 513 mDialogFragment = null; 514 } 515 516 /** 517 * Sets the OnCancelListener of the dialog shown. This method can only be 518 * called after showDialog(int) and before removeDialog(int). The method 519 * does nothing otherwise. 520 */ setOnCancelListener(DialogInterface.OnCancelListener listener)521 protected void setOnCancelListener(DialogInterface.OnCancelListener listener) { 522 if (mDialogFragment != null) { 523 mDialogFragment.mOnCancelListener = listener; 524 } 525 } 526 527 /** 528 * Sets the OnDismissListener of the dialog shown. This method can only be 529 * called after showDialog(int) and before removeDialog(int). The method 530 * does nothing otherwise. 531 */ setOnDismissListener(DialogInterface.OnDismissListener listener)532 protected void setOnDismissListener(DialogInterface.OnDismissListener listener) { 533 if (mDialogFragment != null) { 534 mDialogFragment.mOnDismissListener = listener; 535 } 536 } 537 onDialogShowing()538 public void onDialogShowing() { 539 // override in subclass to attach a dismiss listener, for instance 540 } 541 542 @Override onDisplayPreferenceDialog(Preference preference)543 public void onDisplayPreferenceDialog(Preference preference) { 544 if (preference.getKey() == null) { 545 // Auto-key preferences that don't have a key, so the dialog can find them. 546 preference.setKey(UUID.randomUUID().toString()); 547 } 548 DialogFragment f = null; 549 if (preference instanceof RestrictedListPreference) { 550 f = RestrictedListPreference.RestrictedListPreferenceDialogFragment 551 .newInstance(preference.getKey()); 552 } else if (preference instanceof CustomListPreference) { 553 f = CustomListPreference.CustomListPreferenceDialogFragment 554 .newInstance(preference.getKey()); 555 } else if (preference instanceof CustomDialogPreferenceCompat) { 556 f = CustomDialogPreferenceCompat.CustomPreferenceDialogFragment 557 .newInstance(preference.getKey()); 558 } else if (preference instanceof CustomEditTextPreferenceCompat) { 559 f = CustomEditTextPreferenceCompat.CustomPreferenceDialogFragment 560 .newInstance(preference.getKey()); 561 } else { 562 super.onDisplayPreferenceDialog(preference); 563 return; 564 } 565 f.setTargetFragment(this, 0); 566 f.show(getFragmentManager(), "dialog_preference"); 567 onDialogShowing(); 568 } 569 570 public static class SettingsDialogFragment extends InstrumentedDialogFragment { 571 private static final String KEY_DIALOG_ID = "key_dialog_id"; 572 private static final String KEY_PARENT_FRAGMENT_ID = "key_parent_fragment_id"; 573 574 private Fragment mParentFragment; 575 576 private DialogInterface.OnCancelListener mOnCancelListener; 577 private DialogInterface.OnDismissListener mOnDismissListener; 578 newInstance(DialogCreatable fragment, int dialogId)579 public static SettingsDialogFragment newInstance(DialogCreatable fragment, int dialogId) { 580 if (!(fragment instanceof Fragment)) { 581 throw new IllegalArgumentException("fragment argument must be an instance of " 582 + Fragment.class.getName()); 583 } 584 585 final SettingsDialogFragment settingsDialogFragment = new SettingsDialogFragment(); 586 settingsDialogFragment.setParentFragment(fragment); 587 settingsDialogFragment.setDialogId(dialogId); 588 589 return settingsDialogFragment; 590 } 591 592 @Override getMetricsCategory()593 public int getMetricsCategory() { 594 if (mParentFragment == null) { 595 return Instrumentable.METRICS_CATEGORY_UNKNOWN; 596 } 597 final int metricsCategory = 598 ((DialogCreatable) mParentFragment).getDialogMetricsCategory(mDialogId); 599 if (metricsCategory <= 0) { 600 throw new IllegalStateException("Dialog must provide a metrics category"); 601 } 602 return metricsCategory; 603 } 604 605 @Override onSaveInstanceState(Bundle outState)606 public void onSaveInstanceState(Bundle outState) { 607 super.onSaveInstanceState(outState); 608 if (mParentFragment != null) { 609 outState.putInt(KEY_DIALOG_ID, mDialogId); 610 outState.putInt(KEY_PARENT_FRAGMENT_ID, mParentFragment.getId()); 611 } 612 } 613 614 @Override onStart()615 public void onStart() { 616 super.onStart(); 617 618 if (mParentFragment != null && mParentFragment instanceof SettingsPreferenceFragment) { 619 ((SettingsPreferenceFragment) mParentFragment).onDialogShowing(); 620 } 621 } 622 623 @Override onCreateDialog(Bundle savedInstanceState)624 public Dialog onCreateDialog(Bundle savedInstanceState) { 625 if (savedInstanceState != null) { 626 mDialogId = savedInstanceState.getInt(KEY_DIALOG_ID, 0); 627 mParentFragment = getParentFragment(); 628 int mParentFragmentId = savedInstanceState.getInt(KEY_PARENT_FRAGMENT_ID, -1); 629 if (mParentFragment == null) { 630 mParentFragment = getFragmentManager().findFragmentById(mParentFragmentId); 631 } 632 if (!(mParentFragment instanceof DialogCreatable)) { 633 throw new IllegalArgumentException( 634 (mParentFragment != null 635 ? mParentFragment.getClass().getName() 636 : mParentFragmentId) 637 + " must implement " 638 + DialogCreatable.class.getName()); 639 } 640 // This dialog fragment could be created from non-SettingsPreferenceFragment 641 if (mParentFragment instanceof SettingsPreferenceFragment) { 642 // restore mDialogFragment in mParentFragment 643 ((SettingsPreferenceFragment) mParentFragment).mDialogFragment = this; 644 } 645 } 646 return ((DialogCreatable) mParentFragment).onCreateDialog(mDialogId); 647 } 648 649 @Override onCancel(DialogInterface dialog)650 public void onCancel(DialogInterface dialog) { 651 super.onCancel(dialog); 652 if (mOnCancelListener != null) { 653 mOnCancelListener.onCancel(dialog); 654 } 655 } 656 657 @Override onDismiss(DialogInterface dialog)658 public void onDismiss(DialogInterface dialog) { 659 super.onDismiss(dialog); 660 if (mOnDismissListener != null) { 661 mOnDismissListener.onDismiss(dialog); 662 } 663 } 664 getDialogId()665 public int getDialogId() { 666 return mDialogId; 667 } 668 669 @Override onDetach()670 public void onDetach() { 671 super.onDetach(); 672 673 // This dialog fragment could be created from non-SettingsPreferenceFragment 674 if (mParentFragment instanceof SettingsPreferenceFragment) { 675 // in case the dialog is not explicitly removed by removeDialog() 676 if (((SettingsPreferenceFragment) mParentFragment).mDialogFragment == this) { 677 ((SettingsPreferenceFragment) mParentFragment).mDialogFragment = null; 678 } 679 } 680 } 681 setParentFragment(DialogCreatable fragment)682 private void setParentFragment(DialogCreatable fragment) { 683 mParentFragment = (Fragment) fragment; 684 } 685 setDialogId(int dialogId)686 private void setDialogId(int dialogId) { 687 mDialogId = dialogId; 688 } 689 } 690 hasNextButton()691 protected boolean hasNextButton() { 692 return ((ButtonBarHandler) getActivity()).hasNextButton(); 693 } 694 getNextButton()695 protected Button getNextButton() { 696 return ((ButtonBarHandler) getActivity()).getNextButton(); 697 } 698 finish()699 public void finish() { 700 Activity activity = getActivity(); 701 if (activity == null) return; 702 if (getFragmentManager().getBackStackEntryCount() > 0) { 703 getFragmentManager().popBackStack(); 704 } else { 705 activity.finish(); 706 } 707 } 708 getIntent()709 protected Intent getIntent() { 710 if (getActivity() == null) { 711 return null; 712 } 713 return getActivity().getIntent(); 714 } 715 setResult(int result, Intent intent)716 protected void setResult(int result, Intent intent) { 717 if (getActivity() == null) { 718 return; 719 } 720 getActivity().setResult(result, intent); 721 } 722 setResult(int result)723 protected void setResult(int result) { 724 if (getActivity() == null) { 725 return; 726 } 727 getActivity().setResult(result); 728 } 729 isFinishingOrDestroyed()730 protected boolean isFinishingOrDestroyed() { 731 final Activity activity = getActivity(); 732 return activity == null || activity.isFinishing() || activity.isDestroyed(); 733 } 734 replaceEnterprisePreferenceScreenTitle(String overrideKey, int resource)735 protected void replaceEnterprisePreferenceScreenTitle(String overrideKey, int resource) { 736 getActivity().setTitle(mDevicePolicyManager.getResources().getString( 737 overrideKey, () -> getString(resource))); 738 } 739 replaceEnterpriseStringSummary( String preferenceKey, String overrideKey, int resource)740 protected void replaceEnterpriseStringSummary( 741 String preferenceKey, String overrideKey, int resource) { 742 Preference preference = findPreference(preferenceKey); 743 if (preference == null) { 744 Log.d(TAG, "Could not find enterprise preference " + preferenceKey); 745 return; 746 } 747 748 preference.setSummary( 749 mDevicePolicyManager.getResources().getString(overrideKey, 750 () -> getString(resource))); 751 } 752 replaceEnterpriseStringTitle( String preferenceKey, String overrideKey, int resource)753 protected void replaceEnterpriseStringTitle( 754 String preferenceKey, String overrideKey, int resource) { 755 Preference preference = findPreference(preferenceKey); 756 if (preference == null) { 757 Log.d(TAG, "Could not find enterprise preference " + preferenceKey); 758 return; 759 } 760 761 preference.setTitle( 762 mDevicePolicyManager.getResources().getString(overrideKey, 763 () -> getString(resource))); 764 } 765 } 766