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.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.RestrictionEntry;
24 import android.content.res.Resources;
25 import android.os.Bundle;
26 import android.preference.PreferenceManager;
27 import android.util.Log;
28 
29 import java.util.ArrayList;
30 
31 public class GetRestrictionsReceiver extends BroadcastReceiver {
32     private static final String TAG = GetRestrictionsReceiver.class.getSimpleName();
33 
34     // Keys for referencing app restriction settings from the platform.
35     public static final String KEY_BOOLEAN = "boolean_key";
36     public static final String KEY_CHOICE = "choice_key";
37     public static final String KEY_MULTI_SELECT = "multi_key";
38 
39     @Override
onReceive(final Context context, Intent intent)40     public void onReceive(final Context context, Intent intent) {
41         final PendingResult result = goAsync();
42 
43         // If app restriction settings are already created, they will be included in the Bundle
44         // as key/value pairs.
45         final Bundle existingRestrictions =
46                 intent.getBundleExtra(Intent.EXTRA_RESTRICTIONS_BUNDLE);
47         Log.i(TAG, "existingRestrictions = " + existingRestrictions);
48 
49         new Thread() {
50             public void run() {
51                 createRestrictions(context, result, existingRestrictions);
52             }
53         }.start();
54     }
55 
56     // Initializes a boolean type restriction entry.
populateBooleanEntry(Resources res, RestrictionEntry entry)57     public static void populateBooleanEntry(Resources res, RestrictionEntry entry) {
58         entry.setType(RestrictionEntry.TYPE_BOOLEAN);
59         entry.setTitle(res.getString(R.string.boolean_entry_title));
60     }
61 
62     // Initializes a single choice type restriction entry.
populateChoiceEntry(Resources res, RestrictionEntry reSingleChoice)63     public static void populateChoiceEntry(Resources res, RestrictionEntry reSingleChoice) {
64         String[] choiceEntries = res.getStringArray(R.array.choice_entry_entries);
65         String[] choiceValues = res.getStringArray(R.array.choice_entry_values);
66         if (reSingleChoice.getSelectedString() == null) {
67             reSingleChoice.setSelectedString(choiceValues[0]);
68         }
69         reSingleChoice.setTitle(res.getString(R.string.choice_entry_title));
70         reSingleChoice.setChoiceEntries(choiceEntries);
71         reSingleChoice.setChoiceValues(choiceValues);
72         reSingleChoice.setType(RestrictionEntry.TYPE_CHOICE);
73     }
74 
75     // Initializes a multi-select type restriction entry.
populateMultiEntry(Resources res, RestrictionEntry reMultiSelect)76     public static void populateMultiEntry(Resources res, RestrictionEntry reMultiSelect) {
77         String[] multiEntries = res.getStringArray(R.array.multi_entry_entries);
78         String[] multiValues = res.getStringArray(R.array.multi_entry_values);
79         if (reMultiSelect.getAllSelectedStrings() == null) {
80             reMultiSelect.setAllSelectedStrings(new String[0]);
81         }
82         reMultiSelect.setTitle(res.getString(R.string.multi_entry_title));
83         reMultiSelect.setChoiceEntries(multiEntries);
84         reMultiSelect.setChoiceValues(multiValues);
85         reMultiSelect.setType(RestrictionEntry.TYPE_MULTI_SELECT);
86     }
87 
88     // Demonstrates the creation of standard app restriction types: boolean, single choice, and
89     // multi-select.
initRestrictions(Context context)90     private ArrayList<RestrictionEntry> initRestrictions(Context context) {
91         ArrayList<RestrictionEntry> newRestrictions = new ArrayList<>();
92         Resources res = context.getResources();
93 
94         RestrictionEntry reBoolean = new RestrictionEntry(KEY_BOOLEAN, false);
95         populateBooleanEntry(res, reBoolean);
96         newRestrictions.add(reBoolean);
97 
98         RestrictionEntry reSingleChoice = new RestrictionEntry(KEY_CHOICE, (String) null);
99         populateChoiceEntry(res, reSingleChoice);
100         newRestrictions.add(reSingleChoice);
101 
102         RestrictionEntry reMultiSelect = new RestrictionEntry(KEY_MULTI_SELECT, (String[]) null);
103         populateMultiEntry(res, reMultiSelect);
104         newRestrictions.add(reMultiSelect);
105 
106         return newRestrictions;
107     }
108 
createRestrictions(Context context, PendingResult result, Bundle existingRestrictions)109     private void createRestrictions(Context context, PendingResult result,
110                                     Bundle existingRestrictions) {
111         // The incoming restrictions bundle contains key/value pairs representing existing app
112         // restrictions for this package. In order to retain existing app restrictions, you need to
113         // construct new restriction entries and then copy in any existing values for the new keys.
114         ArrayList<RestrictionEntry> newEntries = initRestrictions(context);
115 
116         // If app restrictions were not previously configured for the package, create the default
117         // restrictions entries and return them.
118         if (existingRestrictions == null) {
119             Bundle extras = new Bundle();
120             extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST, newEntries);
121             result.setResult(Activity.RESULT_OK, null, extras);
122             result.finish();
123             return;
124         }
125 
126         // Retains current restriction settings by transferring existing restriction entries to
127         // new ones.
128         for (RestrictionEntry entry : newEntries) {
129             final String key = entry.getKey();
130             if (KEY_BOOLEAN.equals(key)) {
131                 entry.setSelectedState(existingRestrictions.getBoolean(KEY_BOOLEAN));
132             } else if (KEY_CHOICE.equals(key)) {
133                 if (existingRestrictions.containsKey(KEY_CHOICE)) {
134                     entry.setSelectedString(existingRestrictions.getString(KEY_CHOICE));
135                 }
136             } else if (KEY_MULTI_SELECT.equals(key)) {
137                 if (existingRestrictions.containsKey(KEY_MULTI_SELECT)) {
138                     entry.setAllSelectedStrings(existingRestrictions.getStringArray(key));
139                 }
140             }
141         }
142 
143         final Bundle extras = new Bundle();
144 
145         // This path demonstrates the use of a custom app restriction activity instead of standard
146         // types.  When a custom activity is set, the standard types will not be available under
147         // app restriction settings.
148         //
149         // If your app has an existing activity for app restriction configuration, you can set it
150         // up with the intent here.
151         if (PreferenceManager.getDefaultSharedPreferences(context)
152                 .getBoolean(MainActivity.CUSTOM_CONFIG_KEY, false)) {
153             final Intent customIntent = new Intent();
154             customIntent.setClass(context, CustomRestrictionsActivity.class);
155             extras.putParcelable(Intent.EXTRA_RESTRICTIONS_INTENT, customIntent);
156         }
157 
158         extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST, newEntries);
159         result.setResult(Activity.RESULT_OK, null, extras);
160         result.finish();
161     }
162 }
163