Pair and Manage Card Readers

Applies to: Mobile Payments SDK - Android

Learn how to pair and manage card readers with the Mobile Payments SDK for Android.

Link to section

Overview

The Mobile Payments SDK's ReaderManager lets you pair and monitor changes in Square Readers.

Did you know?

Physical reader devices cannot be used in the Square Sandbox. For testing purposes, you can use the Mock Reader UI to pair simulated readers and process mock payments with your application in the Square Sandbox.

Link to section

Settings Manager

The Mobile Payments SDK offers a preconfigured reader settings screen, built from the SDK's public API, that you can use in your application by calling settingsManager.showSettings(). This screen includes two tabs. The Devices tab displays the model and connection status for readers paired to the merchant's phone or tablet and includes a button for pairing a new reader. The About tab displays information about the Mobile Payments SDK, authorized location, and environment used to take payments. Users can also enable or disable consent for performance and analytics tracking from this screen, if they are in a region where consent is required.

Call settingsManager.getSdkSettings() to retrieve SdkSettings, which exposes sdkVersion, sdkEnvironment (PRODUCTION or SANDBOX), and securityComplianceVersion. You can also retrieve PaymentSettings for offline payments with settingsManager.getPaymentSettings().

Link to section

Settings screen lifecycle

You can check whether the settings screen is currently displayed with settingsManager.isShowingSettings() and programmatically dismiss it with settingsManager.closeSettings(). This is useful for kiosks, or when your application needs to respond to external events while settings are open.

The Mobile Payments SDK's built-in settings screen, with tabs for the devices (readers) connected to the mobile device, and information about the SDK: its version, authorized location, and a toggle to accept cookies.

fun showSettings() { val settingsManager = MobilePaymentsSdk.settingsManager() settingsManager.showSettings { result -> when (result) { is Success -> { val settingsClosed = result.value logSettingsResult(settingsClosed) } is Failure -> { logSettingsFailure(result.errorCode, result.errorMessage) } } } }
Link to section

Reader Manager

For more control over your reader pairing and management screens, you can create your own using information from the SDK's ReaderManager, which provides methods for pairing and forgetting readers, accessing information about a particular reader, and listening for reader status updates.

Link to section

Pairing a reader

Pair a new reader using readerManager.pairReader(). Only one reader pairing can be in progress at one time, so check the Boolean value readerManager.isPairingInProgress and only begin pairing if it's false. readerManager.pairReader consumes a callback to notify your application when pairing completes. Use this callback to update progress indicators in your application and provide notifications to users based on whether reader pairing is successful.

The pairing callback is called once when pairing reaches a terminal state on its own: a reader connects, the 60-second scan times out, or an error occurs. A successful result is always true, meaning a reader was found, reported to the callback registered with setReaderChangedCallback, and added to ReaderManager.getReaders(). Pairing that ends without a reader returns a failure with a PairingErrorCode, such as TIMEOUT.

Calling pairingHandle.stop() doesn't invoke the callback, so dismiss your progress UI based on the returned StopResult (STOPPED or ALREADY_COMPLETE) instead.

The Mobile Payments SDK also provides setReaderChangedCallback, which is called when the status of a reader changes. Use this callback to notify your application when magstripe readers are inserted or removed, contactless and chip readers are paired or disconnected with Bluetooth, or the battery status changes.

Important

Register one reader-changed callback and distribute the events within your application. Only one callback can be registered at a time, so calling setReaderChangedCallback again silently replaces the previous one.

Paired readers are remembered by the Mobile Payments SDK, so when a new card reader is paired to the application, it remains paired and present in the list of readers provided by readerManager.getReaders() and will automatically reconnect when the authorized Square seller loads your application.

Link to section

Unpairing and identifying a reader

Call readerManager.forget(reader) to disconnect a paired reader and return it to its unpaired state. Check reader.isForgettable first; magstripe and Tap to Pay readers cannot be unpaired. To help a seller identify a reader, check reader.isBlinkable and call readerManager.blink(reader) to flash its LEDs. You can also call readerManager.getReader(id) to retrieve the current ReaderInfo for a known reader ID.

fun blinkReader(reader: ReaderInfo) { if (reader.isBlinkable) { MobilePaymentsSdk.readerManager().blink(reader) } } fun forgetReader(reader: ReaderInfo) { if (reader.isForgettable) { MobilePaymentsSdk.readerManager().forget(reader) } }
Link to section

Reader information

The ReaderInfo class provides information about Square readers paired with your application. These properties include:

  • The battery level and charging status.
  • The model (CONTACTLESS_AND_CHIP, MAGSTRIPE, or TAP_TO_PAY for Tap to Pay on Android).
  • The serial number.
  • The firmware info, including version and update status (see Firmware info).
  • The card entry methods supported by the reader (CONTACTLESS, EMV, or SWIPED).
  • The connection type (BLUETOOTH, USB, AUDIO, or EMBEDDED).

A Tap to Pay on Android device appears in getReaders() without pairing, reports a connectionType of EMBEDDED, and has isForgettable and isBlinkable set to false.

You can use this information to notify merchants when a reader is unpaired or its battery is low. You can create your own screens to display information about the status of readers or use a Square-provided settings screen for quick integration.

Link to section

Card entry methods

Different readers offer different card entry methods. For example, Square Reader for magstripe can only accept swiped cards, while Square Reader for contactless and chip can accept tapped cards, dipped cards, or digital wallets. The card entry methods supported are available within a reader's readerInfo.supportedCardEntryMethods. To track changes in the entry methods (for example, if the NFC connection to a contactless reader times out) register a callback with paymentManager.setAvailableCardEntryMethodChangedCallback. Like setReaderChangedCallback, it holds only one callback at a time.

Link to section

Reader status

Your application can monitor the current status of connected readers with readerInfo.status to display updates and messages to users. The possible status values are:

  • Ready: The reader is paired, connected, and able to accept card payments.
    • Magstripe readers connect automatically and are always Ready until physically disconnected from the mobile device.
  • ConnectingToSquare: The reader is establishing a connection to Square's servers.
  • ConnectingToDevice: The reader is establishing a connection to the mobile device.
  • Faulty: The reader has been tampered with or its firmware is damaged. This state is unrecoverable. Direct the seller to Square Support for a replacement.
  • ReaderUnavailable: The reader cannot currently take payments. This includes connected readers that are blocked, such as during a firmware update, and readers that have lost their connection.

If a reader is unavailable, check ReaderUnavailable.reason for details, such as Bluetooth failure, a blocking firmware update, or an issue with the seller's Square account. Depending on the reason, prompt the seller to take action or call readerManager.retryConnection(reader) to retry the connection to Square. The method returns one of these RetryConnectionResult values:

  • STARTING_RECONNECTION - The reconnection attempt started.
  • READER_ALREADY_CONNECTING_TO_SQUARE - A connection attempt is already running.
  • UNABLE_TO_RETRY - The reader's current status isn't retryable.
  • READER_NOT_FOUND - The reader is no longer known to the SDK.

Only readers that are Ready, or ReaderUnavailable because of SECURE_CONNECTION_TO_SQUARE_FAILURE or SECURE_CONNECTION_NETWORK_FAILURE, can retry the connection. Check the result before showing a reconnecting state.

Note

readerInfo.status was added in Android Mobile Payments SDK version 2.3.0 and replaces the legacy readerInfo.state. The state property was deprecated at error level in 2.4.0 and removed from the public API in 2.5.0. Migrate to readerInfo.status before upgrading.

Link to section

Firmware info

The ReaderInfo.firmwareInfo property provides structured firmware data through the ReaderFirmwareInfo class, which includes:

  • version: String? — The current firmware version installed on the reader.
  • updateStatus: FirmwareUpdateStatus — The current firmware update status, represented as a sealed class with the following values:
    • None — No firmware update is available or in progress.
    • Pending(updateDate: Date) — A firmware update is scheduled for the specified date.
    • InProgress(updatePercentage: Int?) — A firmware update is currently being installed, with an optional progress percentage.

Important

Deprecation notice:

  • readerInfo.firmwareVersion is deprecated. Use readerInfo.firmwareInfo.version instead.
  • readerInfo.firmwarePercent is deprecated. Use readerInfo.firmwareInfo.updateStatus instead.
fun checkFirmwareStatus() { val readerManager = MobilePaymentsSdk.readerManager() val readers = readerManager.getReaders() for (reader in readers) { val firmwareInfo = reader.firmwareInfo println("Firmware version: ${firmwareInfo.version}") when (val status = firmwareInfo.updateStatus) { is FirmwareUpdateStatus.None -> println("Firmware is up to date") is FirmwareUpdateStatus.Pending -> println("Update scheduled for: ${status.updateDate}") is FirmwareUpdateStatus.InProgress -> { val progress = status.updatePercentage?.let { "$it%" } ?: "unknown" println("Updating: $progress") } } } }
Link to section

Reader settings

Use readerManager.readerSettings to configure preferences that apply to all readers.

readerManager.tapToPaySettings exposes isDeviceCapable(), which reports whether the device can accept Tap to Pay on Android payments. Call it after authorizing the SDK.

Link to section

Preferred firmware update time

You can schedule firmware updates to occur at a preferred time of day using readerSettings.preferredFirmwareUpdateTime. This property accepts a TimeOfDay value with hour (0–23) and minute (0–59) properties. Setting this value allows sellers to schedule reader firmware updates during off-hours to avoid interruptions during business operations.

fun setFirmwareUpdateTime() { val readerManager = MobilePaymentsSdk.readerManager() val readerSettings = readerManager.readerSettings // Schedule firmware updates for 2:00 AM readerSettings.preferredFirmwareUpdateTime = TimeOfDay(hour = 2, minute = 0) }
Link to section

Reduced charging mode

Set readerSettings.isReducedChargingModeEnabled to true to limit how far supported readers charge. This can extend battery lifespan for readers that remain connected to power. The preference is persisted and applied when a reader connects.

fun enableReducedChargingMode() { MobilePaymentsSdk.readerManager() .readerSettings .isReducedChargingModeEnabled = true }