Build a secure in-person payment solution for Android devices with the Reader SDK.
Reader SDK

Build on Android

To build with the Reader SDK, the following must be true:

  • You have a Square account enabled for payment processing. If you have not enabled payment processing on your account (or you are not sure), visit squareup.com/activation.

  • Your application minSdkVersion is API 21 (Lollipop 5.0) or later.

  • Your application targetSdkVersion is API 29 (Q, 10.0) or earlier.

  • Your application uses AndroidX or enables Jetifier in gradle.properties.

  • You are using the Android Gradle Plugin version 3.0.0 or later. The Reader SDK might work with 2.3.0 or later, but stability is not guaranteed.

  • Your application uses Google Play Services version 16.0.1. Square cannot guarantee that the SDK works with different versions of these libraries.

  • You are not using Proguard for code optimization. Compressing the Reader SDK binary removes critical bytecode elements and results in runtime errors.

Additionally, this guide makes the following assumptions:

  • Your version of the Reader SDK adheres to the Square update policy. To limit risk to developers and their users, Square enforces a Reader SDK update policy requiring developers keep their version of the Reader SDK current.

  • You are generally familiar with developing applications on Android. If you are new to Android development, you should read the Getting Started Guide on the Android Developers site before continuing.

    Important

    The Reader SDK is not supported on Android versions earlier than API 19 (KitKat, 4.4). Square does not recommend targeting Android versions later than API 29 (Q, 10.0) with the Reader SDK.

To work with Square Readers, applications must have the following device permissions. If the required device permissions are not granted when the checkout flow initiates, the Reader SDK prompts the user to grant the necessary permissions.

Android device permissionPurpose
LocationTo confirm that payments are occurring in a supported country.
AudioTo connect Magstripe Readers.
BluetoothTo connect Contactless Readers.
Device StorageTo store information during checkout.
Phone AccessTo identify the device sending information to Square servers.

To use the steps in this topic, you need:

  • Your application ID. Find your application ID on the Credentials page of your Square application in the Developer Dashboard.

  • Your Reader SDK repository password. Find your Reader SDK repository password on the Reader SDK page of your Square application in the Developer Dashboard.

  1. Open the Square Developer Dashboard. You are prompted to sign in or create an account.

  2. Create a Square application.

  3. Choose the new application to open the Square application settings pages.

  4. Open the Reader SDK page, and then choose Request Credentials to generate your Reader SDK repository password.

    A graphic showing the Reader SDK page in the Developer Dashboard with the generated Reader SDK repository password.

  1. Update the gradle.properties file in the root folder of your project to increase the maximum heap size provided to the Gradle daemon and set variables for the Square application ID and repository password.

  1. Add the Reader SDK variables from your properties file and confirm that the Google repository is set properly in the build.gradle file of your :app module.

    a. Update the gradle.properties file.

    b. Add the Reader SDK variables.

Did you know?

If you run into compile errors, make sure that you are using AndroidX across all your dependencies by running ./gradlew app:dependencies.

The Reader SDK and its dependencies contain more than 65,000 methods, so your build script must enable multidex. If your minSdkVersion is earlier than API 21, you need to include the multidex dependency.

  1. Connect the Reader SDK to a Square Contactless Reader to accept chip and tap payments.

  1. Add a compile option to support Java version 1.8 in the build.gradle file for your :app module.

  1. Configure the multidex options.

  1. Add the Reader SDK dependencies.

  1. Create an Application class that extends android.app.Application and specify the android:name property for the <application> node in AndroidManifest.xml. For more information, see Understanding the Android Application Class on Codepath.

  2. Import and initialize the Reader SDK.

To authorize the SDK, you must build an authorization service to retrieve a mobile authorization code with the Mobile Authorization API and return it to your application.

Mobile authorization codes are short lived and should be used immediately to authorize the Reader SDK. Authorization is valid until it is explicitly revoked by calling deauthorize or your application fails to take a payment within 90 days. Mobile authorization codes do not need to be manually refreshed under normal operations.

Create a new AuthorizeActivity with two skeleton functions (retrieveAuthorizationCode() and onAuthorizationCodeRetrieved()), and then customize them to call your authorization service.

Did you know?

You can also generate mobile authorization codes manually with a command-line tool. For more information, see Request a Mobile Authorization Code on the Command Line.

  1. Add a callback (onAuthorizeResult()) to the Authorization Manager in the onCreate method of your authorization activity using AuthorizationManager.addAuthorizeCallback().

  2. Implement the onAuthorizeResult() callback. AuthorizeCallback.onResult() is invoked asynchronously on the main thread with a Result object. The result includes the authorized Location (in case of success) or a ResultError (in case of error).

  3. Add code to clear the callback reference in your onDestroy() method to avoid memory leaks.

  1. Add the onAuthorizeResult callback to the Authorization Manager.

  2. Implement the onAuthorizeResult() callback.

  3. Clear the callback reference in your onDestroy() method.

Create a new activity, CheckoutActivity, with a button that calls startCheckout() to begin the checkout flow.

Did you know?

The Checkout activity is a good place to add a button that starts the contactless reader connect flow. A Square contactless reader cannot be connected until the Reader SDK is authorized. Authorization is completed in Step 6 which means you can now connect a reader. See Connect a Contactless Reader for information about connecting a reader.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
import com.squareup.sdk.reader.checkout.AdditionalPaymentType;
import com.squareup.sdk.reader.checkout.CheckoutErrorCode;
import com.squareup.sdk.reader.checkout.CheckoutManager;
import com.squareup.sdk.reader.checkout.CheckoutParameters;
import com.squareup.sdk.reader.checkout.CheckoutResult;
import com.squareup.sdk.reader.checkout.CurrencyCode;
import com.squareup.sdk.reader.checkout.Money;
import com.squareup.sdk.reader.core.CallbackReference;
import com.squareup.sdk.reader.core.Result;
import com.squareup.sdk.reader.core.ResultError;

public class CheckoutActivity extends Activity {

  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (!ReaderSdk.authorizationManager().getAuthorizationState().isAuthorized()) {
      goToAuthorizeActivity();
    }

    setContentView(R.layout.checkout_activity);

    View startCheckoutButton = findViewById(R.id.start_checkout_button);
    startCheckoutButton.setOnClickListener(view -> startCheckout());
  }

  private void goToAuthorizeActivity() {
      // TODO: Reader SDK is not authorized, move to Authorize Activity
  }
}

  1. Implement the startCheckout() method by adding code to build the CheckoutParameters object and configure the checkout experience. The following code uses CurrencyCode#current to obtain the currency code of the authorized location and set CASH as one of the additional tender types, which lets you test payments without charging a card.

  2. Add a callback (onCheckoutResult()) to the Checkout Manager in the onCreate method of CheckoutActivity using CheckoutManager.addCheckoutActivityCallback.

  3. Add code to clear the checkout callback reference in your onDestroy() method to avoid memory leaks.

  1. Implement the startCheckout() method.

  2. Add onCheckoutResult() to the Checkout Manager.

  3. Clear the checkout callback reference in your onDestroy() method.

Implement the onCheckoutResult callback to parse the checkout response. CheckoutActivityCallback.onResult() is invoked asynchronously on the main thread with a Result object. The result includes the CheckoutResult (in case of success) or a ResultError (in case of error).

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
public class CheckoutActivity extends Activity {
  // ...

  private void onCheckoutResult(Result<CheckoutResult, ResultError<CheckoutErrorCode>> result) {
    if (result.isSuccess()) {
      CheckoutResult checkoutResult = result.getSuccessValue();
      showCheckoutResult(checkoutResult);
    } else {
      ResultError<CheckoutErrorCode> error = result.getError();

      switch (error.getCode()) {
        case SDK_NOT_AUTHORIZED:
          goToAuthorizeActivity();
          break;
        case CANCELED:
          Toast.makeText(this, "Checkout canceled", Toast.LENGTH_SHORT).show();
          break;
        case USAGE_ERROR:
          showErrorDialog(error);
          break;
      }
    }
  }

  private void showCheckoutResult(CheckoutResult checkoutResult) {
    // TODO: Display the checkout result.
  }

  private void showErrorDialog(ResultError<?> error) {
    String dialogMessage = error.getMessage();
    if (BuildConfig.DEBUG) {
      dialogMessage += "\n\nDebug Message: " + error.getDebugMessage();
      Log.d("Checkout", error.getDebugCode() + ", " + error.getDebugMessage());
    }
    showDialog(getString(R.string.error_dialog_title), dialogMessage);
  }

  private void showDialog(CharSequence title, CharSequence message) {
    // TODO: Display a dialog to the user.
  }
}

If you need more assistance, contact Developer Support or ask for help in the Developer Forums.