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