Skip to main content
inc.reactor.sdk.android.Reactor represents a client connection and its session. It implements AutoCloseable. Calls that wait are suspend functions, and state is exposed as flows. See Installation for the dependency and a complete example, and the API reference for every signature. The snippets below run inside a coroutine with a Reactor reactor; command and media operations need a connected session. Import SDK types from inc.reactor.sdk.android.

Create a client

Build ReactorOptions and pass it to the Reactor constructor. Creating a client does not connect it. The constructor’s second parameter, dispatcher, sets where control events are delivered. It defaults to Dispatchers.Main.immediate, so status and error collectors can update UI directly. Frame handlers run separately; see Track.
For a local model, set apiUrl = "http://localhost:8080" and local = true. From an emulator, the host machine is 10.0.2.2 rather than localhost.

Authentication

Use jwt in apps you distribute. During development, apiKey lets the client exchange the key for a token on each connect(), scoped to the model it creates a session for, or to the session it joins. A jwt you set takes priority, and the SDK never replaces it. A trusted backend or tool can exchange its API key with Reactor.fetchJwt(apiUrl, apiKey). Without options, the token grants everything the key allows. Pass a JSON scope to limit it:
An unknown option key fails the call rather than being ignored. To bind a token to an existing session, put its ID in a sessions array instead of models. See Authentication for token scope and expiry.

Session lifecycle

Model names are owner/name. connect() returns once the connection is set up; wait for READY before sending commands:
Call disconnect() before close() to end a session you created. A session joined by ID remains available to its owner after you disconnect. To restore a connection on the same session, call reconnect() without first calling disconnect(). Receiving tracks resume after connect and reconnect. Sending tracks must be published again before pushing frames. Cancelling a coroutine stops waiting for a call. It does not undo an operation already sent. See Errors for handling failures.

Commands and schema

Use command names and arguments from the model’s API reference. Arguments are a JSON object as a string. requestSchema() returns the running model’s schema as a Map<String, Any?>.
sendCommand(name) sends a command with no arguments. The call returns a CommandReply. An empty reply means the model acknowledged the command without returning a message; it is a successful result.

Upload files

Each returns a FileRef. uploadContent and uploadStream copy the stream to a cache file first, up to 64 MiB by default; pass maxBytes to change the limit. Pass the uploaded file in uploads, keyed by the command’s parameter name:
This example requires a model with a set_image command accepting an image parameter. Give the upload a name with the right extension: the MIME type is inferred from it, and a content URI’s own name often has none. See File uploads.

Recordings

requestClip(durationSeconds) requests a recent window; requestRecording() requests the session recording. Each returns a Clip once the request is accepted. The media may not be ready yet. downloadClip waits for it and assembles a playable file:
The progress callback is optional. readyTimeoutSeconds bounds the wait beyond the clip’s predicted ready time; by default it waits while the session can still produce the clip. Keep the session open until the download completes. Closing the client while a download runs fails the call but does not cancel the download; the file may still arrive. See Recordings.

Events

Collect them from a lifecycle-aware scope, for example lifecycleScope.launch { reactor.errors.collect { … } }. Start collecting errors and messages before connecting to see every one. messages carries each message the model sends as a {"type", "data"} object, including the ones no call returns, such as state updates. A command’s reply also arrives as the return value of sendCommand. runtimeMessages carries what the platform sends about the session, such as recording lifecycle notices. Media is delivered on individual tracks.

Stepped generation

A model that supports it can generate one step at a time instead of streaming. Set generation = Generation.STEPPED, then call step():
The runtime applies the state, then the commands, then the input frames pushed since the previous step, generates, and returns a StepResult. Every argument is optional: step() runs on the model’s current state. connect() fails when the model cannot run a stepped session. In a stepped session, Track.pushFrame buffers a frame for the next step instead of sending it. clearStepInputs() drops what is buffered. Frame handlers are refused, because nothing streams.

Connection statistics

stats() returns a Stats snapshot of the connection. droppedFrames counts received frames that arrived on a track with no handler.