Installation

The Android SDK is a set of lightweight libraries delivered as Android Archive Repository files, .aar. The minimum supported version of Android is v7, level 24. Prove manages a maven repository with Android binaries to enable integration with Gradle. Update the dependencies object in the build.gradle file:
dependencies {
  // Existing dependencies are here.

  // Add the Prove Link dependencies:
  implementation 'com.prove.sdk:proveauth:6.4.1'
}
You’ll also need to point to the repository by updating your settings.gradle file with the Maven repository:
dependencyResolutionManagement {
    // Existing repository settings are here.

    repositories {
        // Existing repositories are here.

        // Add the Prove Link Maven repository:
        maven {
            url = "https://prove.jfrog.io/artifactory/libs-public-maven/"
        }
    }
}
The following needs added to the build.gradle file to also download dependency libraries:
dependencies {
  implementation fileTree('libs')
}
If you receive an error message on the application@fullBackupContent value, you can resolve it by adding this line of code to your application AndroidManifest.xml file inside the <application>...</application> node. Add it as an attribute to the opening application tag:
<application
...
tools:replace="android:fullBackupContent"
...>
</application>

Permissions

The Prove Auth SDK and its children SDKs merge the following permissions into the main application:
<!-- Required to perform authentication -->
<uses-permission android:name="android.permission.INTERNET" />

<!-- Required to access information about networks -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- Required for ConnectivityManager.requestNetwork -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

Send the Type of Flow: Mobile

Unlike the Web SDK, when using the Android SDK, use the mobile flow. Pass mobile to the Unify() function on the server. In a mobile flow, OTP validation is performed on the mobile phone. In the mobile flow, once OTP validation is complete, the AuthFinishStep function executes.

Authenticate()

The SDK requires an authToken as a parameter for the Authenticate() function. This token returns from the Unify() call of the server SDK. The token is session specific, limiting it to a single flow. It also expires after 15 minutes.

Retrieve authToken

To start the flow, you’ll need to send a request to your backend server with possession type, and an optional phone number if using Prove’s possession check.
String initialize(String phoneNumber, String possessionType) {
    YourBackendClient backend = new YourBackendClient(); // Backend API client

    // TODO: Build your InitializeRequest object
    InitializeRequest initializeRequest = new InitializeRequest(phoneNumber, possessionType);

    // Send an initialize request to your backend server to get authToken
    InitializeResponse response = backend.initialize(initializeRequest);

    // TODO: define your own InitializeResponse object to parse authToken string
    return response.getAuthToken();
}

Setup Authenticator

Once you have the authToken, build the authenticator for the mobile flow.
Java
// Object implementing AuthFinishStep interface
AuthFinishStep authFinishStep = new AuthFinishStep() {
...
};

// Objects implementing OtpStartStep/OtpFinishStep interfaces
OtpStartStep otpStartStep = new OtpStartStep() {
...
};

OtpFinishStep otpFinishStep = new OtpFinishStep() {
...
};

ProveAuth proveAuth = ProveAuth.builder()
    .withAuthFinishStep(authId -> verify(authId)) // verify(authId) call defined in #Validate the Mobile Phone section
    .withOtpFallback(otpStartStep, otpFinishStep)
    .withContext(this)
    .build();
The cellular data connection can sometimes be unavailable during testing. The Builder class offers a withTestMode(boolean testMode) method. This method permits simulated successful session results while connected to a Wi-Fi network only. Testing using a Wi-Fi connection is useful in the Sandbox environment.
Java
ProveAuth proveAuth = ProveAuth.builder()
    .withAuthFinishStep(authId -> verify(authId))
    .withOtpFallback(otpStartStep, otpFinishStep)
    .withContext(this)
    .withTestMode(true) // Test mode flag
    .build();

Performing the Authentication

The ProveAuth object is thread safe. You can use it as a singleton. Most Prove Auth methods are blocking and therefore can’t execute in the main application thread. The application employs an executor service with a minimum of two threads to manage threads due to the SDK’s ability to process concurrent blocking requests.
public class MyAuthenticator {
    private final MyBackendClient backend = new MyBackendClient(); // Backend API client
    private ExecutorService executor = Executors.newCachedThreadPool();
    private final AuthFinishStep authFinishStep = new AuthFinishStep() {
        @Override
        void execute(String authId) {
            try {
                AuthFinishResponse response = backend.authFinish("My App", authId);
                ... // Check the authentication status returned in the response
            } catch (IOException e) {
                String failureCause = e.getCause() != null ? e.getCause().getMessage() : "Failed to request authentication results";
                // Authentication failed due to request failure
            }
        }
    };

    private ProveAuth proveAuth;

    public MyAuthenticator(Context context) {
        proveAuth = ProveAuth.builder()
          .withAuthFinishStep(authFinishStep)
			    .withOtpFallback(otpStartStep, otpFinishStep)
          .withContext(context)
          .build();
    }

    public void authenticate() throws IOException, ProveAuthException {
        AuthStartResponse response = backend.authStart("My Prove Auth App");

        proveAuth.authenticate(response.getAuthToken());
    }
}

public void authenticate() throws IOException, ProveAuthException {
      // NOTE: blocking method proveAuth.authenticate() should be run in background thread
      executor.submit(() -> {
          AuthStartResponse response = backend.authStart("My Prove Auth App");
          proveAuth.authenticate(response.getAuthToken());
      }
}

Validate the Mobile Phone

In the AuthFinishStep, you’ll specify a function to call once the possession checks are complete on the mobile phone. This endpoint on your back end server calls the Validate() function to check phone number validation. If it was successful, the server returns the results from the Challenge() function, including customer information.
// Send a verify request to get return customer information.
void verify(String: authId) {
  YourBackendClient backend = new YourBackendClient(); // Backend API client

  // Build your VerifyRequest object
  VerifyRequest verifyRequest = new VerifyRequest(authId, ...);

  // Send a verify request to your backend server to get return customer information.
  VerifyResponse response = backend.verify(verifyRequest);
}

Configure OTP

To use the Resend/Retry/Phone Change features, you need to install the Android SDK version 6.5.0 or later.
To set the One-Time Password (OTP) handler, withOtpFallback(otpStart: otpStartStep, otpFinish: otpFinishStep), requires implementing the OtpStartStep and OtpFinishStep. The default implementation is below, but you can also view the other tabs if you wish to enable advanced capabilities. The OTP session has a two minute timeout from when it’s sent through SMS to when the customer can enter in the OTP.
Follow these instructions if you are implementing OTP and you are passing in the phone number on the /v3/start endpoint. In this case, you’ve already prompted for a phone number so you don’t need to prompt for it in the client SDK.Since you passed the phone number in the Start() function, call OtpStartStepCallback.onSuccess(OtpStartInput); to communicate to the SDK you have the customer’s agreement to deliver the SMS message. Ensure you return an instance of OtpStartInput with empty string or null to OtpStartStepCallback.onSuccess() function.
java
import com.prove.sdk.proveauth.OtpStartInput;
import com.prove.sdk.proveauth.OtpStartStep;
import com.prove.sdk.proveauth.OtpStartStepCallback;
import com.prove.sdk.proveauth.ProveAuthException;

public class MyOtpStartStep implements OtpStartStep {
    @Override
    public void execute(boolean phoneNumberNeeded, ProveAuthException otpException,
            OtpStartStepCallback callback) {
        // No phone number needed, no need to ask end user for input.
        callback.onSuccess(new OtpStartInput(""));
    }
}
Call the OtpStartStepCallback.onError(); method to communicate to the SDK any issues while trying to obtain the phone number or the OTP. Report an error if the customer cancels the SMS transaction or presses the back button to leave the screen.In the finish step, call the OtpFinishStepCallback.onSuccess(OtpFinishInput); method to return the collected OTP value wrapped in OtpFinishInput.
Java
import com.prove.sdk.proveauth.OtpFinishInput;
import com.prove.sdk.proveauth.OtpFinishStep;
import com.prove.sdk.proveauth.OtpFinishStepCallback;
import com.prove.sdk.proveauth.OtpValidationException;
import com.prove.sdk.proveauth.ProveAuthException;

public class MyOtpFinishStep implements OtpFinishStep {
    @Override
    public void execute(@Nullable ProveAuthException otpException,
            OtpFinishStepCallback otpFinishStepCallback) {
        // If error message is found, handle it.
        if (otpException instanceof OtpValidationException) {
            // Set to a variable and display it in a field.
            // In this example, we don't do anything with the error.
            String errorMsg = otpException.getMessage();
        }

        try {
            // Prompt the user for OTP delivered by SMS. You can build UI to provide
            // best UX based on your application and business logic, here we simplify to a
            // generic function named promptForOtpCode which gives us the OTP code.
            String otpCode = promptForOtpCode();
            otpFinishStepCallback.onSuccess(new OtpFinishInput(otpCode));
        } catch (Exception e) {
            // if any issue with the OTP collection from the end user or the user wants to cancel
            // then call onError to exit the flow. In this example we simplify it as catching
            // an exception.
            otpFinishStepCallback.onError();
        }
    }
}