App limits sample

Shows how to expose app restrictions for both simple types
and custom intents.

Change-Id: I95d422d1d637bd4bdb4f731d862975a160b65a50
This commit is contained in:
Amith Yamasani
2013-03-29 17:46:22 -07:00
parent d3b17b74c1
commit 447d1e3d6c
6 changed files with 409 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := samples tests
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := AppLimits
LOCAL_SDK_VERSION := current
include $(BUILD_PACKAGE)
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
# Use the following include to make our test apk.
include $(call all-makefiles-under,$(LOCAL_PATH))

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<manifest android:versionCode="1"
android:versionName="1"
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.applimits">
<application android:label="@string/app_name"
android:requiredForAllUsers="true">
<activity android:name="CustomRestrictionsActivity"
android:exported="true"
android:label="@string/restrictions_activity_label">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="GetRestrictionsReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.GET_RESTRICTION_ENTRIES" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">AppLimits Demo</string>
<string name="restrictions_activity_label">Custom app restrictions</string>
<string name="app_limits_main_label">App Limits</string>
<string name="custom_or_not_title">Test Custom Restrictions</string>
<string name="choice_entry_title">Test choice type</string>
<string name="multi_entry_title">Test multi-select type</string>
<string-array name="multi_entry_entries">
<item>Ice Cream</item>
<item>Jelly Bean</item>
<item>More Jelly Bean</item>
</string-array>
<string-array name="multi_entry_values" translateable="false">
<item>1</item>
<item>2</item>
<item>3</item>
</string-array>
<string-array name="choice_entry_entries">
<item>Ice Cream</item>
<item>Jelly Bean</item>
<item>More Jelly Bean</item>
</string-array>
<string-array name="choice_entry_values" translateable="false">
<item>1</item>
<item>2</item>
<item>3</item>
</string-array>
</resources>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/restrictions_activity_label">
<CheckBoxPreference android:key="custom"
android:title="@string/custom_or_not_title" />
<ListPreference android:key="choice"
android:title="@string/choice_entry_title"
android:entries="@array/choice_entry_entries"
android:entryValues="@array/choice_entry_values" />
<MultiSelectListPreference android:key="multi"
android:title="@string/multi_entry_title"
android:entries="@array/multi_entry_entries"
android:entryValues="@array/multi_entry_values" />
</PreferenceScreen>

View File

@@ -0,0 +1,118 @@
/*
* 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.
*/
package com.example.android.applimits;
import android.content.Intent;
import android.content.RestrictionEntry;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.MultiSelectListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
public class CustomRestrictionsActivity extends PreferenceActivity
implements OnPreferenceChangeListener {
private static final String KEY_CUSTOM_PREF = "custom";
private static final String KEY_CHOICE_PREF = "choice";
private static final String KEY_MULTI_PREF = "multi";
ArrayList<RestrictionEntry> mRestrictions;
CheckBoxPreference mCustomPref;
ListPreference mChoicePref;
MultiSelectListPreference mMultiPref;
RestrictionEntry mCustomEntry;
RestrictionEntry mChoiceEntry;
RestrictionEntry mMultiEntry;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRestrictions = getIntent().getParcelableArrayListExtra(
Intent.EXTRA_RESTRICTIONS);
if (savedInstanceState != null
&& savedInstanceState.containsKey(Intent.EXTRA_RESTRICTIONS)) {
mRestrictions = savedInstanceState.getParcelableArrayList(Intent.EXTRA_RESTRICTIONS);
}
this.addPreferencesFromResource(R.xml.custom_prefs);
mCustomPref = (CheckBoxPreference) findPreference(KEY_CUSTOM_PREF);
mChoicePref = (ListPreference) findPreference(KEY_CHOICE_PREF);
mMultiPref = (MultiSelectListPreference) findPreference(KEY_MULTI_PREF);
// Transfer the saved values into the preference hierarchy
for (RestrictionEntry entry : mRestrictions) {
if (entry.getKey().equals(GetRestrictionsReceiver.KEY_CUSTOM)) {
mCustomPref.setChecked(entry.getSelectedState());
mCustomEntry = entry;
} else if (entry.getKey().equals(GetRestrictionsReceiver.KEY_CHOICE)) {
mChoicePref.setValue(entry.getSelectedString());
mChoiceEntry = entry;
} else if (entry.getKey().equals(GetRestrictionsReceiver.KEY_MULTI_SELECT)) {
HashSet<String> set = new HashSet<String>();
for (String value : entry.getAllSelectedStrings()) {
set.add(value);
}
mMultiPref.setValues(set);
mMultiEntry = entry;
}
}
mCustomPref.setOnPreferenceChangeListener(this);
mChoicePref.setOnPreferenceChangeListener(this);
mMultiPref.setOnPreferenceChangeListener(this);
Intent intent = new Intent(getIntent());
intent.putParcelableArrayListExtra(Intent.EXTRA_RESTRICTIONS,
mRestrictions);
setResult(RESULT_OK, intent);
}
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS, mRestrictions);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mCustomPref) {
mCustomEntry.setSelectedState((Boolean) newValue);
} else if (preference == mChoicePref) {
mChoiceEntry.setSelectedString((String) newValue);
} else if (preference == mMultiPref) {
String[] selectedStrings = new String[((Set<String>)newValue).size()];
int i = 0;
for (String value : (Set<String>) newValue) {
selectedStrings[i++] = value;
}
mMultiEntry.setAllSelectedStrings(selectedStrings);
}
Intent intent = new Intent(getIntent());
intent.putParcelableArrayListExtra(Intent.EXTRA_RESTRICTIONS,
mRestrictions);
setResult(RESULT_OK, intent);
return true;
}
}

View File

@@ -0,0 +1,150 @@
/*
* 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.
*/
package com.example.android.applimits;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.RestrictionEntry;
import android.content.BroadcastReceiver.PendingResult;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
public class GetRestrictionsReceiver extends BroadcastReceiver {
private static final String TAG = "AppLimits$GetRestrictionsReceiver";
static final String KEY_CUSTOM = "custom_or_not";
static final String KEY_CHOICE = "choice";
static final String KEY_MULTI_SELECT = "multi";
@Override
public void onReceive(final Context context, Intent intent) {
final PendingResult result = goAsync();
final ArrayList<RestrictionEntry> oldRestrictions =
intent.getParcelableArrayListExtra(Intent.EXTRA_RESTRICTIONS);
Log.i(TAG, "oldRestrictions = " + oldRestrictions);
new Thread() {
public void run() {
createRestrictions(context, result, oldRestrictions);
}
}.start();
}
public static void populateCustomEntry(Resources res, RestrictionEntry entry) {
entry.setType(RestrictionEntry.TYPE_BOOLEAN);
entry.setTitle(res.getString(R.string.custom_or_not_title));
}
public static void populateChoiceEntry(Resources res, RestrictionEntry reSingleChoice) {
String[] choiceEntries = res.getStringArray(R.array.choice_entry_entries);
String[] choiceValues = res.getStringArray(R.array.choice_entry_values);
if (reSingleChoice.getSelectedString() == null) {
reSingleChoice.setSelectedString(choiceValues[0]);
}
reSingleChoice.setTitle(res.getString(R.string.choice_entry_title));
reSingleChoice.setChoiceEntries(choiceEntries);
reSingleChoice.setChoiceValues(choiceValues);
reSingleChoice.setType(RestrictionEntry.TYPE_CHOICE);
}
public static void populateMultiEntry(Resources res, RestrictionEntry reMultiSelect) {
String[] multiEntries = res.getStringArray(R.array.multi_entry_entries);
String[] multiValues = res.getStringArray(R.array.multi_entry_values);
if (reMultiSelect.getAllSelectedStrings() == null) {
reMultiSelect.setAllSelectedStrings(new String[0]);
}
reMultiSelect.setTitle(res.getString(R.string.multi_entry_title));
reMultiSelect.setChoiceEntries(multiEntries);
reMultiSelect.setChoiceValues(multiValues);
reMultiSelect.setType(RestrictionEntry.TYPE_MULTI_SELECT);
}
private ArrayList<RestrictionEntry> initRestrictions(Context context) {
ArrayList<RestrictionEntry> newRestrictions = new ArrayList<RestrictionEntry>();
Resources res = context.getResources();
RestrictionEntry reCustomOrNot = new RestrictionEntry(KEY_CUSTOM, false);
populateCustomEntry(res, reCustomOrNot);
newRestrictions.add(reCustomOrNot);
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, ArrayList<RestrictionEntry> old) {
Resources res = context.getResources();
ArrayList<RestrictionEntry> newEntries = initRestrictions(context);
// If this is the first time, create the default restrictions entries and return them.
if (old == null) {
Bundle extras = new Bundle();
extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS, newEntries);
result.setResult(Activity.RESULT_OK, null, extras);
result.finish();
return;
}
boolean custom = false;
for (RestrictionEntry entry : old) {
if (entry.getKey().equals(KEY_CUSTOM)) {
if (entry.getSelectedState()) {
custom = true;
}
RestrictionEntry newEntry = find(newEntries, KEY_CUSTOM);
newEntry.setSelectedState(entry.getSelectedState());
} else if (entry.getKey().equals(KEY_CHOICE)) {
RestrictionEntry newEntry = find(newEntries, KEY_CHOICE);
newEntry.setSelectedString(entry.getSelectedString());
} else if (entry.getKey().equals(KEY_MULTI_SELECT)) {
RestrictionEntry newEntry = find(newEntries, KEY_MULTI_SELECT);
newEntry.setAllSelectedStrings(entry.getAllSelectedStrings());
}
}
Bundle extras = new Bundle();
if (custom) {
Intent customIntent = new Intent();
customIntent.setClass(context, CustomRestrictionsActivity.class);
extras.putParcelable(Intent.EXTRA_RESTRICTIONS_INTENT, customIntent);
}
extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS, newEntries);
result.setResult(Activity.RESULT_OK, null, extras);
result.finish();
}
private RestrictionEntry find(ArrayList<RestrictionEntry> entries, String key) {
for (RestrictionEntry entry : entries) {
if (entry.getKey().equals(key)) {
return entry;
}
}
return null;
}
}