Skip to main content

Android SDK

Overview

The Android SDK enables secure collection and reveal of sensitive data in native Android applications, supporting both XML layouts and Jetpack Compose.

Download SDK

Requirements

  • Minimum SDK: 23+
  • Target SDK: 36 (recommended)
  • Kotlin: 1.9+
  • Java Toolchain: 17 (recommended)
  • Theme: Must use AppCompatActivity theme

Installation

  1. Download and extract the SDK package
  2. Move secureconnect-maven-0.0.1.zip contents to {project_root}/mavenLib
  3. Add the Maven repository to your settings.gradle.kts:
dependencyResolutionManagement {
repositories {
maven {
url = uri("${rootProject.projectDir}/mavenLib")
}
}
}
  1. Add the dependency to your module's build.gradle.kts:
dependencies {
implementation("com.financial.connect:secureconnect:0.0.1")
}

Configuration

Initialize the SDK with your gateway URL:

import com.financial.connect.SecureConnectSdkFactory
import com.financial.connect.SecureConnectConfig

// Create SDK instance
val sdk = SecureConnectSdkFactory.create(
context = applicationContext,
config = SecureConnectConfig(gatewayUrl = "https://api.connect.financial")
)

// Initialize with auth token
sdk.initialize(authToken = "<auth-token>")

XML Layout Integration

Layout Definition

Add secure fields to your XML layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">

<com.financial.connect.ui.SecureEditText
android:id="@+id/ssnField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter SSN"
app:fieldType="ssn" />

<Button
android:id="@+id/submitButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Submit" />

</LinearLayout>

Binding and Submission

class CollectActivity : AppCompatActivity() {

private lateinit var sdk: SecureConnectSdk
private lateinit var ssnField: SecureEditText

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_collect)

// Initialize SDK
sdk = SecureConnectSdkFactory.create(
context = applicationContext,
config = SecureConnectConfig(gatewayUrl = "https://api.connect.financial")
)
sdk.initialize(authToken = "<auth-token>")

// Get field reference
ssnField = findViewById(R.id.ssnField)

// Bind the field to an operation
sdk.bindField(ssnField, Operation.SUBMIT_DOCUMENT_SSN)

// Add validation listener
ssnField.addOnFieldStateChangeListener { state ->
if (!state.isValid && !state.isEmpty) {
ssnField.setError("Invalid SSN format")
} else {
ssnField.setError(null)
}
}

// Handle submission
findViewById<Button>(R.id.submitButton).setOnClickListener {
submitData()
}
}

private fun submitData() {
lifecycleScope.launch {
val result = sdk.submit(
operation = Operation.SUBMIT_DOCUMENT_SSN,
customerId = "customer-uuid"
)
when (result) {
is Result.Success -> {
Log.d("SecureConnect", "Token: ${result.data.token}")
}
is Result.Error -> {
Log.e("SecureConnect", "Error: ${result.exception}")
}
}
}
}
}

Jetpack Compose Integration

Basic Compose Usage

@Composable
fun SecureSSNInput(
sdk: SecureConnectSdk,
onSubmitSuccess: (String) -> Unit
) {
var fieldState by remember { mutableStateOf<FieldState?>(null) }
var isSubmitting by remember { mutableStateOf(false) }
val scope = rememberCoroutineScope()

Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
SecureTextField(
sdk = sdk,
operation = Operation.SUBMIT_DOCUMENT_SSN,
modifier = Modifier.fillMaxWidth(),
placeholder = { Text("Enter SSN") },
onStateChange = { fieldState = it },
isError = fieldState?.let { !it.isValid && !it.isEmpty } ?: false
)

if (fieldState?.let { !it.isValid && !it.isEmpty } == true) {
Text(
text = "Invalid SSN format",
color = MaterialTheme.colorScheme.error,
style = MaterialTheme.typography.bodySmall
)
}

Spacer(modifier = Modifier.height(16.dp))

Button(
onClick = {
scope.launch {
isSubmitting = true
val result = sdk.submit(
operation = Operation.SUBMIT_DOCUMENT_SSN,
customerId = "customer-uuid"
)
isSubmitting = false
if (result is Result.Success) {
onSubmitSuccess(result.data.token)
}
}
},
enabled = fieldState?.isValid == true && !isSubmitting,
modifier = Modifier.fillMaxWidth()
) {
if (isSubmitting) {
CircularProgressIndicator(
modifier = Modifier.size(16.dp),
color = MaterialTheme.colorScheme.onPrimary
)
} else {
Text("Submit")
}
}
}
}

Revealing Card Data

XML Approach

<com.financial.connect.ui.SecureLabel
android:id="@+id/panLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
app:placeholder="•••• •••• •••• ••••" />

<com.financial.connect.ui.SecureLabel
android:id="@+id/cvvLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:placeholder="•••" />

<com.financial.connect.ui.SecureLabel
android:id="@+id/expiryLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:placeholder="••/••" />

Binding and Revealing

class RevealActivity : AppCompatActivity() {

private lateinit var sdk: SecureConnectSdk

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_reveal)

sdk = SecureConnectSdkFactory.create(
context = applicationContext,
config = SecureConnectConfig(gatewayUrl = "https://api.connect.financial")
)
sdk.initialize(authToken = "<auth-token>")

// Bind reveal fields
val panLabel = findViewById<SecureLabel>(R.id.panLabel)
val cvvLabel = findViewById<SecureLabel>(R.id.cvvLabel)
val expiryLabel = findViewById<SecureLabel>(R.id.expiryLabel)

sdk.bindRevealField(panLabel, RevealOperation.REVEAL_CARD_PAN)
sdk.bindRevealField(cvvLabel, RevealOperation.REVEAL_CARD_CVV)
sdk.bindRevealField(expiryLabel, RevealOperation.REVEAL_CARD_EXPIRY)

// Reveal button
findViewById<Button>(R.id.revealButton).setOnClickListener {
revealCardData()
}
}

private fun revealCardData() {
lifecycleScope.launch {
// Reveal PAN with formatting
sdk.reveal(
operation = RevealOperation.REVEAL_CARD_PAN,
cardId = "card-uuid",
serializer = PanSerializer.WITH_DASHES
)

// Reveal CVV
sdk.reveal(
operation = RevealOperation.REVEAL_CARD_CVV,
cardId = "card-uuid"
)

// Reveal expiry with formatting
sdk.reveal(
operation = RevealOperation.REVEAL_CARD_EXPIRY,
cardId = "card-uuid",
serializer = ExpirySerializer.SHORT // MM/YY format
)
}
}
}

Compose Reveal Example

@Composable
fun CardRevealScreen(sdk: SecureConnectSdk, cardId: String) {
var isRevealed by remember { mutableStateOf(false) }
val scope = rememberCoroutineScope()

Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
SecureRevealLabel(
sdk = sdk,
operation = RevealOperation.REVEAL_CARD_PAN,
cardId = cardId,
serializer = PanSerializer.WITH_SPACES,
placeholder = "•••• •••• •••• ••••",
modifier = Modifier.fillMaxWidth()
)

Spacer(modifier = Modifier.height(8.dp))

Row(
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
SecureRevealLabel(
sdk = sdk,
operation = RevealOperation.REVEAL_CARD_EXPIRY,
cardId = cardId,
serializer = ExpirySerializer.SHORT,
placeholder = "••/••"
)

SecureRevealLabel(
sdk = sdk,
operation = RevealOperation.REVEAL_CARD_CVV,
cardId = cardId,
placeholder = "•••"
)
}

Spacer(modifier = Modifier.height(16.dp))

Button(
onClick = {
scope.launch {
if (isRevealed) {
sdk.hideAll()
} else {
sdk.revealAll(cardId = cardId)
}
isRevealed = !isRevealed
}
},
modifier = Modifier.fillMaxWidth()
) {
Text(if (isRevealed) "Hide" else "Reveal")
}
}
}

Serializers (Formatting)

The SDK supports serializers for formatting revealed data:

SerializerOutput FormatExample
PanSerializer.WITH_DASHESXXXX-XXXX-XXXX-XXXX4111-1111-1111-1111
PanSerializer.WITH_SPACESXXXX XXXX XXXX XXXX4111 1111 1111 1111
ExpirySerializer.SHORTMM/YY12/25
ExpirySerializer.FULLMM/YYYY12/2025

Supported Operations

Collect Operations

OperationDescription
Operation.SUBMIT_DOCUMENT_IDSubmit government-issued ID
Operation.SUBMIT_DOCUMENT_SSNSubmit Social Security Number
Operation.SUBMIT_DOCUMENT_DRIVERS_LICENCESubmit driver's license
Operation.SUBMIT_DOCUMENT_PASSPORTSubmit passport

Reveal Operations

OperationDescription
RevealOperation.REVEAL_DOCUMENT_IDReveal government-issued ID
RevealOperation.REVEAL_DOCUMENT_SSNReveal Social Security Number
RevealOperation.REVEAL_DOCUMENT_DRIVERS_LICENCEReveal driver's license
RevealOperation.REVEAL_DOCUMENT_PASSPORTReveal passport
RevealOperation.REVEAL_CARD_PANReveal card number
RevealOperation.REVEAL_CARD_CVVReveal card CVV
RevealOperation.REVEAL_CARD_EXPIRYReveal card expiry date