Android Kiosk Mode - Preventing users from "unauthorized" unpinning the application
Asked Answered
F

3

7

I am pretty new to android and I am currently developing an Android App that should run in KioskMode, so that a normal user can't exit the application or do anything outside of it.
What I already did:

  • I set my app as a device owner
  • I "screen pin" the app in the onCreate()-method in the MainActivity as a device owner
  • I have a button in the MainActivity which later on allows an admin to exit by entering a password. Calls stopLockTask()

The Problem I encountered now is, that any user can exit the Screen Pinning by simply long pressing "back" and "multitasking" buttons simultaneously, because the tablet on which the app should run has hardwarebuttons which I can not simply deactivate. (at least I don't know how to do this without rooting the device)
So is there any way to deactivate this button combination for exiting screen pinning, or some neat workaround? One approach I thought of was repinning the Application in my AdminReceiver class in the onLockTaskModeExiting(), but I´m still stuck on how to do this.

Here are some code snippets of my MainActivity and the AdminReceiver class:
AdminReceiver.java

public class AdminReceiver extends DeviceAdminReceiver{

@Override
public void onEnabled(Context context, Intent intent) {
    Toast.makeText(context, context.getString(R.string.device_admin_enabled), Toast.LENGTH_SHORT).show();
}

@Override
public CharSequence onDisableRequested(Context context, Intent intent) {
    return context.getString(R.string.device_admin_warning);
}

@Override
public void onDisabled(Context context, Intent intent) {
    Toast.makeText(context, context.getString(R.string.device_admin_disabled), Toast.LENGTH_SHORT).show();
}

@Override
public void onLockTaskModeEntering(Context context, Intent intent, String pkg) {
    Toast.makeText(context, context.getString(R.string.kiosk_mode_enabled), Toast.LENGTH_SHORT).show();
}

@Override
public void onLockTaskModeExiting(Context context, Intent intent) {
    Toast.makeText(context, context.getString(R.string.kiosk_mode_disabled), Toast.LENGTH_SHORT).show();
}

}

MainActivity.java

public class MainActivity extends Activity {

private DevicePolicyManager mDpm;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ComponentName deviceAdmin = new ComponentName(this, AdminReceiver.class);
    mDpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);

    if (!mDpm.isAdminActive(deviceAdmin)) {
        Toast.makeText(this, getString(R.string.not_device_admin), Toast.LENGTH_SHORT).show();
    }


    if (mDpm.isDeviceOwnerApp(getPackageName())) {
        Toast.makeText(this, getString(R.string.device_owner), Toast.LENGTH_SHORT).show();

        mDpm.setLockTaskPackages(deviceAdmin, new String[]{getPackageName()});
        startLockTask();
    } else {
        Toast.makeText(this, getString(R.string.not_device_owner), Toast.LENGTH_SHORT).show();
    }

    Button exit = (Button) findViewById(R.id.exit);
    exit.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v) {
            stopLockTask();
        }
    });}

Any help is highly appreciated. Thanks!

Fatimahfatimid answered 27/4, 2016 at 22:7 Comment(2)
How are you setting your app as Device Owner? If your app is actually set as Device Owner the recent button will also be hidden. See the sample DPC for more info.Thaumaturge
@Phil, yea how did you set Device owner?Gesner
Z
2

If the activity is set as DEFAULT HOME

<activity
        android:name=".AppActivity"
        android:label="Locked Activity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER" />
            <category android:name="android.intent.category.HOME"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
</activity>

every time the user press the home button the activity can re-enable the lock on onCreate, onResume or onStart. If the app was forcefully unpinned using overview and back key and the recent activity list is empty, the user can only press the home button which will re-enable the lock.

As the question is 12 months old, I'm too still looking for a more effective solution.

Zumstein answered 23/4, 2017 at 21:5 Comment(2)
Could you provide an example with this? I'm a react native developer so I'm kinda lost. Thanks! I have the restriction that I can not set the app as device owner.Turbit
@Zumstein were you able to find any solution for this?Gamba
T
0

Just restart your activity and re-pin the screen if the lock task mode exited without intention.

@Override
public void onLockTaskModeExiting(Context context, Intent intent) {
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
        if (sharedPreferences.getBoolean(PIN_SHOULD_ENABLED, false)) {
            context.startActivity(new Intent(context, YOUR_PIN_SCREEN_ACTIVITY.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
    }
}
Tasimeter answered 14/5, 2016 at 15:52 Comment(0)
V
0

I had this issue and tried answers in this thread. I wouldnt recommend Xavier Lin's answer as it ends up creating multiple instances of your app.

Fortunately I came up with a solution of my own.

In your class that extends DeviceAdminReceiver, override onLockTaskModeExiting and run the pin code there.

public class AdminReceiver extends DeviceAdminReceiver{

    @Override
    public void onLockTaskModeExiting(Context context, Intent intent) {
        super.onLockTaskModeExiting(context, intent);

        // Run pinning code here
    }
}
Vagary answered 8/3, 2018 at 3:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.