简体   繁体   中英

Kiosk mode for android

I have a hybrid application written on phonegap for android tablets. Now I want the tablet to show only my application. Basically I want the tablet to be always in kiosk mode running only my application. So that all the buttons are disabled. I have looked for solutions online and one of them is to use "surelock", but it doesnt do all of the above. Another option is to write my own ROM, however I couldnt find any good tutorials on that. Can anyone help me plz?

I did a lot of research and now finally I am satisfied with what I got.

You basically have two options :

  1. Create you own custom ROM, which is not the best solution for me.

  2. Customize the tablets using various hacks.

So I will be explaining the second option.

First you need to root your devices. There are various methods, but I prefer rooting by oneclick software. For Chinese tablets you can use VROOT and for more popular ones use Kingo root.

Now, that you have your device rooted, we can get rid of the top and bottom bar.

private void hideBar(){
    try
    {
        Process proc = Runtime.getRuntime().exec(new String[]{"su","-c","service call activity 42 s16 com.android.systemui"}); 
        proc.waitFor();
    }
    catch(Exception ex)
    {
        Toast.makeText(getApplicationContext(), ex.getMessage(), Toast.LENGTH_LONG).show();
        Log.e("ROOT ERROR", ex.getMessage());
    }
}

This will make the top and bottom bar disappear. However you will probably need a way to show the bars again. For that you can use:

public void showBars(){
    try 
    {
        String command;
        command = "LD_LIBRARY_PATH=/vendor/lib:/system/lib am startservice -n com.android.systemui/.SystemUIService";
        String[] envp = null;
        Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command }, envp);
        proc.waitFor();
    } 
    catch(Exception ex)
    {
        Toast.makeText(context.getApplicationContext(), ex.getMessage(), Toast.LENGTH_LONG).show();
    }
}

Ok so we have that, all that remains is to make your application start at boot time. For that you can find many tutorials, just google.

With Android L-release (Lollipop) there is a feature called pinning that is pretty much the equivalent of Kiosk mode. Here is a link that explains how to set it up.

I believe Apple introduced this first in iOS. Even though the OP hasn't asked, I am also providing the details for iOS:

Android: http://www.cnet.com/how-to/ho-to-pin-apps-in-android-5-lollipop/

iOS: http://www.webascender.com/Blog/ID/447/How-to-Setup-Kiosk-Mode-Lock-Your-iPad-to-Just-One-App#.VzrO2ZN95E5

I think there is an alternative solution without rooting the device. My boss asked me to avoid rooting, so after some research I came to this workaround. In result, no hacks were done, system keys still remain, but the user is not able to leave the application and launch another one. So, I did following steps.

1. By editing the manifest set the fullscreen theme without TitleBar and ActionBar for the appropriate Activity , like this:

<application
    ...
    android:theme="android:Theme.Holo.NoActionBar.Fullscreen" >

2. Disabled the back button by overriding the method of Activity class:

@Override
public void onBackPressed() {
    return;
}

3. Add following strings to manifest (intent filter of the appropriate Activity ):

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.HOME" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

Now you can replace the default home screen with your application. But the ability to quit the app yet remains, by clicking the "recent apps" button and choosing another one.

4. To avoid all another ways of leaving the app I added a service, which starts every time when the activity is paused. This service relaunches the application and sends a notification about it. Service code:

public class RelaunchService extends Service {
    private Notification mNotification;
    private Timer mTimer;

    public RelaunchService() {
    }

    @Override
    public void onCreate(){
        super.onCreate();
        if (mNotification == null) {
            Context context = getApplicationContext();
            Intent notificationIntent = new Intent(this, FullscreenActivity.class);
            PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                    notificationIntent, 0);
            Notification.Builder mBuilder = new Notification.Builder(context)
                    .setSmallIcon(android.R.drawable.ic_dialog_info)
                    .setWhen(System.currentTimeMillis())
                    .setContentIntent(contentIntent)
                    .setContentTitle("Your app title")
                    .setContentText("App is being relaunched");
            mNotification = mBuilder.getNotification();

            mTimer = new Timer("LaunchTimer");
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        startForeground(1, mNotification);
        mTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                Intent intent = new Intent(RelaunchService.this, YourActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
            }
        }, 300);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopForeground(true);
        mTimer.cancel();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

Code added to the Activity class:

@Override
protected void onResume() {
    super.onResume();
    exitAllowed = false;
    Intent servIntent = new Intent(this, RelaunchService.class);
    stopService(servIntent);
}

@Override
protected void onPause() {
    super.onPause();
    savePersistentData();
    if (!exitAllowed) {
        Intent servIntent = new Intent(this, RelaunchService.class);
        startService(servIntent);
    }
}

The exitAllowed boolean variable should be assinged to true when you want to close the application. You can consider some way to do that, for example by clicking "Exit" button. In my case, the password is required to quit.

Non rooted solution is possible in Samsung phone, Have a look on free Superlock app

https://play.google.com/store/apps/details?id=com.superkiosk.ospolice.superlocklite&hl=en_GB

You don't need to create a custom ROM or even root you devices to get kiosk mode. It is usually strongly advised to not root devices that will be out in the field especially if your apps will have sensitive data.

12oz Mouse's answer ( https://stackoverflow.com/a/29560438/2888763 ) may work in most cases but it isn't completely secure. Your app or service can always be killed by system or crash, giving the user complete access to the device.

One way to achieve kiosk mode is to use Google's lock task mode - which is different than screen-pinning ( https://developer.android.com/work/cosu.html ). The link there lists some of the lock task mode features like: having one app pinned to the home screen and disabling/hiding Home and Recents buttons. The link also shows why the biggest issue with Google's solution is the complexity of setting it up. You either have to "Use a third-party enterprise mobility management (EMM) solution" or "Create your own DPC app". Google's COSU solution also may not work if you don't have access to Google Play Services.

Another option is using a mobile deployment platform like Mason ( https://bymason.com/ ) where you can build a custom Android OS in a few minutes with features like kiosk mode. You can then deploy OS or app updates remotely to all of your devices.

Feel free to ping me directly: trevor @ bymason.com

DISCLAIMER: I work for Mason

I eventually settled on this solution, needs no root, external apps and can be used on browsers, webapps and native apps:

Immersive full-screen mode

  1. Using adb, check if your device is visible with adb devices (dev options must be enabled)
  2. Find the id of the app you want to full-screen (if it's a webapp it's the browser it uses like org.mozilla.firefox or com.android.chrome ) it's in the play store url: https://play.google.com/store/apps/details?id=org.mozilla.firefox
  3. Excecute the command adb shell settings put global policy_control immersive.full=org.mozilla.firefox replacing org.mozilla.firefox with your id

More info here: https://www.howtogeek.com/302194/how-to-force-any-android-app-into-fullscreen-immersive-mode-without-rooting/

In combination with Screen pinning:

  1. Launch the Settings app on your Android device.
  2. Scroll down until you find the Security option. Tap on it.
  3. At the bottom of the Security page tap on Screen pinning.
  4. Slide the switch to the On position.
  5. Open your app, go the the view with your recent apps and tap the pin icon on the preview of your current app (bottom right)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM