Ultimate Guide To KIOSK Mode
Posted By : Keshav Gupta | 22-Jun-2017
A strongKiosk Mode is useful if you develop an Android app and want prevent any other applications to run in the foreground.
A few things to consider
1)Exit mechanism: Don't forget to implement and test an exit mechanism in your Android Kiosk app.
2)Talk to your users: Be careful, if you want to distribute your Kiosk app through the Play Store. Tell your users how they can leave your app before they enter the Kiosk Mode.
3)Nothing is completely secure: There are techies like you out there who can bypass your restrictions if the device is not physically secured.
Implementation
Overview
A Kiosk Mode is implemented by disabling various Android features that can be used to leave your app. The following features are affected:
- The back button
- The home button
- The recent apps button
- The power button
- The volume buttons
Disable the back button
This is a simple task: Just override onBackPressed in your Activity class. Please note that you can not override onBackPressed inside fragments!
public void onBackPressed()
{
just do nothing here..
}
Disable the volume buttons:
private final List blockedKeys = new ArrayList(Arrays.asList(KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_UP));
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (blockedKeys.contains(event.getKeyCode())) {
return true;
} else {
return super.dispatchKeyEvent(event);
}
}
Disable the Status Bar from scroll down to give a perfect Kiosk mode:
public class customViewGroup extends ViewGroup {
public customViewGroup(Context context) {
super(context);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("customViewGroup", "**********Intercepted");
return true;
}
}
//-------------------------------------------------------------------------------//
private WindowManager amanager;
public void disableStatusBar()
{
amanager = ((WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = (int) (50 * getResources()
.getDisplayMetrics().scaledDensity);
localLayoutParams.format = PixelFormat.TRANSPARENT;
view = new customViewGroup(this);
amanager.addView(view, localLayoutParams);
}
As there is no native way to do so. But to provide this feature we will set a transparent layer over the status bar which will consume the user touch. In a way restricting user to scroll.
create a class customviewgroup
Remove lock on status bar:
wmanager.removeview(customviewgroup instance)
Disabling recent app button and Long power button press:
/*CODE INITIATING KIOSK MODE FOR RESTRICTING RECENT TASK BUTTON IN FAVOR OF KIOSK MODE
SO THAT ANY SYSTEM DIALOG GET DISMISSED AUTOMATICALLY*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(!hasFocus)
{
Intent closeDialog=new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(closeDialog);
}
}
Disabling HomeButton:
There is no way to intercept the home button on Android, unless you make your app the home screen. This is for security reasons, so that malicious apps cannot take over your device by overriding all the buttons that can exit. The home button is the one sure shot way to be able to leave any app.
If you want to handle the HOME button, implement a home screen. or you need to create your application as home application.
Short power button press:
You can detect a short button press by handling the ACTION_SCREEN_OFF intent and kick the screen back to life with acquiring a wake lock. What a hack!
Please note that you can't declare ACTION_SCREEN_OFF in the AndroidManifest.xml! You are only allowed to catch them while your application is running. For that reason, create a class called OnScreenOffReceiver that extends BroadcastReceiver and add the following code:
public class OnScreenOffReceiver extends BroadcastReceiver {
private static final String PREF_KIOSK_MODE = "pref_kiosk_mode";
@Override
public void onReceive(Context context, Intent intent) {
if(Intent.ACTION_SCREEN_OFF.equals(intent.getAction())){
AppContext ctx = (AppContext) context.getApplicationContext();
// is Kiosk Mode active?
if(isKioskModeActive(ctx)) {
wakeUpDevice(ctx);
}
}
}
private void wakeUpDevice(AppContext context) {
PowerManager.WakeLock wakeLock = context.getWakeLock(); // get WakeLock reference via AppContext
if (wakeLock.isHeld()) {
wakeLock.release(); // release old wake lock
}
// create a new wake lock...
wakeLock.acquire();
// ... and release again
wakeLock.release();
}
private boolean isKioskModeActive(final Context context) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
return sp.getBoolean(PREF_KIOSK_MODE, false);
}
}
Create a subclass of Application and add the following code:
public class AppContext extends Application {
private AppContext instance;
private PowerManager.WakeLock wakeLock;
private OnScreenOffReceiver onScreenOffReceiver;
@Override
public void onCreate() {
super.onCreate();
instance = this;
registerKioskModeScreenOffReceiver();
}
private void registerKioskModeScreenOffReceiver() {
// register screen off receiver
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
onScreenOffReceiver = new OnScreenOffReceiver();
registerReceiver(onScreenOffReceiver, filter);
}
public PowerManager.WakeLock getWakeLock() {
if(wakeLock == null) {
// lazy loading: first call, create wakeLock via PowerManager.
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "wakeup");
}
return wakeLock;
}
}
Add the permission WAKE_LOCK to your manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
Register your subclass of Application in your manifest (android:name=".AppContext"):
<application
android:name=".AppContext"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
To make the wake up a bit smarter, add the following line in your activity (before setContentView is called!). This line deactivates the lock screen:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
For example:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
setContentView(R.layout.my_activity);
// … further layout init
}
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Keshav Gupta
Keshav Gupta is Android Developer in Oodles, he always look forward for new tasks and new things to learn more.