Before you start
Keep the first test small and repeatable.
- The exact device model, region variant, Android build, firmware and approved SDK release.
- A deployment policy that distinguishes read-only inspection from administrator-level controls.
- A recovery path that does not depend on the key, status-bar or application setting being changed.
Step by step
Build it in 4 deliberate passes.
Each pass produces a checkable result. Keep device-specific calls in the adapter and keep the workflow portable.
- 01
Capture a versioned capability snapshot
Record model, region, Android version, security patch, firmware, SDK, application build, accessories and available peripherals. A product family name is not enough to reproduce a deployment result.
- 02
Separate inspection from privileged control
Keep identity, software version and capability reads available to a diagnostic screen. Treat status-bar, network profile, kiosk, application installation and similar operations as administrator-controlled deployment actions with an allowlist and audit record.
- 03
Make hardware input changes reversible
Prefer application-level key handling. When a deployment must change a physical mapping, snapshot the original key code, action and interception state before applying one change at a time.
- 04
Gate, verify and restore
Run the target workflow, reboot and repeat the check. Store the before/after result and limitation, then restore the original state or keep the approved deployment record with a physical recovery procedure.
Copyable pattern / Kotlin
Start with the boundary, then bind the device.
Original port pattern. Bind it to the approved device SDK inside a private adapter; keep privileged calls out of the application workflow layer.
enum class DeviceCapability {
BARCODE, PRINTER, PHYSICAL_KEYS,
MAGNETIC_STRIPE, CONTACT_CARD,
CONTACTLESS_CARD, SECURE_MODULE,
}
data class DeviceBaseline(
val model: String,
val region: String,
val android: String,
val firmware: String,
val sdk: String,
val appBuild: String,
val capabilities: Set<DeviceCapability>,
)
data class KeySnapshot(
val keyCode: Int,
val action: String?,
val intercepted: Boolean,
)
interface DeviceCapabilityPort {
fun readBaseline(): DeviceBaseline
fun snapshotKey(keyCode: Int): KeySnapshot?
fun applyKeyAction(keyCode: Int, action: String)
fun restoreKey(snapshot: KeySnapshot)
}
class DeploymentInspector(
private val device: DeviceCapabilityPort,
) {
fun inspect(): DeviceBaseline = device.readBaseline()
fun applyTemporaryKey(
keyCode: Int,
action: String,
) {
val original = device.snapshotKey(keyCode)
?: error("key-mapping-unavailable")
try {
device.applyKeyAction(keyCode, action)
} catch (error: Throwable) {
device.restoreKey(original)
throw error
}
}
}When the happy path breaks
Make recovery part of the first implementation.
Operators experience the failure state, not the API call. Translate device signals into a useful next action.
Mark the deployment not-ready and request a model-specific diagnostic instead of filling the gap from a nearby variant.
Keep the read-only result, record the required administrator scope and do not retry with broader permissions.
Mark it session-only, restore the original mapping and move persistence into the approved deployment profile.
Use the physical recovery procedure, restore the snapshot and remove the change from the rollout.
Before you ship
Use this checklist on the target configuration.
- 01
Record model, region, Android, firmware, SDK, application build and accessories before the test.
- 02
Run the read-only capability viewer after cold start, app restart and reboot.
- 03
Execute privileged controls only with an approved deployment policy and record the permission boundary.
- 04
Verify key restore, system navigation, persistence behavior and the physical recovery path.
Further reading
Use platform guidance for the parts the device SDK does not own.
These references cover Android lifecycle, broadcast, testing and architecture patterns. Device-specific compatibility still needs a model-level validation record.