Android Data and Device Capabilities
SDK Version: 1.0.0
Package:com.xtalk.mesh.sdk.ble
Except for image transcoding, these APIs require successful ensureInitialized(); send APIs also require connection, Auth, and Init. Invoke blocking/device-waiting methods on Dispatchers.IO. Treat only the explicit success member of a delivered result enum as success.
1. Binary and RF
| API | Use | Result semantics |
|---|---|---|
sendBinaryFrame(data) | Normal binary business frame | SendResult; empty/length/state/link errors are enum outcomes |
sendRfPayloadAndWaitSendFinish(rawPayload, timeoutMs) | Device completion required | true only after send completion within the deadline |
sendRfPayloadNoWait(rawPayload) | Realtime voice/control | Submission only; empty payload is false; caller rate-limits |
Prefer the waited operation for reliable traffic. Use no-wait only for a loss-tolerant, rate-controlled realtime stream. Never overlap with Auth, Init, or custom AT.
2. Raw AT and passthrough ownership (Advanced)
| API | Contract |
|---|---|
runAtCommand(...) | Exclusive radio lock and response lines; see API Reference |
sendAtCommand(command) | SendResult, without response lines |
sendAtCommandNoWait(command) | Write submission only |
sendEncryptedAt(bytes) | Bytes already encoded by the delivered AT protocol; true on submission |
setPassthroughListener(listener) | Installs the single low-level passthrough owner; null releases it; may interfere with runAtCommand |
withWirelessOpLock(block) | Serializes an advanced customer transaction with Auth/Init/AT; never wait recursively on the same lock |
Use BleAtErrorPolicy.COLLECT_UNTIL_COMPLETE only with a clear stopWhen. When drainResponseTailAfterStop = true, stopWhen is mandatory and the SDK retains the listener/lock through a terminal line or original deadline.
3. Text and data reception
private val textListener = TextReceivedCallback { sourceId, text, snr, rssi ->
// Dispatch UI work to the main thread.
}
private val dataListener = DataReceivedCallback { bytes, length, snr, rssi ->
val payload = bytes.copyOf(length.coerceIn(0, bytes.size))
}
XTalkBleClient.addTextListener(textListener)
XTalkBleClient.addDataListener(dataListener)
val result = XTalkBleClient.sendText("hello")
XTalkBleClient.removeTextListener(textListener)
XTalkBleClient.removeDataListener(dataListener)
sendText returns SendResult. Data callbacks run on the high-frequency I/O path; consume only 0 until length and return quickly. Text callbacks include source ID, text, SNR, and RSSI.
4. File transfer
private val sendListener = FileSendCallback { progress, sent, total, result -> }
private val receiveListener = FileReceiveCallback { progress, received, total, result, bytes ->
if (bytes != null) savePrivately(bytes)
}
XTalkBleClient.addFileSendListener(sendListener)
XTalkBleClient.addFileReceiveListener(receiveListener)
val accepted = XTalkBleClient.sendFile(fileBytes)
XTalkBleClient.cancelFileSend()
XTalkBleClient.cancelFileReceive()
XTalkBleClient.removeFileSendListener(sendListener)
XTalkBleClient.removeFileReceiveListener(receiveListener)
Send/cancel SendResult values describe the request; final progress and outcome come from callbacks. The customer owns file selection, size checks, storage, and privacy. Run one channel-owning file/AT/Auth/Init operation at a time. Restore text/PTT defaults after completion or cancellation when a mode was changed.
5. PTT and realtime voice
Runtime RECORD_AUDIO permission is required.
| API | Parameters/defaults | Lifecycle |
|---|---|---|
startPttVoiceCapture(enablePcmCallback = true) | Local PCM callback toggle | Pair with stopPttVoiceCapture() |
startRealtimeVoiceCapture(peopleCount = 2, mute = 0) | Participant count and mute flag | Pair with stopRealtimeVoiceCapture() |
stopVoiceCaptureLocal() | None | Local-only abnormal/fast cleanup |
setRealtimeWorkModeOverride(workMode) | null clears | Set before and clear after the session |
getRealtimeWorkModeOverride() | None | Current override or null |
Register VoiceReceivedCallback and VoiceCaptureCallback with their matching add/remove pairs. Copy only the reported PCM length. Voice callbacks are realtime paths: do not perform file I/O, network calls, or blocking UI work.
6. PCM playback
startVoicePlayback(pcm) and stopVoicePlayback() return PlaybackStartResult and PlaybackStopResult. Input must match the PCM format in the delivery contract. Inspect the enum result; do not infer success from elapsed time.
7. Image transcoding
val output = XTalkBleClient.transcodeImage(
imageBytes = encodedImage,
targetTier = targetTier,
inputFormat = null, // auto-detect
)
This is an offline CPU operation and needs no BLE/Auth/Init/audio permission. Run large images off the main thread. Inspect the delivered ImageTranscodeResult success state before using output bytes.
8. 16-byte key
require(key.size == 16)
check(XTalkBleClient.setCryptoKey16(key))
key.fill(0)
On false, do not continue encrypted traffic. Never log, send to analytics, or persist the plaintext key.
9. Radio settings
| API | Difference |
|---|---|
setChannelFrequency(freqHz, timeoutMs = 3000) | Waits for wireless-config channel callback |
setFrequencyHz(freqHz, timeoutMs = 3000) | AT command sets all four frequency slots |
setRateMode(rateMode) | Coerces into 0..255; device support is still determined by the result |
restoreTextPttDefaults(rate = 7, addtl = 1, work = 21) | Restores all three values; succeeds only when all do |
Use only project/region-approved frequencies. Stop traffic and query actual state after a failed setting; do not retry forever.
10. Hardware, firmware, battery, and management events
getHardwareVersion(2000), getFirmwareVersion(2000), and getBatteryLevel(4000) wait for device results and return null for failure, timeout, or unsupported operations. Successful values are cached until disconnect. A DeviceManageCallback can observe asynchronous management values; cast value based on type and remove the listener during cleanup. Do not invent an extra battery range/unit beyond the device-reported integer.
11. Listener pairs
| Add | Remove | Callback/thread |
|---|---|---|
addListener | removeListener | Scan/connection state; main-thread fanout |
addDataListener | removeDataListener | Binary/realtime data; I/O callback thread |
addDeviceManageListener | removeDeviceManageListener | Versions/battery; main-thread fanout |
addTextListener | removeTextListener | Text; main-thread fanout |
addVoiceListener | removeVoiceListener | Remote PCM; realtime callback thread |
addVoiceCaptureListener | removeVoiceCaptureListener | Local PCM; main-thread fanout |
addFileSendListener | removeFileSendListener | Send progress; main-thread fanout |
addFileReceiveListener | removeFileReceiveListener | Receive progress/final bytes; main-thread fanout |
The SDK strongly retains listeners. Remove the same instance to prevent duplicate callbacks and leaked Activity/ViewModel lifetimes.