Skip to main content
Android mainboards · Touch displays · Firmware — since 2013

Build a kiosk that survives the field

A kiosk in the field has no keyboard, no technician, and no patience for a stuck screen. This guide turns a KTM board into a device that boots straight into your app, refuses to be tampered with, and brings itself back after a power cut or a frozen night — using the device API end to end.

We build it in layers, each one a real call you can paste. Skip none of them — each closes a gap that becomes a support ticket later.

Root makes this simpler than on most hardware

Every lockdown call here works from a normally-signed app, because the firmware is rooted. No platform key, no owner-mode dance. See Permissions and signing.

What you will build​

A device that:

  1. Launches your app automatically on boot.
  2. Hides the status and navigation bars so there is no way out.
  3. Blocks app installation and USB storage so it cannot be tampered with.
  4. Reboots itself nightly to clear leaks, and recovers from a freeze via the hardware watchdog.
  5. Powers down out of hours and wakes before opening.

Layer 1 — Launch on boot​

Your app has to come up on its own. That is a BOOT_COMPLETED receiver — it does not need ItempApiPub, but it is the foundation everything else sits on. The full recipe is in Start on boot; the short version:

AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<receiver android:name=".BootReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
public class BootReceiver extends BroadcastReceiver {
@Override public void onReceive(Context ctx, Intent it) {
Intent app = new Intent(ctx, MainActivity.class);
app.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(app);
}
}

Layer 2 — Hide the system UI​

Once your app is up, remove every route out of it. Two calls:

import com.itemp.itempapi.ItempApiPub;

// Call once your kiosk activity is in the foreground.
ItempApiPub.setStatusBarHide(context);
ItempApiPub.setNavigationBarHide(context);

Now there is no notification shade to pull down and no back/home/recents bar. To restore them during development:

ItempApiPub.setStatusBarShow(context);
ItempApiPub.setNavigationBarShow(context);
Leave yourself a way back in — before you deploy

Once the bars are gone and installs are blocked (next layer), a hidden exit is the only way to service the device without reflashing. Build one now: a multi-tap on a corner, a long-press, a password dialog — something a passer-by will not find but a technician can use. Do this before the device leaves your bench.

Layer 3 — Block tampering​

Stop anyone installing another app or pulling files off a USB stick.

// Whitelist: only your own package may be installed or updated.
String[] allow = { "com.yourcompany.kioskapp" };
ItempApiPub.intallBlock(context, allow, ItempApiPub.WHITELIST_MODE);

// Ignore USB mass storage entirely.
ItempApiPub.setUsbStorageBlock(context, true);

intallBlock is spelled exactly that way in the API — see Kiosk and lockdown. Whitelist mode is the strong choice for a fixed-function device: nothing but your app gets on.

To lift the lock during servicing:

ItempApiPub.intallBlock(context, null, ItempApiPub.DISABLED_MODE);
ItempApiPub.setUsbStorageBlock(context, false);

Layer 4 — Recover from freezes and leaks​

Two independent safety nets. A nightly reboot clears slow memory leaks before they matter; the hardware watchdog catches a hard freeze the same night.

// Reboot every night at 04:00, when nobody is using it.
ItempApiPub.setRebootTime(context, "4", "0", true);

The scheduled reboot above is the recovery mechanism the device API provides directly. For a hard freeze between reboots, a hardware watchdog — where the board resets if it is not periodically "fed" — is the stronger net. On KTM boards the watchdog is a platform feature rather than an ItempApiPub call; confirm availability and the feed mechanism for your board with your account manager. If you use one, feed it from your main work loop, never from a timer — a timer keeps feeding while the app itself is frozen:

while (running) {
doWork();
updateUi();
// feed the watchdog here, if your board exposes one
Thread.sleep(1000);
}

See Power and scheduling for the reboot schedule.

The nightly reboot and your boot flow must agree

A 04:00 reboot only helps if Layer 1 brings your app back up cleanly afterward. Test the full cycle: let the scheduled reboot fire and confirm the device lands back in your kiosk with the bars still hidden. A reboot that drops to the launcher is worse than no reboot.

Layer 5 — Power schedule (optional but cheap)​

If the kiosk serves a business with opening hours, don't burn the panel 24/7.

// Power off at 22:00, back on at 07:30, every day.
ItempApiPub.setPowerOffTime(context, "22", "0", "0", true);
ItempApiPub.setPowerOnTime(context, "7", "30", "0", true);

Or keep the board running and just blank the screen — lighter, wakes instantly:

ItempApiPub.setBacklightEnable(context, false); // panel dark, board alive
// ...at opening...
ItempApiPub.setBacklightEnable(context, true);

Backlight-off keeps schedules and network alive; full power-off saves the most energy but needs standby power to wake. See Power and scheduling for the trade-off.

Putting it together​

A minimal kiosk setup, run once when your activity first reaches the foreground:

void lockDown(Context context) {
// hide UI
ItempApiPub.setStatusBarHide(context);
ItempApiPub.setNavigationBarHide(context);

// block tampering
ItempApiPub.intallBlock(context,
new String[]{ "com.yourcompany.kioskapp" },
ItempApiPub.WHITELIST_MODE);
ItempApiPub.setUsbStorageBlock(context, true);

// recovery
ItempApiPub.setRebootTime(context, "4", "0", true);

// hours (optional)
ItempApiPub.setPowerOffTime(context, "22", "0", "0", true);
ItempApiPub.setPowerOnTime(context, "7", "30", "0", true);
}

Layer 1 (boot receiver) and the watchdog feed loop live outside this method — boot in the manifest, watchdog in your work loop.

Before you ship — the field checklist​

  • Hidden exit works and survives lockdown (you can get back in)
  • Power-cut test: pull power, restore, device returns to the kiosk unattended
  • Scheduled reboot lands back in the kiosk, bars still hidden
  • If using a hardware watchdog: it resets on a simulated freeze
  • USB stick is ignored; a second APK cannot install
  • Backlight/power schedule fires at the right local time (check the system clock)