diff --git a/AppRestrictions/AppRestrictions.csproj b/AppRestrictions/AppRestrictions.csproj new file mode 100644 index 000000000..420afc152 --- /dev/null +++ b/AppRestrictions/AppRestrictions.csproj @@ -0,0 +1,77 @@ + + + + Debug + AnyCPU + 10.0.0 + 2.0 + {6762E9D8-DDEC-4D81-BF13-6549BA8C588D} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + AppRestrictions + True + Resources\Resource.designer.cs + Resource + Resources + Assets + False + AppRestrictions + v4.3 + Properties\AndroidManifest.xml + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + None + false + True + + + full + true + bin\Release + prompt + 4 + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AppRestrictions/AppRestrictions.sln b/AppRestrictions/AppRestrictions.sln new file mode 100644 index 000000000..65787c89d --- /dev/null +++ b/AppRestrictions/AppRestrictions.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppRestrictions", "AppRestrictions.csproj", "{6762E9D8-DDEC-4D81-BF13-6549BA8C588D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6762E9D8-DDEC-4D81-BF13-6549BA8C588D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6762E9D8-DDEC-4D81-BF13-6549BA8C588D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6762E9D8-DDEC-4D81-BF13-6549BA8C588D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6762E9D8-DDEC-4D81-BF13-6549BA8C588D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = AppRestrictions.csproj + EndGlobalSection +EndGlobal diff --git a/AppRestrictions/CustomRestrictionsActivity.cs b/AppRestrictions/CustomRestrictionsActivity.cs new file mode 100644 index 000000000..bfd9dec9f --- /dev/null +++ b/AppRestrictions/CustomRestrictionsActivity.cs @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Android.App; +using Android.Content; +using Android.OS; +using Android.Runtime; +using Android.Views; +using Android.Widget; + +namespace AppRestrictions +{ + /** + * This activity demonstrates how an app can integrate its own custom app restriction settings + * with the restricted profile feature. + * + * This sample app maintains custom app restriction settings in shared preferences. When + * the activity is invoked (from Settings > Users), the stored settings are used to initialize + * the custom configuration on the user interface. Three sample input types are + * shown: checkbox, single-choice, and multi-choice. When the settings are modified by the user, + * the corresponding restriction entries are saved, which are retrievable under a restricted + * profile. + */ + [Activity (Label = "CustomRestrictionsActivity")] + public class CustomRestrictionsActivity : Activity + { + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + if (bundle == null) { + FragmentManager.BeginTransaction () + .Replace (Android.Resource.Id.Content, new CustomRestrictionsFragment ()).Commit (); + } + } + } +} + diff --git a/AppRestrictions/CustomRestrictionsFragment.cs b/AppRestrictions/CustomRestrictionsFragment.cs new file mode 100644 index 000000000..56c194d15 --- /dev/null +++ b/AppRestrictions/CustomRestrictionsFragment.cs @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Android.App; +using Android.Content; +using Android.OS; +using Android.Runtime; +using Android.Util; +using Android.Views; +using Android.Widget; +using Android.Preferences; + +namespace AppRestrictions +{ + /** + * This fragment is included in {@code CustomRestrictionsActivity}. It demonstrates how an app + * can integrate its own custom app restriction settings with the restricted profile feature. + * + * This sample app maintains custom app restriction settings in shared preferences. Your app + * can use other methods to maintain the settings. When this activity is invoked + * (from Settings > Users > Restricted Profile), the shared preferences are used to initialize + * the custom configuration on the user interface. + * + * Three sample input types are shown: checkbox, single-choice, and multi-choice. When the + * settings are modified by the user, the corresponding restriction entries are saved in the + * platform. The saved restriction entries are retrievable when the app is launched under a + * restricted profile. + */ + public class CustomRestrictionsFragment : PreferenceFragment + { + // Shared preference key for the boolean restriction. + private static readonly String KEY_BOOLEAN_PREF = "pref_boolean"; + // Shared preference key for the single-select restriction. + private static readonly String KEY_CHOICE_PREF = "pref_choice"; + // Shared preference key for the multi-select restriction. + private static readonly String KEY_MULTI_PREF = "pref_multi"; + + private List mRestrictions; + private Bundle mRestrictionsBundle; + + // Shared preferences for each of the sample input types. + private CheckBoxPreference mBooleanPref; + private ListPreference mChoicePref; + private MultiSelectListPreference mMultiPref; + + // Restriction entries for each of the sample input types. + private RestrictionEntry mBooleanEntry; + private RestrictionEntry mChoiceEntry; + private RestrictionEntry mMultiEntry; + + public override void OnCreate (Bundle savedInstanceState) + { + base.OnCreate (savedInstanceState); + + AddPreferencesFromResource (Resource.Xml.custom_prefs); + + // This sample app uses shared preferences to maintain app restriction settings. Your app + // can use other methods to maintain the settings. + mBooleanPref = FindPreference (KEY_BOOLEAN_PREF) as CheckBoxPreference; + mChoicePref = FindPreference (KEY_CHOICE_PREF) as ListPreference; + mMultiPref = FindPreference (KEY_MULTI_PREF) as MultiSelectListPreference; + + mBooleanPref.PreferenceChange += OnPreferenceChange; + mChoicePref.PreferenceChange += OnPreferenceChange; + mMultiPref.PreferenceChange += OnPreferenceChange; + + RetainInstance = true; + } + + public override void OnActivityCreated (Bundle savedInstanceState) + { + base.OnActivityCreated (savedInstanceState); + Activity act = Activity; + + /* BEGIN_INCLUDE (GET_CURRENT_RESTRICTIONS) */ + // Existing app restriction settings, if exist, can be retrieved from the Bundle. + mRestrictionsBundle = act.Intent.GetBundleExtra (Intent.ExtraRestrictionsBundle); + + if (mRestrictionsBundle == null) { + mRestrictionsBundle = ((UserManager) act.GetSystemService (Context.UserService)) + .GetApplicationRestrictions (Activity.PackageName); + } + + if (mRestrictionsBundle == null) { + mRestrictionsBundle = new Bundle (); + } + + mRestrictions = (List) act.Intent.GetParcelableArrayListExtra (Intent.ExtraRestrictionsList); + /* END_INCLUDE (GET_CURRENT_RESTRICTIONS) */ + + // Transfers the saved values into the preference hierarchy. + if (mRestrictions != null) { + foreach (RestrictionEntry entry in mRestrictions) { + if (entry.Key.Equals (GetRestrictionsReceiver.KEY_BOOLEAN)) { + mBooleanPref.Checked = entry.SelectedState; + mBooleanEntry = entry; + + } else if (entry.Key.Equals (GetRestrictionsReceiver.KEY_CHOICE)) { + mChoicePref.Value = entry.SelectedString; + mChoiceEntry = entry; + + } else if (entry.Key.Equals (GetRestrictionsReceiver.KEY_MULTI_SELECT)) { + List list = new List (); + foreach (String value in entry.GetAllSelectedStrings ()) { + list.Add (value); + } + mMultiPref.Values = list; + mMultiEntry = entry; + } + } + } else { + mRestrictions = new List (); + + // Initializes the boolean restriction entry and updates its corresponding shared + // preference value. + mBooleanEntry = new RestrictionEntry (GetRestrictionsReceiver.KEY_BOOLEAN, + mRestrictionsBundle.GetBoolean (GetRestrictionsReceiver.KEY_BOOLEAN, false)); + mBooleanEntry.Type = RestrictionEntryType.Boolean; + mBooleanPref.Checked = mBooleanEntry.SelectedState; + + // Initializes the single choice restriction entry and updates its corresponding + // shared preference value. + mChoiceEntry = new RestrictionEntry (GetRestrictionsReceiver.KEY_CHOICE, + mRestrictionsBundle.GetString (GetRestrictionsReceiver.KEY_CHOICE)); + mChoiceEntry.Type = RestrictionEntryType.Choice; + mChoicePref.Value = mChoiceEntry.SelectedString; + + // Initializes the multi-select restriction entry and updates its corresponding + // shared preference value. + mMultiEntry = new RestrictionEntry (GetRestrictionsReceiver.KEY_MULTI_SELECT, + mRestrictionsBundle.GetStringArray (GetRestrictionsReceiver.KEY_MULTI_SELECT)); + mMultiEntry.Type = RestrictionEntryType.MultiSelect; + + if (mMultiEntry.GetAllSelectedStrings() != null) { + List hset = new List (); + String[] values = mRestrictionsBundle.GetStringArray (GetRestrictionsReceiver.KEY_MULTI_SELECT); + + if (values != null) { + foreach (String value in values) { + hset.Add (value); + } + } + mMultiPref.Values = hset; + } + mRestrictions.Add (mBooleanEntry); + mRestrictions.Add (mChoiceEntry); + mRestrictions.Add (mMultiEntry); + } + // Prepares result to be passed back to the Settings app when the custom restrictions + // activity finishes. + Intent intent = new Intent (Activity.Intent); + intent.PutParcelableArrayListExtra (Intent.ExtraRestrictionsList, new List (mRestrictions)); + Activity.SetResult (Result.Ok, intent); + } + + public void OnPreferenceChange (object sender, Preference.PreferenceChangeEventArgs e) + { + if (e.Preference == mBooleanPref) { + mBooleanEntry.SelectedState = (bool) e.NewValue; + + } else if (e.Preference == mChoicePref) { + mChoiceEntry.SelectedString = (string) e.NewValue; + + } else if (e.Preference == mMultiPref) { + String[] selectedStrings = new String [((IList ) e.NewValue).Count]; + int i = 0; + foreach (String value in (IList) e.NewValue) { + selectedStrings[i++] = value; + } + mMultiEntry.SetAllSelectedStrings (selectedStrings); + } + + // Saves all the app restriction configuration changes from the custom activity. + Intent intent = new Intent (Activity.Intent); + intent.PutParcelableArrayListExtra (Intent.ExtraRestrictionsList, new List (mRestrictions)); + Activity.SetResult (Result.Ok, intent); + } + } +} + diff --git a/AppRestrictions/GetRestrictionsReceiver.cs b/AppRestrictions/GetRestrictionsReceiver.cs new file mode 100644 index 000000000..bead4c6fb --- /dev/null +++ b/AppRestrictions/GetRestrictionsReceiver.cs @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Linq; +using System.Text; +using System.Threading; + +using Android.App; +using Android.Content; +using Android.OS; +using Android.Runtime; +using Android.Views; +using Android.Widget; +using Android.Util; +using Android.Content.Res; +using Android.Preferences; +using System.Collections; +using System.Collections.Generic; + +namespace AppRestrictions +{ + [BroadcastReceiver (Name = "com.xamarin.apprestrictions.GetRestrictionsReciever")] + [IntentFilter (new[] {Intent.ActionGetRestrictionEntries})] + public class GetRestrictionsReceiver : BroadcastReceiver + { + static readonly String TAG = typeof (GetRestrictionsReceiver).Name; + + // Keys for referencing app restriction settings from the platform. + public static readonly String KEY_BOOLEAN = "boolean_key"; + public static readonly String KEY_CHOICE = "choice_key"; + public static readonly String KEY_MULTI_SELECT = "multi_key"; + + public override void OnReceive (Context context, Intent intent) + { + PendingResult result = GoAsync (); + + // If app restriction settings are already created, they will be included in the Bundle + // as key/value pairs. + Bundle existingRestrictions = intent.GetBundleExtra (Intent.ExtraRestrictionsBundle); + Log.Info (TAG, "existingRestrictions = " + existingRestrictions); + + Thread thread = new Thread (new ThreadStart (delegate { + CreateRestrictions (context, result, existingRestrictions); + })); + + thread.Start (); + } + + // Initializes a boolean type restriction entry. + public static void PopulateBooleanEntry (Resources res, RestrictionEntry entry) + { + entry.Type = RestrictionEntryType.Boolean; + entry.Title = res.GetString (Resource.String.boolean_entry_title); + } + + // Initializes a single choice type restriction entry. + public static void PopulateChoiceEntry (Resources res, RestrictionEntry reSingleChoice) + { + String[] choiceEntries = res.GetStringArray (Resource.Array.choice_entry_entries); + String[] choiceValues = res.GetStringArray (Resource.Array.choice_entry_values); + + if (reSingleChoice.SelectedString == null) + reSingleChoice.SelectedString = choiceValues [0]; + + reSingleChoice.Title = res.GetString (Resource.String.choice_entry_title); + reSingleChoice.SetChoiceEntries (choiceEntries); + reSingleChoice.SetChoiceValues (choiceValues); + reSingleChoice.Type = RestrictionEntryType.Choice; + } + + // Initializes a multi-select type restriction entry. + public static void PopulateMultiEntry (Resources res, RestrictionEntry reMultiSelect) + { + String[] multiEntries = res.GetStringArray (Resource.Array.multi_entry_entries); + String[] multiValues = res.GetStringArray (Resource.Array.multi_entry_values); + + if (reMultiSelect.GetAllSelectedStrings() == null) + reMultiSelect.SetAllSelectedStrings (new String[0]); + + reMultiSelect.Title = res.GetString (Resource.String.multi_entry_title); + reMultiSelect.SetChoiceEntries (multiEntries); + reMultiSelect.SetChoiceValues (multiValues); + reMultiSelect.Type = RestrictionEntryType.MultiSelect; + } + + // Demonstrates the creation of standard app restriction types: boolean, single choice, and + // multi-select. + List InitRestrictions (Context context) + { + List newRestrictions = new List (); + Resources res = context.Resources; + + RestrictionEntry reBoolean = new RestrictionEntry (KEY_BOOLEAN, false); + PopulateBooleanEntry (res, reBoolean); + newRestrictions.Add (reBoolean); + + RestrictionEntry reSingleChoice = new RestrictionEntry (KEY_CHOICE, (String) null); + PopulateChoiceEntry (res, reSingleChoice); + newRestrictions.Add (reSingleChoice); + + RestrictionEntry reMultiSelect = new RestrictionEntry (KEY_MULTI_SELECT, (String[]) null); + PopulateMultiEntry (res, reMultiSelect); + newRestrictions.Add (reMultiSelect); + + return newRestrictions; + } + + private void CreateRestrictions (Context context, PendingResult result, Bundle existingRestrictions) + { + // The incoming restrictions bundle contains key/value pairs representing existing app + // restrictions for this package. In order to retain existing app restrictions, you need to + // construct new restriction entries and then copy in any existing values for the new keys. + List newEntries = InitRestrictions (context); + + // If app restrictions were not previously configured for the package, create the default + // restrictions entries and return them. + if (existingRestrictions == null) { + var extras = new Bundle (); + extras.PutParcelableArrayList (Intent.ExtraRestrictionsList, newEntries); + result.SetResult (Result.Ok, null, extras); + result.Finish (); + return; + } + + // Retains current restriction settings by transferring existing restriction entries to + // new ones. + foreach (RestrictionEntry entry in newEntries) { + String key = entry.Key; + + if (KEY_BOOLEAN.Equals (key)) { + entry.SelectedState = existingRestrictions.GetBoolean (KEY_BOOLEAN); + + } else if (KEY_CHOICE.Equals (key)) { + if (existingRestrictions.ContainsKey (KEY_CHOICE)) { + entry.SelectedString = existingRestrictions.GetString (KEY_CHOICE); + } + + } else if (KEY_MULTI_SELECT.Equals (key)) { + if (existingRestrictions.ContainsKey (KEY_MULTI_SELECT)) { + entry.SetAllSelectedStrings(existingRestrictions.GetStringArray (key)); + } + } + } + + var extra = new Bundle(); + + // This path demonstrates the use of a custom app restriction activity instead of standard + // types. When a custom activity is set, the standard types will not be available under + // app restriction settings. + // + // If your app has an existing activity for app restriction configuration, you can set it + // up with the intent here. + if (PreferenceManager.GetDefaultSharedPreferences (context) + .GetBoolean (MainActivity.CUSTOM_CONFIG_KEY, false)) { + var customIntent = new Intent(); + customIntent.SetClass (context, typeof (CustomRestrictionsActivity)); + extra.PutParcelable (Intent.ExtraRestrictionsIntent, customIntent); + } + + extra.PutParcelableArrayList (Intent.ExtraRestrictionsList, newEntries); + result.SetResult (Result.Ok, null, extra); + result.Finish (); + } + } +} + diff --git a/AppRestrictions/MainActivity.cs b/AppRestrictions/MainActivity.cs new file mode 100644 index 000000000..6f45923c0 --- /dev/null +++ b/AppRestrictions/MainActivity.cs @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using Android.App; +using Android.Content; +using Android.Runtime; +using Android.Views; +using Android.Widget; +using Android.OS; +using Android.Preferences; + +namespace AppRestrictions +{ + /** + * This is the main user interface of the App Restrictions sample app. It demonstrates the use + * of the App Restriction feature, which is available on Android 4.3 and above tablet devices + * with the multiuser feature. + * + * When launched under the primary User account, you can toggle between standard app restriction + * types and custom. When launched under a restricted profile, this activity displays app + * restriction settings, if available. + * + * Follow these steps to exercise the feature: + * 1. If this is the primary user, go to Settings > Users. + * 2. Create a restricted profile, if one doesn't exist already. + * 3. Open the profile settings, locate the sample app, and tap the app restriction settings + * icon. Configure app restrictions for the app. + * 4. In the lock screen, switch to the user's restricted profile, launch this sample app, + * and see the configured app restrictions displayed. + */ + [Activity (Label = "AppRestrictions", MainLauncher = true)] + public class MainActivity : Activity + { + Bundle mRestrictionsBundle; + + // Checkbox to indicate whether custom or standard app restriction types are selected. + CheckBox mCustomConfig; + + public static readonly String CUSTOM_CONFIG_KEY = "custom_config"; + + private TextView mMultiEntryValue; + private TextView mChoiceEntryValue; + private TextView mBooleanEntryValue; + + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + SetContentView (Resource.Layout.Main); + + mCustomConfig = FindViewById (Resource.Id.custom_app_limits); + + bool customChecked = + PreferenceManager.GetDefaultSharedPreferences (this).GetBoolean ( + CUSTOM_CONFIG_KEY, false); + + if (customChecked) mCustomConfig.Checked = true; + + mMultiEntryValue = FindViewById (Resource.Id.multi_entry_id); + mChoiceEntryValue = FindViewById (Resource.Id.choice_entry_id); + mBooleanEntryValue = FindViewById (Resource.Id.boolean_entry_id); + + /** + * Saves custom app restriction to the shared preference. + * + * This flag is used by {@code GetRestrictionsReceiver} to determine if a custom app + * restriction activity should be used. + * + * @param view + */ + mCustomConfig.Click += delegate (object sender, EventArgs e) { + var editor = PreferenceManager.GetDefaultSharedPreferences (this).Edit (); + editor.PutBoolean (CUSTOM_CONFIG_KEY, mCustomConfig.Checked).Commit (); + }; + } + + protected override void OnResume () + { + base.OnResume (); + + // If app restrictions are set for this package, when launched from a restricted profile, + // the settings are available in the returned Bundle as key/value pairs. + mRestrictionsBundle = ((UserManager) GetSystemService (Context.UserService)) + .GetApplicationRestrictions (PackageName); + + if (mRestrictionsBundle == null) { + mRestrictionsBundle = new Bundle (); + } + + // Reads and displays values from a boolean type restriction entry, if available. + // An app can utilize these settings to restrict its content under a restricted profile. + String booleanRestrictionValue = + mRestrictionsBundle.ContainsKey (GetRestrictionsReceiver.KEY_BOOLEAN) ? + mRestrictionsBundle.GetBoolean (GetRestrictionsReceiver.KEY_BOOLEAN) + "": + GetString (Resource.String.na); + mBooleanEntryValue.Text = booleanRestrictionValue; + + // Reads and displays values from a single choice restriction entry, if available. + String singleChoiceRestrictionValue = + mRestrictionsBundle.ContainsKey (GetRestrictionsReceiver.KEY_CHOICE) ? + mRestrictionsBundle.GetString (GetRestrictionsReceiver.KEY_CHOICE) : + GetString (Resource.String.na); + mChoiceEntryValue.Text = singleChoiceRestrictionValue; + + // Reads and displays values from a multi-select restriction entry, if available. + String[] multiSelectValues = + mRestrictionsBundle.GetStringArray (GetRestrictionsReceiver.KEY_MULTI_SELECT); + + if (multiSelectValues == null || multiSelectValues.Length == 0) { + mMultiEntryValue.Text = GetString (Resource.String.na); + + } else { + String tempValue = ""; + foreach (String value in multiSelectValues) { + tempValue = tempValue + value + " "; + } + mMultiEntryValue.Text = tempValue ; + } + } + } +} + diff --git a/AppRestrictions/Properties/AndroidManifest.xml b/AppRestrictions/Properties/AndroidManifest.xml new file mode 100644 index 000000000..e11dea0bb --- /dev/null +++ b/AppRestrictions/Properties/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/AppRestrictions/Properties/AssemblyInfo.cs b/AppRestrictions/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..d2bd87c71 --- /dev/null +++ b/AppRestrictions/Properties/AssemblyInfo.cs @@ -0,0 +1,23 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using Android.App; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. +[assembly: AssemblyTitle ("AppRestrictions")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("petercollins")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. +[assembly: AssemblyVersion ("1.0.0")] +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/AppRestrictions/README.md b/AppRestrictions/README.md new file mode 100644 index 000000000..a10b066b5 --- /dev/null +++ b/AppRestrictions/README.md @@ -0,0 +1,23 @@ +App Restrictions +================== +When launched under the primary User account, you can toggle between standard app restriction +types and custom. When launched under a restricted profile, this activity displays app +restriction settings, if available. + +This sample app maintains custom app restriction settings in shared preferences. When +the activity is invoked (from Settings > Users), the stored settings are used to initialize +the custom configuration on the user interface. Three sample input types are shown: +checkbox, single-choice, and multi-choice. When the settings are modified by the user, +the corresponding restriction entries are saved, which are retrievable under a restricted +profile. + +Follow these steps to exercise the feature: + 1. If this is the primary user, go to Settings > Users. + 2. Create a restricted profile, if one doesn't exist already. + 3. Open the profile settings, locate the sample app, and tap the app restriction settings + icon. Configure app restrictions for the app. + 4. In the lock screen, switch to the user's restricted profile, launch this sample app, + and see the configured app restrictions displayed. + +Based on the Google Android-18 sample "AppRestrictions". +Ported by: Peter Collins \ No newline at end of file diff --git a/AppRestrictions/Resources/drawable-hdpi/icon.png b/AppRestrictions/Resources/drawable-hdpi/icon.png new file mode 100755 index 000000000..2e6ef769f Binary files /dev/null and b/AppRestrictions/Resources/drawable-hdpi/icon.png differ diff --git a/AppRestrictions/Resources/drawable-mdpi/icon.png b/AppRestrictions/Resources/drawable-mdpi/icon.png new file mode 100755 index 000000000..edefb8b57 Binary files /dev/null and b/AppRestrictions/Resources/drawable-mdpi/icon.png differ diff --git a/AppRestrictions/Resources/drawable-xhdpi/icon.png b/AppRestrictions/Resources/drawable-xhdpi/icon.png new file mode 100755 index 000000000..de4bbc0d9 Binary files /dev/null and b/AppRestrictions/Resources/drawable-xhdpi/icon.png differ diff --git a/AppRestrictions/Resources/drawable-xxhdpi/icon.png b/AppRestrictions/Resources/drawable-xxhdpi/icon.png new file mode 100755 index 000000000..5e5182b38 Binary files /dev/null and b/AppRestrictions/Resources/drawable-xxhdpi/icon.png differ diff --git a/AppRestrictions/Resources/layout/Main.axml b/AppRestrictions/Resources/layout/Main.axml new file mode 100644 index 000000000..19c8cb337 --- /dev/null +++ b/AppRestrictions/Resources/layout/Main.axml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AppRestrictions/Resources/values/Strings.xml b/AppRestrictions/Resources/values/Strings.xml new file mode 100644 index 000000000..2dac3b1bf --- /dev/null +++ b/AppRestrictions/Resources/values/Strings.xml @@ -0,0 +1,65 @@ + + + + App Restrictions Demo + Custom app restrictions + Test boolean type + Test choice type + Test multi-select type + If checked, use a custom app restriction Activity. Otherwise, + use standard restriction types. + + Note: This sample app requires the restricted profile + feature.\n\n + 1. If this is the primary user, go to Settings > Users.\n\n + 2. Create a restricted profile, if one doesn\'t exist already.\n\n + 3. Open the profile settings, locate the sample app, and tap the app restriction settings + icon. Configure app restrictions for the app.\n\n + 4. In the lock screen, switch to the user\'s restricted profile, launch this sample app, + and see the configured app restrictions displayed.\n + + Go to Settings + Current app restriction settings: + N/A + Your app can restrict its content based on these + settings, which can be configured through the primary user\'s Users Settings. + + + + Ice Cream + Jelly Bean + More Jelly Bean + + + + 1 + 2 + 3 + + + + Ice Cream + Jelly Bean + More Jelly Bean + + + + 1 + 2 + 3 + + + \ No newline at end of file diff --git a/AppRestrictions/Resources/xml/custom_prefs.xml b/AppRestrictions/Resources/xml/custom_prefs.xml new file mode 100644 index 000000000..5a3cf0df5 --- /dev/null +++ b/AppRestrictions/Resources/xml/custom_prefs.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/AppRestrictions/Screenshots/configure_restrictions.png b/AppRestrictions/Screenshots/configure_restrictions.png new file mode 100755 index 000000000..1821a3083 Binary files /dev/null and b/AppRestrictions/Screenshots/configure_restrictions.png differ diff --git a/AppRestrictions/Screenshots/custom_configure_restrictions.png b/AppRestrictions/Screenshots/custom_configure_restrictions.png new file mode 100755 index 000000000..6ccf6a5d3 Binary files /dev/null and b/AppRestrictions/Screenshots/custom_configure_restrictions.png differ diff --git a/AppRestrictions/Screenshots/owner_view.png b/AppRestrictions/Screenshots/owner_view.png new file mode 100755 index 000000000..1e72b1ece Binary files /dev/null and b/AppRestrictions/Screenshots/owner_view.png differ diff --git a/AppRestrictions/Screenshots/restricted_view.png b/AppRestrictions/Screenshots/restricted_view.png new file mode 100755 index 000000000..753424088 Binary files /dev/null and b/AppRestrictions/Screenshots/restricted_view.png differ