/*
* Copyright (C) 2014 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.apprestrictionenforcer;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.RestrictionEntry;
import android.content.RestrictionsManager;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
/**
* This fragment provides UI and functionality to set restrictions on the AppRestrictionSchema
* sample.
*/
public class AppRestrictionEnforcerFragment extends Fragment implements View.OnClickListener,
CompoundButton.OnCheckedChangeListener {
/**
* Package name of the AppRestrictionSchema sample.
*/
private static final String PACKAGE_NAME_APP_RESTRICTION_SCHEMA
= "com.example.android.apprestrictionschema";
/**
* Key for {@link SharedPreferences}
*/
private static final String PREFS_KEY = "AppRestrictionEnforcerFragment";
/**
* Key for the boolean restriction in AppRestrictionSchema.
*/
private static final String RESTRICTION_KEY_SAY_HELLO = "can_say_hello";
/**
* Default boolean value for "can_say_hello" restriction. The actual value is loaded in
* {@link #loadRestrictions(android.app.Activity)}.
*/
private boolean mDefaultValueRestrictionSayHello;
// UI Components
private TextView mTextStatus;
private Button mButtonUnhide;
private Switch mSwitchSayHello;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_app_restriction_enforcer, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
mTextStatus = (TextView) view.findViewById(R.id.status);
mButtonUnhide = (Button) view.findViewById(R.id.unhide);
mSwitchSayHello = (Switch) view.findViewById(R.id.say_hello);
mButtonUnhide.setOnClickListener(this);
mSwitchSayHello.setOnCheckedChangeListener(this);
}
@Override
public void onResume() {
super.onResume();
updateUi(getActivity());
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.unhide: {
unhideApp(getActivity());
break;
}
}
}
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
switch (compoundButton.getId()) {
case R.id.say_hello: {
allowSayHello(getActivity(), checked);
break;
}
}
}
/**
* Updates the UI components according to the current status of AppRestrictionSchema and its
* restriction.
*
* @param activity The activity
*/
private void updateUi(Activity activity) {
PackageManager packageManager = activity.getPackageManager();
try {
ApplicationInfo info = packageManager.getApplicationInfo(
PACKAGE_NAME_APP_RESTRICTION_SCHEMA, PackageManager.GET_UNINSTALLED_PACKAGES);
DevicePolicyManager devicePolicyManager =
(DevicePolicyManager) activity.getSystemService(Activity.DEVICE_POLICY_SERVICE);
if (0 < (info.flags & ApplicationInfo.FLAG_INSTALLED)) {
if (!devicePolicyManager.isApplicationHidden(
EnforcerDeviceAdminReceiver.getComponentName(activity),
PACKAGE_NAME_APP_RESTRICTION_SCHEMA)) {
// The app is ready
loadRestrictions(activity);
mTextStatus.setVisibility(View.GONE);
mButtonUnhide.setVisibility(View.GONE);
mSwitchSayHello.setVisibility(View.VISIBLE);
mSwitchSayHello.setOnCheckedChangeListener(null);
mSwitchSayHello.setChecked(canSayHello(activity));
mSwitchSayHello.setOnCheckedChangeListener(this);
} else {
// The app is installed but hidden in this profile
mTextStatus.setText(R.string.status_not_activated);
mTextStatus.setVisibility(View.VISIBLE);
mButtonUnhide.setVisibility(View.VISIBLE);
mSwitchSayHello.setVisibility(View.GONE);
}
} else {
// Need to reinstall the sample app
mTextStatus.setText(R.string.status_need_reinstall);
mTextStatus.setVisibility(View.VISIBLE);
mButtonUnhide.setVisibility(View.GONE);
mSwitchSayHello.setVisibility(View.GONE);
}
} catch (PackageManager.NameNotFoundException e) {
mTextStatus.setText(R.string.status_not_installed);
mTextStatus.setVisibility(View.VISIBLE);
mButtonUnhide.setVisibility(View.GONE);
mSwitchSayHello.setVisibility(View.GONE);
}
}
/**
* Unhides the AppRestrictionSchema sample in case it is hidden in this profile.
*
* @param activity The activity
*/
private void unhideApp(Activity activity) {
DevicePolicyManager devicePolicyManager =
(DevicePolicyManager) activity.getSystemService(Activity.DEVICE_POLICY_SERVICE);
devicePolicyManager.setApplicationHidden(
EnforcerDeviceAdminReceiver.getComponentName(activity),
PACKAGE_NAME_APP_RESTRICTION_SCHEMA, false);
Toast.makeText(activity, "Enabled the app", Toast.LENGTH_SHORT).show();
updateUi(activity);
}
/**
* Loads the restrictions for the AppRestrictionSchema sample. In this implementation, we just
* read the default value for the "can_say_hello" restriction.
*
* @param activity The activity
*/
private void loadRestrictions(Activity activity) {
RestrictionsManager restrictionsManager =
(RestrictionsManager) activity.getSystemService(Context.RESTRICTIONS_SERVICE);
List<RestrictionEntry> restrictions =
restrictionsManager.getManifestRestrictions(PACKAGE_NAME_APP_RESTRICTION_SCHEMA);
for (RestrictionEntry restriction : restrictions) {
if (RESTRICTION_KEY_SAY_HELLO.equals(restriction.getKey())) {
mDefaultValueRestrictionSayHello = restriction.getSelectedState();
}
}
}
/**
* Returns whether the AppRestrictionSchema is currently allowed to say hello to its user. Note
* that a profile/device owner needs to remember each restriction value on its own.
*
* @param activity The activity
* @return True if the AppRestrictionSchema is allowed to say hello
*/
private boolean canSayHello(Activity activity) {
SharedPreferences prefs = activity.getSharedPreferences(PREFS_KEY, Context.MODE_PRIVATE);
return prefs.getBoolean(RESTRICTION_KEY_SAY_HELLO, mDefaultValueRestrictionSayHello);
}
/**
* Sets the value for the "cay_say_hello" restriction of AppRestrictionSchema.
*
* @param activity The activity
* @param allow The value to be set for the restriction.
*/
private void allowSayHello(Activity activity, boolean allow) {
DevicePolicyManager devicePolicyManager
= (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
Bundle restrictions = new Bundle();
restrictions.putBoolean(RESTRICTION_KEY_SAY_HELLO, allow);
devicePolicyManager.setApplicationRestrictions(
EnforcerDeviceAdminReceiver.getComponentName(activity),
PACKAGE_NAME_APP_RESTRICTION_SCHEMA, restrictions);
// The profile/device owner needs to remember the current state of restrictions on its own
activity.getSharedPreferences(PREFS_KEY, Context.MODE_PRIVATE)
.edit()
.putBoolean(RESTRICTION_KEY_SAY_HELLO, allow)
.apply();
Toast.makeText(activity, allow ? R.string.allowed : R.string.disallowed,
Toast.LENGTH_SHORT).show();
}
}