1 /*
2  * Copyright (C) 2013 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.example.android.apprestrictions;
18 
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.RestrictionEntry;
23 import android.os.Bundle;
24 import android.os.UserManager;
25 import android.preference.CheckBoxPreference;
26 import android.preference.ListPreference;
27 import android.preference.MultiSelectListPreference;
28 import android.preference.Preference;
29 import android.preference.PreferenceFragment;
30 
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.HashSet;
34 import java.util.List;
35 import java.util.Set;
36 
37 /**
38  * This fragment is included in {@code CustomRestrictionsActivity}.  It demonstrates how an app
39  * can integrate its own custom app restriction settings with the restricted profile feature.
40  *
41  * This sample app maintains custom app restriction settings in shared preferences.  Your app
42  * can use other methods to maintain the settings.  When this activity is invoked
43  * (from Settings > Users > Restricted Profile), the shared preferences are used to initialize
44  * the custom configuration on the user interface.
45  *
46  * Three sample input types are shown: checkbox, single-choice, and multi-choice.  When the
47  * settings are modified by the user, the corresponding restriction entries are saved in the
48  * platform.  The saved restriction entries are retrievable when the app is launched under a
49  * restricted profile.
50  */
51 public class CustomRestrictionsFragment extends PreferenceFragment
52         implements Preference.OnPreferenceChangeListener {
53 
54     // Shared preference key for the boolean restriction.
55     private static final String KEY_BOOLEAN_PREF = "pref_boolean";
56     // Shared preference key for the single-select restriction.
57     private static final String KEY_CHOICE_PREF = "pref_choice";
58     // Shared preference key for the multi-select restriction.
59     private static final String KEY_MULTI_PREF = "pref_multi";
60 
61 
62     private List<RestrictionEntry> mRestrictions;
63     private Bundle mRestrictionsBundle;
64 
65     // Shared preferences for each of the sample input types.
66     private CheckBoxPreference mBooleanPref;
67     private ListPreference mChoicePref;
68     private MultiSelectListPreference mMultiPref;
69 
70     // Restriction entries for each of the sample input types.
71     private RestrictionEntry mBooleanEntry;
72     private RestrictionEntry mChoiceEntry;
73     private RestrictionEntry mMultiEntry;
74 
75     @Override
onCreate(Bundle savedInstanceState)76     public void onCreate(Bundle savedInstanceState) {
77         super.onCreate(savedInstanceState);
78         addPreferencesFromResource(R.xml.custom_prefs);
79 
80         // This sample app uses shared preferences to maintain app restriction settings.  Your app
81         // can use other methods to maintain the settings.
82         mBooleanPref = (CheckBoxPreference) findPreference(KEY_BOOLEAN_PREF);
83         mChoicePref = (ListPreference) findPreference(KEY_CHOICE_PREF);
84         mMultiPref = (MultiSelectListPreference) findPreference(KEY_MULTI_PREF);
85 
86         mBooleanPref.setOnPreferenceChangeListener(this);
87         mChoicePref.setOnPreferenceChangeListener(this);
88         mMultiPref.setOnPreferenceChangeListener(this);
89 
90         setRetainInstance(true);
91     }
92 
93     @Override
onActivityCreated(Bundle savedInstanceState)94     public void onActivityCreated(Bundle savedInstanceState) {
95         super.onActivityCreated(savedInstanceState);
96         final Activity activity = getActivity();
97 
98         // BEGIN_INCLUDE (GET_CURRENT_RESTRICTIONS)
99         // Existing app restriction settings, if exist, can be retrieved from the Bundle.
100         mRestrictionsBundle =
101                 activity.getIntent().getBundleExtra(Intent.EXTRA_RESTRICTIONS_BUNDLE);
102 
103         if (mRestrictionsBundle == null) {
104             mRestrictionsBundle =
105                     ((UserManager) activity.getSystemService(Context.USER_SERVICE))
106                             .getApplicationRestrictions(activity.getPackageName());
107         }
108 
109         if (mRestrictionsBundle == null) {
110             mRestrictionsBundle = new Bundle();
111         }
112 
113         mRestrictions = activity.getIntent().getParcelableArrayListExtra(
114                 Intent.EXTRA_RESTRICTIONS_LIST);
115         // END_INCLUDE (GET_CURRENT_RESTRICTIONS)
116 
117         // Transfers the saved values into the preference hierarchy.
118         if (mRestrictions != null) {
119             for (RestrictionEntry entry : mRestrictions) {
120                 if (entry.getKey().equals(GetRestrictionsReceiver.KEY_BOOLEAN)) {
121                     mBooleanPref.setChecked(entry.getSelectedState());
122                     mBooleanEntry = entry;
123                 } else if (entry.getKey().equals(GetRestrictionsReceiver.KEY_CHOICE)) {
124                     mChoicePref.setValue(entry.getSelectedString());
125                     mChoiceEntry = entry;
126                 } else if (entry.getKey().equals(GetRestrictionsReceiver.KEY_MULTI_SELECT)) {
127                     HashSet<String> set = new HashSet<>();
128                     Collections.addAll(set, entry.getAllSelectedStrings());
129                     mMultiPref.setValues(set);
130                     mMultiEntry = entry;
131                 }
132             }
133         } else {
134             mRestrictions = new ArrayList<>();
135 
136             // Initializes the boolean restriction entry and updates its corresponding shared
137             // preference value.
138             mBooleanEntry = new RestrictionEntry(GetRestrictionsReceiver.KEY_BOOLEAN,
139                     mRestrictionsBundle.getBoolean(GetRestrictionsReceiver.KEY_BOOLEAN, false));
140             mBooleanEntry.setType(RestrictionEntry.TYPE_BOOLEAN);
141             mBooleanPref.setChecked(mBooleanEntry.getSelectedState());
142 
143             // Initializes the single choice restriction entry and updates its corresponding
144             // shared preference value.
145             mChoiceEntry = new RestrictionEntry(GetRestrictionsReceiver.KEY_CHOICE,
146                     mRestrictionsBundle.getString(GetRestrictionsReceiver.KEY_CHOICE));
147             mChoiceEntry.setType(RestrictionEntry.TYPE_CHOICE);
148             mChoicePref.setValue(mChoiceEntry.getSelectedString());
149 
150             // Initializes the multi-select restriction entry and updates its corresponding
151             // shared preference value.
152             mMultiEntry = new RestrictionEntry(GetRestrictionsReceiver.KEY_MULTI_SELECT,
153                     mRestrictionsBundle.getStringArray(
154                             GetRestrictionsReceiver.KEY_MULTI_SELECT));
155             mMultiEntry.setType(RestrictionEntry.TYPE_MULTI_SELECT);
156             if (mMultiEntry.getAllSelectedStrings() != null) {
157                 HashSet<String> set = new HashSet<>();
158                 final String[] values = mRestrictionsBundle.getStringArray(
159                         GetRestrictionsReceiver.KEY_MULTI_SELECT);
160                 if (values != null) {
161                     Collections.addAll(set, values);
162                 }
163                 mMultiPref.setValues(set);
164             }
165             mRestrictions.add(mBooleanEntry);
166             mRestrictions.add(mChoiceEntry);
167             mRestrictions.add(mMultiEntry);
168         }
169         // Prepares result to be passed back to the Settings app when the custom restrictions
170         // activity finishes.
171         Intent intent = new Intent(getActivity().getIntent());
172         intent.putParcelableArrayListExtra(Intent.EXTRA_RESTRICTIONS_LIST,
173                 new ArrayList<>(mRestrictions));
174         getActivity().setResult(Activity.RESULT_OK, intent);
175     }
176 
177     @Override
onPreferenceChange(Preference preference, Object newValue)178     public boolean onPreferenceChange(Preference preference, Object newValue) {
179         if (preference == mBooleanPref) {
180             mBooleanEntry.setSelectedState((Boolean) newValue);
181         } else if (preference == mChoicePref) {
182             mChoiceEntry.setSelectedString((String) newValue);
183         } else if (preference == mMultiPref && newValue instanceof Set) {
184             // newValue is a Set<String>, skip the lint warning.
185             //noinspection unchecked
186             String[] selectedStrings = new String[((Set<String>) newValue).size()];
187             int i = 0;
188             //noinspection unchecked
189             for (String value : (Set<String>) newValue) {
190                 selectedStrings[i++] = value;
191             }
192             mMultiEntry.setAllSelectedStrings(selectedStrings);
193         }
194 
195         // Saves all the app restriction configuration changes from the custom activity.
196         Intent intent = new Intent(getActivity().getIntent());
197         intent.putParcelableArrayListExtra(Intent.EXTRA_RESTRICTIONS_LIST,
198                 new ArrayList<>(mRestrictions));
199         getActivity().setResult(Activity.RESULT_OK, intent);
200         return true;
201     }
202 }
203