Add Frontdesk kiosk APK build script and manufacturer flash guide.
Deploy Ladill Frontdesk / deploy (push) Successful in 59s
Deploy Ladill Frontdesk / deploy (push) Successful in 59s
Ship OEM documentation for MDM, Elo, and Zebra lockdown plus a provisioning QR on kiosk device registration so factory tablets can pair on first boot. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -8,6 +8,7 @@ use App\Models\Branch;
|
||||
use App\Models\Device;
|
||||
use App\Models\ReceptionDesk;
|
||||
use App\Services\Frontdesk\DeviceService;
|
||||
use App\Services\Frontdesk\QrCodeService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
@@ -97,7 +98,7 @@ class DeviceController extends Controller
|
||||
return redirect()->route('frontdesk.devices.index')->with('success', 'Device registered.');
|
||||
}
|
||||
|
||||
public function edit(Request $request, Device $device): View
|
||||
public function edit(Request $request, Device $device, QrCodeService $qrCodes): View
|
||||
{
|
||||
$this->authorizeAbility($request, 'devices.manage');
|
||||
$this->authorizeOwner($request, $device);
|
||||
@@ -107,6 +108,9 @@ class DeviceController extends Controller
|
||||
'deviceTypes' => config('frontdesk.device_types'),
|
||||
'branches' => $this->branches($request, $device->organization_id),
|
||||
'desks' => $this->desks($request, $device->organization_id),
|
||||
'kioskQrSvg' => $device->type === 'kiosk' && $device->device_token
|
||||
? $qrCodes->kioskSvg($device->device_token, 220)
|
||||
: null,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,16 @@ class QrCodeService
|
||||
return $this->renderSvg($this->employeeUrl($employee), $size);
|
||||
}
|
||||
|
||||
public function kioskUrl(string $deviceToken): string
|
||||
{
|
||||
return route('frontdesk.kiosk.device', $deviceToken);
|
||||
}
|
||||
|
||||
public function kioskSvg(string $deviceToken, int $size = 200): string
|
||||
{
|
||||
return $this->renderSvg($this->kioskUrl($deviceToken), $size);
|
||||
}
|
||||
|
||||
protected function renderSvg(string $url, int $size = 200): string
|
||||
{
|
||||
$options = new QROptions([
|
||||
|
||||
@@ -0,0 +1,319 @@
|
||||
# Ladill Frontdesk Kiosk — Manufacturer Flash Guide
|
||||
|
||||
This guide is for OEM partners flashing Ladill visitor-kiosk tablets before shipment. It covers APK installation, kiosk lockdown, and customer provisioning.
|
||||
|
||||
## Package summary
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| App name | Ladill Frontdesk Kiosk |
|
||||
| Package ID | `com.ladill.frontdesk.kiosk` |
|
||||
| Min Android | 8.0 (API 26) |
|
||||
| Target Android | 15 (API 35) |
|
||||
| Default server | `https://frontdesk.ladill.com` |
|
||||
| Factory admin PIN | `462834` (change after first provision) |
|
||||
|
||||
## Files you receive
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `ladill-frontdesk-kiosk-1.0.0.apk` | Signed release APK to flash on each device |
|
||||
| This guide | Flash, lockdown, and QA checklist |
|
||||
|
||||
Forty8Tech builds the APK with:
|
||||
|
||||
```bash
|
||||
./scripts/build-kiosk-apk.sh
|
||||
```
|
||||
|
||||
Output path: `apps/android/dist/ladill-frontdesk-kiosk-<version>.apk`
|
||||
|
||||
The Android source tree lives under `apps/android/` locally and is not committed to git. Distribute the built APK to manufacturers directly (USB, SFTP, or MDM bundle).
|
||||
|
||||
---
|
||||
|
||||
## End-to-end flow
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[Flash APK] --> B[Set device owner / MDM]
|
||||
B --> C[Pin as HOME launcher]
|
||||
C --> D[Customer registers kiosk in Frontdesk]
|
||||
D --> E[Scan provisioning QR on tablet]
|
||||
E --> F[Kiosk runs fullscreen]
|
||||
```
|
||||
|
||||
1. **Factory:** Install APK, apply kiosk policy, set app as default HOME.
|
||||
2. **Customer:** Registers a Visitor Kiosk under Ladill Frontdesk → Devices.
|
||||
3. **Field / factory QA:** Scan the provisioning QR shown on the device edit screen.
|
||||
4. **Runtime:** Tablet loads the web kiosk, sends heartbeats, and stays locked.
|
||||
|
||||
---
|
||||
|
||||
## 1. Generic pre-flash checklist
|
||||
|
||||
Before flashing a batch:
|
||||
|
||||
- [ ] Tablet is factory-reset (recommended for device-owner provisioning).
|
||||
- [ ] Wi-Fi or Ethernet works; device can reach `https://frontdesk.ladill.com`.
|
||||
- [ ] Date/time and timezone are correct (TLS and session cookies depend on this).
|
||||
- [ ] Screen stays on when plugged in (disable aggressive battery saver).
|
||||
- [ ] You have the signed APK for the target build version.
|
||||
|
||||
### Install APK (ADB)
|
||||
|
||||
```bash
|
||||
adb install -r ladill-frontdesk-kiosk-1.0.0.apk
|
||||
```
|
||||
|
||||
For system-privileged installs (some OEM images):
|
||||
|
||||
```bash
|
||||
adb root
|
||||
adb remount
|
||||
adb push ladill-frontdesk-kiosk-1.0.0.apk /system/priv-app/LadillFrontdeskKiosk/LadillFrontdeskKiosk.apk
|
||||
adb shell chmod 644 /system/priv-app/LadillFrontdeskKiosk/LadillFrontdeskKiosk.apk
|
||||
adb reboot
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Android Device Owner (generic MDM)
|
||||
|
||||
Device Owner mode is required for true kiosk lock (block Home, Recents, status bar). Use this for custom tablets or any MDM that supports Android Enterprise.
|
||||
|
||||
### 2.1 Provision device owner via MDM (recommended)
|
||||
|
||||
Device must have **no Google accounts** and ideally be fresh out of reset.
|
||||
|
||||
Use your MDM’s **Android Enterprise device-owner** provisioning (QR, NFC, zero-touch, or StageNow). Assign `com.ladill.frontdesk.kiosk` as the **kiosk / lock-task** application.
|
||||
|
||||
The current APK uses immersive fullscreen, HOME launcher registration, and `startLockTask()` when the OS allows it. For strict device-owner policies (block Settings, prevent uninstall, silent install), provision through your EMM—do not rely on manual ADB unless your OEM documents a supported path.
|
||||
|
||||
> Need a build with a bundled `DeviceAdminReceiver` for `dpm set-device-owner`? Contact Forty8Tech for an OEM white-label package.
|
||||
|
||||
### 2.2 MDM policy (any EMM)
|
||||
|
||||
Configure these policies for `com.ladill.frontdesk.kiosk`:
|
||||
|
||||
| Policy | Setting |
|
||||
|--------|---------|
|
||||
| Kiosk / lock-task app | `com.ladill.frontdesk.kiosk` |
|
||||
| Single app mode | Enabled |
|
||||
| Default launcher | `com.ladill.frontdesk.kiosk` |
|
||||
| Stay on launcher | Enabled |
|
||||
| Status bar | Hidden or restricted |
|
||||
| System navigation | Disabled |
|
||||
| Auto-launch on boot | Enabled |
|
||||
| Allowlist URLs | `*.ladill.com` |
|
||||
| Camera | Allowed |
|
||||
| Microphone | Allowed |
|
||||
| Install unknown apps | Disabled |
|
||||
| Factory reset | PIN-protected |
|
||||
|
||||
### 2.3 Set as default HOME launcher
|
||||
|
||||
After first launch:
|
||||
|
||||
1. Press Home (if visible during setup).
|
||||
2. Choose **Ladill Frontdesk Kiosk**.
|
||||
3. Select **Always**.
|
||||
|
||||
Or via ADB:
|
||||
|
||||
```bash
|
||||
adb shell cmd package set-home-activity com.ladill.frontdesk.kiosk/.MainActivity
|
||||
```
|
||||
|
||||
### 2.4 Boot behavior
|
||||
|
||||
The APK registers for `BOOT_COMPLETED` and starts automatically. Confirm:
|
||||
|
||||
```bash
|
||||
adb shell am start -n com.ladill.frontdesk.kiosk/.MainActivity
|
||||
adb reboot
|
||||
# After boot, kiosk setup or web UI should appear without manual launch
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Elo Touch Solutions
|
||||
|
||||
Typical on Elo I-Series and Open Frame Android panels with **EloView** or **Elo Access**.
|
||||
|
||||
### 3.1 EloView (cloud)
|
||||
|
||||
1. Add device to your EloView account.
|
||||
2. Upload `ladill-frontdesk-kiosk-1.0.0.apk` as a managed app.
|
||||
3. Create a **Kiosk** profile:
|
||||
- **Primary app:** Ladill Frontdesk Kiosk (`com.ladill.frontdesk.kiosk`)
|
||||
- **Mode:** Single app / lock task
|
||||
- **Auto launch:** On boot
|
||||
- **Navigation bar:** Hidden
|
||||
- **Power button:** Map to sleep only (not exit kiosk)
|
||||
4. Allow **Camera** and **Microphone** in the profile (visitor photo + QR checkout).
|
||||
5. Push profile to device group before shipment.
|
||||
|
||||
### 3.2 Elo device settings (on-device)
|
||||
|
||||
1. Settings → **Elo Device Settings** → **Home App** → Ladill Frontdesk Kiosk.
|
||||
2. Enable **Start on boot**.
|
||||
3. Disable **Android Settings access** for field users.
|
||||
4. Set **Display timeout** to maximum; keep **USB power** connected in lobby installs.
|
||||
|
||||
### 3.3 Elo QA
|
||||
|
||||
- [ ] App survives power cycle.
|
||||
- [ ] No browser chrome visible.
|
||||
- [ ] Camera preview works on check-in photo step.
|
||||
- [ ] QR scanner works on checkout step.
|
||||
|
||||
---
|
||||
|
||||
## 4. Zebra Technologies
|
||||
|
||||
Typical on ET40, ET45, TC series, and custom Zebra Android builds with **StageNow** and **MX**.
|
||||
|
||||
### 4.1 StageNow barcode (recommended)
|
||||
|
||||
1. Open **StageNow** on a PC.
|
||||
2. Create a **Setup** profile:
|
||||
- Install APK from `file://` path or download URL (host APK on your CDN).
|
||||
- Set **Default Launcher** to `com.ladill.frontdesk.kiosk`.
|
||||
- Enable **Mx/kiosk mode** → single app = Ladill Frontdesk Kiosk.
|
||||
3. Export profile as a barcode.
|
||||
4. Scan on factory line during device setup.
|
||||
|
||||
### 4.2 MX KeyManager / AppMgr
|
||||
|
||||
| MX setting | Value |
|
||||
|------------|-------|
|
||||
| `AppMgr` install | `ladill-frontdesk-kiosk-1.0.0.apk` |
|
||||
| `KioskMode` enabled | `true` |
|
||||
| `KioskMode` package | `com.ladill.frontdesk.kiosk` |
|
||||
| `UiMgr` hide status bar | `true` |
|
||||
| `PowerMgr` stay awake on AC | `true` |
|
||||
|
||||
### 4.3 Zebra DataWedge (optional)
|
||||
|
||||
The kiosk uses the **web** QR scanner (`html5-qrcode`) for badge checkout. DataWedge is **not required**. If you remap a hardware scan trigger, ensure it does not steal focus from the WebView during checkout.
|
||||
|
||||
### 4.4 Zebra QA
|
||||
|
||||
- [ ] StageNow profile applies on clean device.
|
||||
- [ ] Lock task survives suspend/resume.
|
||||
- [ ] Wi-Fi roaming does not drop kiosk session.
|
||||
|
||||
---
|
||||
|
||||
## 5. Customer provisioning (after flash)
|
||||
|
||||
The tablet ships **unlinked** until the customer pairs it.
|
||||
|
||||
### 5.1 Customer steps (Ladill Frontdesk admin)
|
||||
|
||||
1. Sign in to [Frontdesk](https://frontdesk.ladill.com).
|
||||
2. Go to **Devices → Add device**.
|
||||
3. Type: **Visitor Kiosk**.
|
||||
4. Save. Open the device → note the **Provision Ladill Kiosk app** QR code.
|
||||
|
||||
### 5.2 On-tablet steps
|
||||
|
||||
1. Power on tablet; Ladill Frontdesk Kiosk opens to **Provision kiosk**.
|
||||
2. Tap **Show QR scanner** and scan the QR from Frontdesk.
|
||||
- Or paste the device token / full kiosk URL manually.
|
||||
3. Tap **Start kiosk**. The visitor check-in UI loads.
|
||||
|
||||
Provisioning URL format:
|
||||
|
||||
```
|
||||
https://frontdesk.ladill.com/kiosk/d/{device_token}
|
||||
```
|
||||
|
||||
Deep link (also supported):
|
||||
|
||||
```
|
||||
ladillfrontdesk://kiosk/{device_token}
|
||||
```
|
||||
|
||||
### 5.3 Verify online status
|
||||
|
||||
In Frontdesk → Devices, the kiosk should show **Online** within a few minutes (heartbeat every 5 minutes, plus activity on page load).
|
||||
|
||||
---
|
||||
|
||||
## 6. Admin access (factory and field service)
|
||||
|
||||
Hidden admin panel for re-provision, reload, and PIN change:
|
||||
|
||||
1. Tap the **top-left corner 7 times** within 2 seconds.
|
||||
2. Enter admin PIN (factory default: `462834`).
|
||||
3. Options: reload kiosk, re-provision, change PIN, exit admin.
|
||||
|
||||
**Change the factory PIN** before shipping to end customers, or document that the customer must change it during provisioning QA.
|
||||
|
||||
---
|
||||
|
||||
## 7. Security and signing
|
||||
|
||||
| Item | Guidance |
|
||||
|------|----------|
|
||||
| Factory keystore | Replace before mass production; do not ship factory passwords to end customers. |
|
||||
| APK signature | All devices in a SKU should use the same release key for OTA updates. |
|
||||
| Network | HTTPS only; app blocks mixed content. |
|
||||
| Token storage | Device token is stored in EncryptedSharedPreferences on-device. |
|
||||
| Token rotation | If customer regenerates token in Frontdesk, re-scan QR or re-provision. |
|
||||
|
||||
---
|
||||
|
||||
## 8. Factory QA checklist (per device)
|
||||
|
||||
| # | Test | Pass |
|
||||
|---|------|------|
|
||||
| 1 | APK installs without error | ☐ |
|
||||
| 2 | App is default HOME launcher | ☐ |
|
||||
| 3 | Boots directly into Ladill app after cold start | ☐ |
|
||||
| 4 | Home / Recents blocked in kiosk mode | ☐ |
|
||||
| 5 | Provisioning QR scan links device | ☐ |
|
||||
| 6 | Visitor welcome screen loads | ☐ |
|
||||
| 7 | Camera permission prompt accepted; photo step works | ☐ |
|
||||
| 8 | Device shows Online in Frontdesk | ☐ |
|
||||
| 9 | Admin PIN changed from factory default | ☐ |
|
||||
| 10 | Device serial / IMEI recorded on build sheet | ☐ |
|
||||
|
||||
---
|
||||
|
||||
## 9. Troubleshooting
|
||||
|
||||
| Symptom | Likely cause | Fix |
|
||||
|---------|--------------|-----|
|
||||
| “Device token required” / 404 | Invalid or revoked token | Re-scan QR from Frontdesk Devices |
|
||||
| Stuck on setup screen | No network | Connect Wi-Fi; verify `frontdesk.ladill.com` reachable |
|
||||
| Camera not working | Permission denied | Re-grant camera in admin → reload; check MDM camera policy |
|
||||
| Device shows Offline | Network or heartbeat blocked | Allow `POST /api/devices/heartbeat`; disable battery optimization for app |
|
||||
| User can exit to Settings | Lock task not active | Apply MDM kiosk policy; set device owner |
|
||||
| White screen after provision | TLS or DNS issue | Check date/time; verify HTTPS certificate trust |
|
||||
| Regenerated token | Old token invalid | Re-provision from admin panel or scan new QR |
|
||||
|
||||
### Useful ADB commands
|
||||
|
||||
```bash
|
||||
# Logs
|
||||
adb logcat -s LadillFrontdeskKiosk
|
||||
|
||||
# Clear app data (forces re-provision)
|
||||
adb shell pm clear com.ladill.frontdesk.kiosk
|
||||
|
||||
# Check lock task state
|
||||
adb shell dumpsys activity activities | grep mLockTaskMode
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Contact
|
||||
|
||||
For white-label APK signing, device-admin receiver builds, or OEM-specific MX/Elo profiles:
|
||||
|
||||
**Forty8Tech / Ladill** — hardware@ladill.com
|
||||
|
||||
Include: tablet model, Android version, MDM platform, batch size, and target market.
|
||||
@@ -41,6 +41,13 @@
|
||||
<code class="mt-1 block break-all text-xs text-slate-700">{{ $device->device_token }}</code>
|
||||
@if ($device->type === 'kiosk')
|
||||
<a href="{{ route('frontdesk.kiosk.device', $device->device_token) }}" target="_blank" class="mt-2 inline-block text-sm text-indigo-700 hover:underline">Open kiosk URL</a>
|
||||
@if (! empty($kioskQrSvg))
|
||||
<div class="mt-4 rounded-xl border border-slate-200 bg-white p-4 text-center">
|
||||
<p class="text-sm font-medium text-slate-900">Provision Ladill Kiosk app</p>
|
||||
<p class="mt-1 text-xs text-slate-500">Scan with the tablet on first boot to link this device.</p>
|
||||
<div class="mx-auto mt-3 inline-block">{!! $kioskQrSvg !!}</div>
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
ANDROID_DIR="$ROOT/apps/android"
|
||||
OUTPUT_DIR="$ANDROID_DIR/dist"
|
||||
KEYSTORE_FILE="$ANDROID_DIR/.factory-release.keystore"
|
||||
KEYSTORE_PROPS="$ANDROID_DIR/keystore.properties"
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
if [[ ! -f "$KEYSTORE_PROPS" ]]; then
|
||||
if [[ ! -f "$KEYSTORE_FILE" ]]; then
|
||||
echo "Generating factory release keystore at $KEYSTORE_FILE"
|
||||
keytool -genkeypair \
|
||||
-alias ladill-frontdesk-kiosk \
|
||||
-keyalg RSA \
|
||||
-keysize 4096 \
|
||||
-validity 10000 \
|
||||
-keystore "$KEYSTORE_FILE" \
|
||||
-storepass "change-me-before-production" \
|
||||
-keypass "change-me-before-production" \
|
||||
-dname "CN=Ladill Frontdesk Kiosk, OU=Hardware, O=Forty8Tech, L=Accra, ST=Greater Accra, C=GH"
|
||||
fi
|
||||
|
||||
cp "$ANDROID_DIR/keystore.properties.example" "$KEYSTORE_PROPS"
|
||||
fi
|
||||
|
||||
if [[ -z "${ANDROID_HOME:-}" && -d "$HOME/Library/Android/sdk" ]]; then
|
||||
export ANDROID_HOME="$HOME/Library/Android/sdk"
|
||||
fi
|
||||
|
||||
if [[ -z "${JAVA_HOME:-}" ]]; then
|
||||
if /usr/libexec/java_home -v 17 >/dev/null 2>&1; then
|
||||
export JAVA_HOME="$(/usr/libexec/java_home -v 17)"
|
||||
fi
|
||||
fi
|
||||
|
||||
cd "$ANDROID_DIR"
|
||||
./gradlew --no-daemon clean assembleRelease
|
||||
|
||||
APK_SRC="$ANDROID_DIR/app/build/outputs/apk/release/app-release.apk"
|
||||
APK_DEST="$OUTPUT_DIR/ladill-frontdesk-kiosk-$(grep versionName app/build.gradle.kts | head -1 | sed -E 's/.*"([^"]+)".*/\1/').apk"
|
||||
|
||||
cp "$APK_SRC" "$APK_DEST"
|
||||
|
||||
echo ""
|
||||
echo "Built release APK:"
|
||||
echo " $APK_DEST"
|
||||
echo ""
|
||||
echo "Package: com.ladill.frontdesk.kiosk"
|
||||
echo "Factory admin PIN: 462834 (change from kiosk admin after provisioning)"
|
||||
echo ""
|
||||
echo "See docs/KIOSK-MANUFACTURER-FLASH.md for full OEM flash instructions."
|
||||
Reference in New Issue
Block a user