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
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

About Author

Author Image
Keshav Gupta

Keshav Gupta is Android Developer in Oodles, he always look forward for new tasks and new things to learn more.

Request for Proposal

Name is required

Comment is required

Sending message..