Every Android scanning integration eventually asks the same question: does this need an SDK, or will keyboard-wedge input do? The answer isn't about scan volume or device brand — it's about whether the app needs anything beyond "a string appeared in a text field."
What the decision actually hinges on
Keyboard-wedge mode makes a scanner emulate a keyboard — decoded data gets typed into whatever field has focus, with a suffix character standing in for pressing Enter. It requires zero app-side integration code, which is exactly why it gets chosen by default, and exactly why it breaks down as soon as an app needs more than that.
What the docs don't tell you
Wedge mode has no concept of which app, or which field within an app, should receive the data — it types into whatever currently has keyboard focus, full stop. On a device with an on-screen keyboard also present, a scan can trigger IME autocomplete/autocorrect behavior mid-entry, corrupting the string before the suffix character even arrives. This is rarely caught in testing because test scans usually happen with the right field deliberately focused and no on-screen keyboard competing for the input.
Decision table
| Requirement | Keyboard wedge sufficient | Needs SDK / DataWedge intents |
|---|---|---|
| Scan lands in exactly one always-focused field | Yes | — |
| Need RSSI, read count, or timestamp per scan | No | Yes |
| Multiple tags/barcodes per trigger pull | No | Yes |
| Scanning while app is backgrounded or screen is off | No | Yes |
| No on-screen keyboard ever present during scanning | Yes, safely | — |
| Scan needs to route to a specific field, not "whatever has focus" | No | Yes (or DataWedge intent routing) |
| Zero app-side integration effort required | Yes | No |
| App needs to distinguish scan source (RFID vs. barcode) | No | Yes |
Hidden costs of wedge mode
Wedge mode's simplicity is real, but it isn't free — the cost shows up operationally, not during development.
- Focus stealing. Any UI element that steals focus during a scan — a toast, a dialog, a keyboard popping up — silently redirects scan data into the wrong place. There's no error; the data just lands somewhere unintended.
- IME conflicts. On devices where an on-screen keyboard is present alongside the physical/wedge scanner, autocomplete and autocorrect can alter the scanned string before the suffix character commits it.
- No metadata. RSSI, antenna, read timestamp, and duplicate-read count are all lost. Wedge mode delivers a string and nothing else — which is a hard blocker for any RFID use case where signal strength or proximity actually matters.
- No control over scan behavior. Continuous scanning, multi-tag capture, and triggered-vs-continuous modes are configured on the device itself (if at all), not from the app — the app has no way to programmatically start or stop a scan session.
DataWedge as the middle path
Zebra devices (and several other Android handheld vendors that ship similar middleware) support broadcasting scan data as a structured Android Intent instead of, or in addition to, keyboard-wedge output. This keeps the "no SDK integration" simplicity while removing the focus-dependency problem entirely.
class ScanReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == "com.example.app.SCAN") {
val data = intent.getStringExtra("com.symbol.datawedge.data_string")
val labelType = intent.getStringExtra("com.symbol.datawedge.label_type")
// Route directly to the intended handler — no focused view required
onScanReceived(data, labelType)
}
}
}Register the intent filter and configure the DataWedge profile (via the DataWedge Configuration app or the DataWedge Intent API) to associate that specific package and action with the scanner's output.
<receiver android:name=".ScanReceiver" android:exported="true">
<intent-filter>
<action android:name="com.example.app.SCAN" />
</intent-filter>
</receiver>This removes the focus-stealing and IME-conflict failure modes entirely — the scan data arrives at a receiver, not a text field — while still not requiring a vendor SDK dependency or a custom reader-management layer.
When to skip both and go straight to an SDK
Multi-tag UHF inventory, RSSI-based proximity logic, or any scenario needing programmatic control over scan sessions (start/stop from app logic, continuous background scanning) all require a full SDK integration — neither wedge mode nor DataWedge intents expose that level of control. See the device-specific SDK guides for Chainway and Zebra hardware for what that integration actually looks like.
Production considerations
- Default to DataWedge-style intents over raw keyboard wedge whenever the hardware supports it — the integration cost is close to zero and it removes an entire class of field-focus bugs.
- If wedge mode is truly the right fit (single always-focused field, no metadata need), disable the on-screen keyboard for that field specifically to eliminate the IME-conflict failure mode.
- Never assume a wedge-mode integration will silently keep working as an app grows more screens — the moment a second focusable field or a modal dialog enters the flow, the focus-stealing risk reappears.
Common errors
| Error | Cause | Fix |
|---|---|---|
| Scanned data appears in the wrong field | Focus was on an unintended view when the scan committed | Ensure the intended field is guaranteed-focused before a scan, or migrate to DataWedge intent routing |
| Scanned string has garbled or autocorrected characters | On-screen keyboard's IME intercepted characters mid-entry | Disable IME suggestions/autocorrect on the target field, or move to intent-based scan delivery |
| App can't tell how many times a tag was read | Wedge mode delivers a string only, no read-count metadata | Move to SDK-based integration for any use case needing read count or RSSI |
| Scanning does nothing while app is backgrounded | Wedge mode requires a focused foreground field by definition | Use SDK-based background scanning if the use case requires it — wedge mode fundamentally cannot support this |