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.
Requirements
- Minimum SDK: 23+
- Target SDK: 36 (recommended)
- Kotlin: 1.9+
- Java Toolchain: 17 (recommended)
- Theme: Must use
AppCompatActivitytheme
Installation
- Download and extract the SDK package
- Move
secureconnect-maven-0.0.1.zipcontents to{project_root}/mavenLib - Add the Maven repository to your
settings.gradle.kts:
dependencyResolutionManagement {
repositories {
maven {
url = uri("${rootProject.projectDir}/mavenLib")
}
}
}
- 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:
| Serializer | Output Format | Example |
|---|---|---|
PanSerializer.WITH_DASHES | XXXX-XXXX-XXXX-XXXX | 4111-1111-1111-1111 |
PanSerializer.WITH_SPACES | XXXX XXXX XXXX XXXX | 4111 1111 1111 1111 |
ExpirySerializer.SHORT | MM/YY | 12/25 |
ExpirySerializer.FULL | MM/YYYY | 12/2025 |
Supported Operations
Collect Operations
| Operation | Description |
|---|---|
Operation.SUBMIT_DOCUMENT_ID | Submit government-issued ID |
Operation.SUBMIT_DOCUMENT_SSN | Submit Social Security Number |
Operation.SUBMIT_DOCUMENT_DRIVERS_LICENCE | Submit driver's license |
Operation.SUBMIT_DOCUMENT_PASSPORT | Submit passport |
Reveal Operations
| Operation | Description |
|---|---|
RevealOperation.REVEAL_DOCUMENT_ID | Reveal government-issued ID |
RevealOperation.REVEAL_DOCUMENT_SSN | Reveal Social Security Number |
RevealOperation.REVEAL_DOCUMENT_DRIVERS_LICENCE | Reveal driver's license |
RevealOperation.REVEAL_DOCUMENT_PASSPORT | Reveal passport |
RevealOperation.REVEAL_CARD_PAN | Reveal card number |
RevealOperation.REVEAL_CARD_CVV | Reveal card CVV |
RevealOperation.REVEAL_CARD_EXPIRY | Reveal card expiry date |