Skip to main content

Device Connection

Note: If you prefer the older connection flow, you can continue to use it without any modifications.

This document explains the connection handling and its interaction with transactions, configuration, and printing. It outlines how these processes should be executed and clarifies the expected behavior when using the DeviceConnection flow in combination with other flows.

The goal of this connection handling approach is provide freedom on the device connection handling. Key enhancements include:

  • Persistent Connections: Device connections are persistent and can be established at any time, even before initiating any transaction or configuring a reader. This ensures that the connection remains available for several tasks without requiring re-initialization.
  • Backward compatibility: If needed, you can still use the old way of connecting to devices without any changes.

Connection Handling

The SDKDeviceConnectionControllerFactory class simplifies the creation of connection controllers for devices within your workflow. You can use this class to:

  • Handle device connection events.
  • Manage the connection lifecycle (connect, disconnect, recover errors).
  • Abort ongoing connections when required.

The SDKDeviceConnectionControllerFactory creates a SDKDeviceConnectionController that is used to manage the connection lifecycle. It needs a SDKDeviceConnectionControllerListener for handling DeviceConnection state and status. Below is an example:

val deviceConnectionListener = SDKDeviceConnectionControllerListener {

override fun onDeviceConnectionStateChanged(state: SDKDeviceConnectionState) {
when (state) {
is SDKDeviceConnectionState.Disconnected -> {
// Device is disconnected.
// In this state you can connect to a device at any time by calling
// state.connect(device) with a device.
state.connect(device)
}

is SDKDeviceConnectionState.Connected -> {
// Device is connected.
// In this state you can disconnect the current device by calling state.disconnect().
state.disconnect()
// When device is connected, information about it can be obtained.
state.device // (`SDKDevice`)
state.deviceInfo // (`SDKDeviceInfo`)
}

is SDKDeviceConnectionState.Error.NonRecoverable<*> -> {
//This state indicates that an error described by SDKDeviceConnectionError and an
// exception has occurred and its NotRecoverable.
// Nothing can be done after the SDKDeviceConnection is in this state.
handleNonRecoverableError(state.error, state.exception)
}

is SDKDeviceConnectionState.Error.Recoverable<*> -> {
// This state indicates that an error described by SDKDeviceConnectionError has
// occurred and its recoverable.
// In this state you can recover the error by calling state.recover().
// Recovering from a RecoverableError will return the SDKDeviceConnection to the
// last "Stable" state to continue.
handleRecoverableError(state.error)
state.recover()
}

is SDKDeviceConnectionState.InUse -> {
// The device is already in use by a transaction, configuration or printing flow.
// You cannot interact with this state.
}
}
}

override fun onDeviceConnectionStatusChanged(status: SDKDeviceConnectionStatus) {
// This status indicates current device status: Disconnected, Connected or Connecting.
// DeviceConnection could be with state InUse and status Disconnected, for example.
}
}

// Create the connection controller
val connection = SDKDeviceConnectionControllerFactory.create(deviceConnectionListener)

Interaction with transaction, configuration or printing flows

  1. Initiate Connection First: A connection to a device must be successfully established before initiating any other process (transaction, configuration, or printing). Starting any of these processes without an active connection is not possible.
  2. Existing Connection:
    • If there is already a connection initiated by SDKDeviceConnectionController, it emits an InUse state.
    • When the state is InUse, you cannot interact with the SDKDeviceConnectionController (e.g., attempting to connect again). In this state, it is not possible to abort the connection. If you do that, a SDKCannotAbortException is thrown.
    • When any other flow using this device connection emits a final status, the SDKDeviceConnectionController will stop being Inuse state and emit the corresponding state (Connected or Disconnected) and you can interact with it again.
    • When any other flow using this device connection ends, connection never ends until you finish it. Therefore, reconnection is not necessary if you want to continue with another transaction, configuration or print.

When using the SDKDeviceConnectionController in combination with others flows:

  1. Separate Flows:
    • The connection flow manages connection states, while the transaction, configuration or printing flow manages their own states.
    • Each flow emits its states independently and should be interacted with separately.
    • If other flow needs to provide a device, it must be the same device used in SDKDeviceConnectionState.Disconnected in SDKDeviceConnectionController.
    • Once the connection is established, you can manage transactions, configurations or printing as usual.SDKDeviceConnectionControllerListener will continue to receive updates on the device connection state.
  2. Error Recovery:
    • If a transaction, configuration or printing encounters a connection error, the state.recover() method in the connection controller attempts to reconnect to the same device and return to the last stable state.
    • If reconnection fails repeatedly, the recovery process will loop until the connection is restored or the user aborts the transaction.
  3. Aborting:
    • If a transaction, configuration or printing is aborted and the connection is InUse, the connection flow will return to the last stable state.

When SDKTransactionIntent's SDKReaderState, SDKReaderConfigurator's SDKReaderState, and SDKPrinter's SDKPrinterState emit a state, this state has a different meaning depending on whether Legacy mode or the new DeviceConnection mode is used.

In Legacy mode, the state refers to the actual connection of the device, so a Disconnected state means that the device is physically disconnected from the phone.

In the new DeviceConnection mode, the physical connection is exclusively managed by the SDKDeviceConnectionController. In this mode, the state emitted by SDKTransactionIntent, SDKReaderConfigurator, or SDKPrinter refers to the logical connection between the device and the "operation" itself.

For example, when an SDKTransactionIntent's SDKReaderState.NotConnected status is emitted after a transaction is aborted or completed, it means that the device is no longer "in use" for that transaction. However, the actual physical connection of the device must be checked through SDKDeviceConnectionController's SDKDeviceConnectionStatus.