- Device Connection: Connecting to & disconnecting from Plaud devices via mobile app
- File Management: Syncing files from Plaud device to mobile app
- Firmware Updates: Updating Plaud device firmware
Prerequisites
The SDK ships native libraries for
arm64-v8a / armeabi-v7a. For testing, you must use a physical device, not an emulator.Installation
1
Clone the Plaud SDK repo
2
Copy and import the Plaud Android SDK as a dependency
The Android SDK ships as a pre-built
.aar. Copy sdk/android/plaud-sdk.aar into your app module’s libs/ directory and add it as a dependency:build.gradle
Getting Started
ImportPlaudDeviceAgent from sdk. PlaudDeviceAgent is a singleton object, so call it directly — there is no instance to construct:
Kotlin
Methods
Plaud Device SDK Initialization
The SDK is initialized with your appContext, a User Token, and your regional domain.
If you haven’t onboarded to the Plaud Developer Platform, see our quickstart onboarding steps.If you’d like more details on how to retrieve your User Token and your regional domain, see the Authentication API reference.
Kotlin
Context
required
Your application
Context (e.g. applicationContext).String
required
User Access Token (JWT), used for device authentication.
String
required
Your regional Plaud server domain without
https:// prefix. All SDK network requests use this domain.For more information on how to find your regional server domain, see the Authentication API docs.Permission Manager
BLE scanning requires runtime permissions on Android. The SDK’ssdk.permission.PermissionManager requests the full set it needs and reports the result.
Kotlin
android.app.Activity
required
Android activity
(Boolean) -> Unit
required
Receives
true only when every requested permission was granted.PermissionManager requests BLUETOOTH_SCAN, BLUETOOTH_CONNECT, ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION on API 31+, and BLUETOOTH, BLUETOOTH_ADMIN, ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION on API ≤ 30. Note that it asks for location on Android 12+ as well.Connecting (binding) to a Plaud Device
Binding a Plaud device generates a key-pair using the user token and creates an ownership lock on your users’ Plaud device. This makes sure their files on device is always encrypted and can only be decrypted with a valid user token by your application. Binding a device requires an API call to Plaud’s cloud services, so you can track device statuses remotely. And a local bind triggered by the Embedded SDK to verify and generate keys on Plaud device.1
Scan for the device
.startScan() delivers results on the bleScanResult callback defined in the PlaudDeviceAgentListener.Kotlin
2
Bind from the cloud
Registers the device/owner association in the Plaud registry. Re-binding a device to the same owner is idempotent, so multiple calls will not have side effects.
Kotlin
String
required
Device type string derived from the SN prefix (
881 → notepro, 882 → notepins).String
required
Device serial number.
A
403 response means the device is already bound to another account.3
Bind the device over BLE
Connects and generates the key-pair on the device itself. The bind result is delivered on
bleBind(sn, status, protVersion, timezone).Kotlin
BleDevice
required
A scanned device, as delivered by
bleScanResult.String
Optional second argument on the
connectBleDevice(bleDevice, deviceToken) overload — a unique identifier for that device. Omit it to connect with an empty token, which is what most integrations do.The serial number is read from the BleDevice — you do not pass it here.PlaudDeviceAgentListener Callbacks
Depair (unbind) a device
Plaud devices can only be bound to one application at a time. This is done to properly secure and encrypt files stored on a Plaud device. When a user wants to unbind a Plaud device (whether to use with another Plaud Embedded App or the core Plaud app), unbind over both cloud and BLE. Unbinding via the cloud allows you to track Connected Device statuses remotely and via API.1
Unbind from the cloud
Removes the device/owner association in the Plaud registry (visible on the Plaud developer portal). This does not require a BLE connection. Send an authenticated
POST to the partner unbind endpoint on your regional domain. Unbinding an already-unbound device is an idempotent no-op, so this is safe to call best-effort.Kotlin
String
required
Device type string derived from the SN prefix (
881 → notepro, 882 → notepins).String
required
Device serial number.
2
Depair the device over BLE
Clears the pairing/handshake on the device itself. Requires the device to be connected. On success the SDK disconnects and clears the session. The result is delivered on the
bleDepair(status: Int) listener callback.Kotlin
Boolean
Whether to also clear the device’s own stored bond list. Pass
false for the normal unbind flow — this is what the Android Starter App does. Omit the argument to call the no-arg depair() overload.Reserve clear = true for recovering a device whose on-device pairing state is stale.bleDepair is best-effort — a device that is out of range or unresponsive never answers. Pair the callback with a timeout (a few seconds) and call PlaudDeviceAgent.disconnect() either way, so the BLE link is always released.File Synchronization
TheexportAudio method exports audio files from the Plaud device to your users’ phone, reporting progress through the AudioExporter.ExportCallback.
Plaud devices will record up to 5 hours. Recordings longer should be broken up.
.getFileList accesses files on your users’ Plaud device.
Kotlin
Long
required
Session ID
File
required
Output directory
AudioExportFormat
required
PCM | WAV | OPUS | MP3. We recommend MP3 — it plays everywhere and is accepted directly by the transcription upload API.Int
Number of audio channels (
1 = mono). Optional — an overload without this argument exists.AudioExporter.ExportCallback
required
fun onProgress(progress: Int, message: String)fun onComplete(outputFile: File)For large audio files, we recommend UX considerations:
- Progress indicators and setting expectations for long transfers (i.e. “This file is large. May take ~X minutes”)
- Supporting background/resumable transfer so closing the app doesn’t kill the session.
- Using WiFi Fast Transfer (see below)
WiFi Fast Transfer
An alternative to a BLE (Bluetooth Low Energy) file transfer, WiFi Fast Transfer is ~10x faster than BLE transfers. A transfer spans two objects:PlaudDeviceAgent opens the hotspot, starts and ends the session, and decodes each recording; IWifiTransferAgent (reached with getWifiAgent()) lists and deletes files during the session.
getWifiAgent() returns IWifiTransferAgent? — it is null until the SDK has a WiFi agent to hand out. Always reach it with a safe call (getWifiAgent()?.…).1
Ask the device to open its hotspot
The device opens a WiFi hotspot on request over BLE. The credentials arrive on the
bleWiFiOpen listener callback.Kotlin
Boolean
required
true opens the device hotspot, false closes it.2
Start the transfer session
Start the session from the Returns
bleWiFiOpen callback. The SDK handles joining the hotspot and the secure handshake for you.Kotlin
String
required
Identifier for the transfer session.
IWifiTransferAgent.WifiTransferCallback
required
Drives the rest of the flow. See WifiTransferCallback below.
false if the session could not be opened.3
Wait for READY, then list files
Connection state advances
NONE → CONNECTING → CONNECTED → HANDSHAKING → READY. No file command works before READY.Kotlin
4
Export each recording
exportAudioViaWiFi takes the same arguments as exportAudio and reports on the same AudioExporter.ExportCallback, so your existing export handling works unchanged over WiFi.Kotlin
Use
exportAudioViaWiFi(...) rather than the raw downloadFile() / downloadAllFiles() path on IWifiTransferAgent. Those write undecrypted .opus bytes straight to disk; exportAudioViaWiFi runs the same decode pipeline as BLE.5
End the session
Kotlin
PlaudDeviceAgent.isWifiTransferActive() to check whether a session is currently open.
Deleting files over WiFi
IWifiTransferAgent.deleteFiles(...) removes several recordings in one call — the only batch delete in the SDK. The result arrives on onFileDeleteCompleted.
Kotlin
List<Long>
required
Session IDs of the recordings to delete from the device.
WifiTransferCallback
The WiFi Fast Transfer flow is driven by the IWifiTransferAgent.WifiTransferCallback. All members are required — there are no default implementations.While faster than BLE transfers, we still recommend the following UX considerations for WiFi Fast Transfer syncs:
- Progress indicators and setting expectations for long transfers (i.e. “This file is large. May take ~X minutes”)
- Supporting background/resumable transfer so closing the app doesn’t kill the session.
Firmware Update (OTA)
The Embedded SDK handles the entire OTA flow across three calls: version query → download → MD5 verify → CRC → BLE packet push → device restart → reconnect. Each phase reports through the FirmwareUpdateCallback.Check for Firmware Updates
Kotlin
FirmwareUpdateCallback
required
Callback that reports the check result as a
FirmwareUpdateInfo.Download Firmware Update
Kotlin
FirmwareUpdateInfo
required
The
FirmwareUpdateInfo returned by checkFirmwareUpdate.FirmwareUpdateCallback
required
Reports download progress and completion.
Install Firmware Update
Kotlin
File
required
The firmware file from
FirmwareDownloadResult.fileFirmwareUpdateInfo
required
The
FirmwareUpdateInfo returned by checkFirmwareUpdateFirmwareUpdateCallback
required
Reports install progress and completion.
Interfaces and Callbacks
The Embedded SDK is callback-driven. Device events flow through a single global listener you assign toPlaudDeviceAgent.listener, while per-operation flows (audio export, WiFi transfer, firmware) take their own callback interface. These four cover most use cases.
Callbacks are delivered on the SDK’s internal threads — not the main thread. Marshal to the main thread (e.g.
runOnUiThread { } / a Handler) before touching UI or view state.PlaudDeviceAgentListener
The primary listener forPlaudDeviceAgent. Assign it once to PlaudDeviceAgent.listener and it drives the entire BLE lifecycle — scan, connect, bind, device state, recording, and file sync. A single global listener receives every device event; all methods return Unit.
Kotlin
The listener also delivers the WiFi auto-sync configuration results (
onWifiSyncEnabled, onWifiSyncListReceived, onWifiSyncConfigReceived, onWifiSyncConfigSet, onWifiSyncDeleteResult, onWifiSyncTestStarted, onWifiSyncTestResult). These configure the device’s own scheduled background upload and are distinct from WiFi Fast Transfer.AudioExporter.ExportCallback
Reports progress, completion, and errors forexportAudio(...) (BLE) and exportAudioViaWiFi(...) (WiFi).
Kotlin
fun
required
Export progress,
0–100 (download bytes), with a human-readable status message.fun
required
Called when decoding finishes;
outputFile is the written file.fun
required
Called if export fails, with a description of the error.
fun
Optional (has a default implementation). Language-neutral phase signal:
DOWNLOADING (bytes still transferring off the device) → TRANSCODING (only local decode/encode remains).IWifiTransferAgent.WifiTransferCallback
WiFi Fast Transfer is split across both high-level interfaces, so you will useIWifiTransferAgent directly for any fast transfer. PlaudDeviceAgent owns the session lifecycle and the audio pipeline; IWifiTransferAgent owns the file operations and the callback you implement to drive them.
Kotlin
WiFi Fast Transfer
The typical flow: open the hotspot over BLE, start the session, wait for
READY, list files, then export each one.
WifiTransferCallback
12 required members for Wifi Transfers, generally driven byPlaudDeviceAgent.exportAudioViaWiFi.
WifiFileInfo carries sessionId, fileName, fileSize, duration (ms), timestamp (epoch seconds), and scene — more per-file metadata than BleFile exposes over BLE.
FirmwareUpdateCallback
Reports each phase of the OTA flow acrosscheckFirmwareUpdate(...), downloadFirmware(...), and installFirmware(...). Extend SimpleFirmwareUpdateCallback() to override only the methods you need — each has an empty default implementation.
Kotlin