Skip to main content

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

APIUseResult semantics
sendBinaryFrame(data)Normal binary business frameSendResult; empty/length/state/link errors are enum outcomes
sendRfPayloadAndWaitSendFinish(rawPayload, timeoutMs)Device completion requiredtrue only after send completion within the deadline
sendRfPayloadNoWait(rawPayload)Realtime voice/controlSubmission 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)

APIContract
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.

APIParameters/defaultsLifecycle
startPttVoiceCapture(enablePcmCallback = true)Local PCM callback togglePair with stopPttVoiceCapture()
startRealtimeVoiceCapture(peopleCount = 2, mute = 0)Participant count and mute flagPair with stopRealtimeVoiceCapture()
stopVoiceCaptureLocal()NoneLocal-only abnormal/fast cleanup
setRealtimeWorkModeOverride(workMode)null clearsSet before and clear after the session
getRealtimeWorkModeOverride()NoneCurrent 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

APIDifference
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

AddRemoveCallback/thread
addListenerremoveListenerScan/connection state; main-thread fanout
addDataListenerremoveDataListenerBinary/realtime data; I/O callback thread
addDeviceManageListenerremoveDeviceManageListenerVersions/battery; main-thread fanout
addTextListenerremoveTextListenerText; main-thread fanout
addVoiceListenerremoveVoiceListenerRemote PCM; realtime callback thread
addVoiceCaptureListenerremoveVoiceCaptureListenerLocal PCM; main-thread fanout
addFileSendListenerremoveFileSendListenerSend progress; main-thread fanout
addFileReceiveListenerremoveFileReceiveListenerReceive progress/final bytes; main-thread fanout

The SDK strongly retains listeners. Remove the same instance to prevent duplicate callbacks and leaked Activity/ViewModel lifetimes.

API Reference · Errors and FAQ