1 /*
2  * Copyright (C) 2015 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.tv.settings;
18 
19 import android.content.ContentProviderClient;
20 import android.net.Uri;
21 import android.os.Bundle;
22 
23 import androidx.annotation.NonNull;
24 import androidx.fragment.app.Fragment;
25 import androidx.fragment.app.FragmentManager;
26 import androidx.leanback.preference.LeanbackSettingsFragmentCompat;
27 import androidx.preference.Preference;
28 import androidx.preference.PreferenceDialogFragmentCompat;
29 import androidx.preference.PreferenceFragmentCompat;
30 import androidx.preference.PreferenceScreen;
31 
32 import com.android.tv.settings.system.LeanbackPickerDialogFragment;
33 import com.android.tv.settings.system.LeanbackPickerDialogPreference;
34 import com.android.tv.twopanelsettings.slices.SliceFragment;
35 import com.android.tv.twopanelsettings.slices.SlicePreference;
36 import com.android.tv.twopanelsettings.slices.SlicesConstants;
37 
38 /**
39  * Base class for settings fragments. Handles launching fragments and dialogs in a reasonably
40  * generic way. Subclasses should only override onPreferenceStartInitialScreen.
41  */
42 
43 public abstract class BaseSettingsFragment extends LeanbackSettingsFragmentCompat implements
44         SliceFragment.OnePanelSliceFragmentContainer {
45     @Override
onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref)46     public final boolean onPreferenceStartFragment(PreferenceFragmentCompat caller,
47             Preference pref) {
48         if (pref.getFragment() != null) {
49             if (pref instanceof SlicePreference) {
50                 SlicePreference slicePref = (SlicePreference) pref;
51                 if (slicePref.getUri() == null || !isUriValid(slicePref.getUri())) {
52                     return false;
53                 }
54                 Bundle b = pref.getExtras();
55                 b.putString(SlicesConstants.TAG_TARGET_URI, slicePref.getUri());
56                 b.putCharSequence(SlicesConstants.TAG_SCREEN_TITLE, slicePref.getTitle());
57             }
58         }
59         final Fragment f =
60                 Fragment.instantiate(getActivity(), pref.getFragment(), pref.getExtras());
61         f.setTargetFragment(caller, 0);
62         if (f instanceof PreferenceFragmentCompat || f instanceof PreferenceDialogFragmentCompat) {
63             startPreferenceFragment(f);
64         } else {
65             startImmersiveFragment(f);
66         }
67         return true;
68     }
69 
isUriValid(String uri)70     private boolean isUriValid(String uri) {
71         if (uri == null) {
72             return false;
73         }
74         ContentProviderClient client =
75                 getContext().getContentResolver().acquireContentProviderClient(Uri.parse(uri));
76         if (client != null) {
77             client.close();
78             return true;
79         } else {
80             return false;
81         }
82     }
83 
84     @Override
onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref)85     public final boolean onPreferenceStartScreen(PreferenceFragmentCompat caller,
86             PreferenceScreen pref) {
87         return false;
88     }
89 
90     /** Navigate back to the previous fragment **/
navigateBack()91     public void navigateBack() {
92         FragmentManager fragmentManager = getChildFragmentManager();
93         if (fragmentManager.getBackStackEntryCount() > 0) {
94             fragmentManager.popBackStack();
95         }
96     }
97 
98     @Override
onPreferenceDisplayDialog(@onNull PreferenceFragmentCompat caller, Preference pref)99     public boolean onPreferenceDisplayDialog(@NonNull PreferenceFragmentCompat caller,
100             Preference pref) {
101         final Fragment f;
102         if (pref instanceof LeanbackPickerDialogPreference) {
103             final LeanbackPickerDialogPreference dialogPreference = (LeanbackPickerDialogPreference)
104                     pref;
105             f = dialogPreference.getType().equals("date")
106                     ? LeanbackPickerDialogFragment.newDatePickerInstance(pref.getKey())
107                     : LeanbackPickerDialogFragment.newTimePickerInstance(pref.getKey());
108             f.setTargetFragment(caller, 0);
109             startPreferenceFragment(f);
110             return true;
111         } else {
112             return super.onPreferenceDisplayDialog(caller, pref);
113         }
114     }
115 }
116