Making your Android Device to be a KIOSK

Steps to achieve our goal:
Develop a KIOSK app for Android devices
Make the App to be the device owner

Develop a KIOSK app for Android devices

A KIOSK implies that a user can only navigate through some screens intended to be viewed and provide appropriate input where required. This also applies that once the device is in KIOSK mode, all other features like notifications for incoming call or SMS, home button, device back button, volume buttons, etc. of the device should be disabled until the admin disables the KIOSK mode, while the screen stays on all the time. Even if the device is restarted during KIOSK mode, the user is taken directly to the Questionnaire screen enabling the KIOSK mode at start up. We can also disable restart and factory reset options if we desire.

Components of a KIOSK app are:

A Receiver Class extending android.app.admin.DeviceAdminReceiver to handle events related to the managed profile

public class DeviceAdminReceiver extends android.app.admin.DeviceAdminReceiver {
private static final String TAG = “DeviceAdminReceiver”;
public static ComponentName getComponentName(Context context) {
return new ComponentName(context.getApplicationContext(), DeviceAdminReceiver.class);
}
}

An Admin Policy file listing all policies that we would like to enforce on the device

<?xml version=”1.0″ encoding=”utf-8″?>

<device-admin>
<uses-policies>
<disable-keyguard-features/>
</uses-policies>
</device-admin

Add the Receiver created above to your AndroidManifest file with required intent-filter(s) and permission(s)

<receiver
android:name=”au.com.rightwayitservices.DeviceAdminReceiver”
android:description=”@string/app_name”
android:label=”@string/app_name”
android:permission=”android.permission.BIND_DEVICE_ADMIN”>
<meta-data
android:name=”android.app.device_admin”
android:resource=”@xml/device_admin_receiver” />
<intent-filter>
<action android:name=”android.intent.action.DEVICE_ADMIN_ENABLED”/>
<action android:name=”android.app.action.DEVICE_ADMIN_DISABLED” />
<action android:name=”android.intent.action.PROFILE_PROVISIONING_COMPLETE”/>
<action android:name=”android.intent.action.BOOT_COMPLETED”/>
</intent-filter>
</receiver>

Now create an User Interface, with function to enable KIOSK view. In our example app I have used an Activity.

private void setDefaultMyKioskPolicies(boolean active) {
// set user restrictions
setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, active);
setUserRestriction(UserManager.DISALLOW_FACTORY_RESET, false);
setUserRestriction(UserManager.DISALLOW_ADD_USER, active);
setUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, active);
setUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME, active);

// disable keyguard and status bar
devicePolicyManager.setKeyguardDisabled(adminComponentName, active);
devicePolicyManager.setStatusBarDisabled(adminComponentName, active);

// enable STAY_ON_WHILE_PLUGGED_IN
enableStayOnWhilePluggedIn(active);

// set system update policy
if (active) {
devicePolicyManager.setSystemUpdatePolicy(adminComponentName,
SystemUpdatePolicy.createWindowedInstallPolicy(60, 120));
} else {
devicePolicyManager.setSystemUpdatePolicy(adminComponentName,
null);
}

// set this Activity as a lock task package
devicePolicyManager.setLockTaskPackages(adminComponentName,
active ? new String[]{getPackageName()} : new String[]{});

IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MAIN);
intentFilter.addCategory(Intent.CATEGORY_HOME);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);

if (active) {
// set KIOSK activity as home intent receiver so that it is started
// on reboot
devicePolicyManager.addPersistentPreferredActivity(
adminComponentName, intentFilter, new ComponentName(
getPackageName(), LockedActivity.class.getName()));
} else {
devicePolicyManager.clearPackagePersistentPreferredActivities(
adminComponentName, getPackageName());
}
}

private void setUserRestriction(String restriction, boolean disallow) {
if (disallow) {
devicePolicyManager.addUserRestriction(adminComponentName,
restriction);
} else {
devicePolicyManager.clearUserRestriction(adminComponentName,
restriction);
}
}

private void enableStayOnWhilePluggedIn(boolean enabled) {
if (enabled) {
devicePolicyManager.setGlobalSetting(
adminComponentName,
Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
Integer.toString(BatteryManager.BATTERY_PLUGGED_AC
| BatteryManager.BATTERY_PLUGGED_USB
| BatteryManager.BATTERY_PLUGGED_WIRELESS));
} else {
devicePolicyManager.setGlobalSetting(
adminComponentName,
Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
“0”
);
}
}

In the code above devicePolicyManager is an instance of (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE)

And adminComponentName is an instance of

DeviceAdminReceiver.getComponentName(this);

Now that we have our KIOSK app, we need to set it to be the device owner.

Make the App to be the device owner

A device owner can only be set on an unprovisioned device, where no account is associated with the device. link. You can add back your account once you have set your KIOSK app to the be device owner.

I have set my app as a device owner by removing all accounts, like gmail, on the device (sometimes you might need to factory reset your device) and then connected the device to my laptop to push the app to the device using ADB and set the app to be device owner using the command below.

adb shell dpm set-device-owner au.com.rightwayitservices.kiosk/.DeviceAdminReceiver

Now we can open our app and set it to KIOSK mode to be used by any user, without having any access to any other features of the Android device, who walks into your shop.

You can learn more on Lock Task modeDeviceAdminReceiver or DevicePolicyManger. You can also refer to link to learn on setting an app as Device Owner.

Source code can be downloaded from github link.