Code Examples Android SDK
Ready-to-use Android code examples for common scenarios.
Example 1: Basic Compose Payment
@Composable
fun PaymentScreen() {
val context = LocalContext.current as ComponentActivity
var showSuccess by remember { mutableStateOf(false) }
if (showSuccess) {
SuccessScreen()
} else {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text("$25.00", fontSize = 32.sp, fontWeight = FontWeight.Bold)
Spacer(modifier = Modifier.height(24.dp))
Button(onClick = {
context.lifecycleScope.launch {
val session = createCheckoutSession()
Yuno.startCheckout(
activity = context,
checkoutSession = session.id,
countryCode = "US",
yunoCreatePayment = { token ->
createPayment(token, session.id)
},
yunoPaymentResult = { result ->
if (result.status == PaymentStatus.SUCCEEDED) {
showSuccess = true
}
}
)
}
}) {
Text("Pay Now")
}
}
}
}Example 2: XML Views Payment
class PaymentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_payment)
findViewById<Button>(R.id.payButton).setOnClickListener {
processPayment()
}
}
private fun processPayment() {
lifecycleScope.launch {
try {
val session = createCheckoutSession(2500)
Yuno.startCheckout(
activity = this@PaymentActivity,
checkoutSession = session.checkoutSession,
countryCode = "US",
yunoCreatePayment = { token ->
createPayment(token, session.checkoutSession)
},
yunoPaymentResult = { result ->
handleResult(result)
}
)
} catch (e: Exception) {
showError(e.message ?: "Payment failed")
}
}
}
private fun handleResult(result: PaymentResult) {
when (result.status) {
PaymentStatus.SUCCEEDED -> {
startActivity(Intent(this, SuccessActivity::class.java))
finish()
}
PaymentStatus.FAILED -> {
showError(result.error?.message ?: "Payment failed")
}
else -> {}
}
}
}Example 3: Subscription Enrollment
class SubscriptionActivity : ComponentActivity() {
fun enrollCard() {
lifecycleScope.launch {
val customerSession = createCustomerSession("cus_123")
Yuno.startEnrollment(
activity = this@SubscriptionActivity,
customerSession = customerSession.id,
countryCode = "US",
yunoEnrolled = { vaultedToken ->
setupSubscription(vaultedToken)
}
)
}
}
private suspend fun setupSubscription(vaultedToken: String) {
apiClient.post("/subscriptions", mapOf(
"customer_id" to "cus_123",
"vaulted_token" to vaultedToken,
"plan" to "premium_monthly"
))
Toast.makeText(this, "Subscription activated!", Toast.LENGTH_SHORT).show()
}
}Example 4: One-Click Payment
@Composable
fun SavedCardsScreen(cards: List<SavedCard>) {
val context = LocalContext.current as ComponentActivity
LazyColumn {
items(cards) { card ->
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.clickable { payWithCard(context, card) }
) {
Row(
modifier = Modifier.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text("${card.brand} ****${card.last4}")
Spacer(Modifier.weight(1f))
Text("Use this card", color = MaterialTheme.colorScheme.primary)
}
}
}
}
}
fun payWithCard(activity: ComponentActivity, card: SavedCard) {
activity.lifecycleScope.launch {
val session = createCheckoutSession()
Yuno.startCheckout(
activity = activity,
checkoutSession = session.id,
countryCode = "US",
vaultedToken = card.vaultedToken,
yunoCreatePayment = { token ->
createPayment(token)
},
yunoPaymentResult = { result ->
if (result.status == PaymentStatus.SUCCEEDED) {
activity.startActivity(Intent(activity, SuccessActivity::class.java))
}
}
)
}
}Example 5: Custom Payment Method Selection
@Composable
fun CustomMethodSelectionScreen() {
var paymentMethods by remember { mutableStateOf<List<PaymentMethod>>(emptyList()) }
val context = LocalContext.current as ComponentActivity
LaunchedEffect(Unit) {
paymentMethods = fetchPaymentMethods()
}
LazyColumn {
items(paymentMethods) { method ->
ListItem(
headlineContent = { Text(method.name) },
leadingContent = {
AsyncImage(model = method.icon, contentDescription = null)
},
modifier = Modifier.clickable {
startPaymentWithMethod(context, method)
}
)
}
}
}
fun startPaymentWithMethod(activity: ComponentActivity, method: PaymentMethod) {
activity.lifecycleScope.launch {
val session = createCheckoutSession()
Yuno.startPaymentLite(
activity = activity,
checkoutSession = session.id,
countryCode = "US",
paymentMethodType = method.type,
yunoCreatePayment = { token -> createPayment(token) }
)
}
}Example 6: Error Handling with Retry
class PaymentWithRetryActivity : ComponentActivity() {
private var retryCount = 0
private val maxRetries = 3
fun attemptPayment() {
lifecycleScope.launch {
try {
val session = createCheckoutSession()
startPayment(session)
} catch (e: Exception) {
handleError(e)
}
}
}
private fun handleError(error: Exception) {
if (retryCount < maxRetries) {
retryCount++
lifecycleScope.launch {
delay(2000) // Wait 2 seconds
attemptPayment()
}
} else {
Toast.makeText(this, "Payment failed after $maxRetries attempts",
Toast.LENGTH_LONG).show()
}
}
private fun startPayment(session: CheckoutSession) {
Yuno.startCheckout(
activity = this,
checkoutSession = session.id,
countryCode = "US",
yunoCreatePayment = { token -> createPayment(token) },
yunoPaymentResult = { result ->
when (result.status) {
PaymentStatus.SUCCEEDED -> {
retryCount = 0
navigateToSuccess()
}
PaymentStatus.FAILED -> handleError(Exception(result.error?.message))
else -> {}
}
}
)
}
}Example 7: Analytics Integration
import com.google.firebase.analytics.FirebaseAnalytics
class PaymentWithAnalyticsActivity : ComponentActivity() {
private lateinit var analytics: FirebaseAnalytics
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
analytics = FirebaseAnalytics.getInstance(this)
analytics.logEvent("checkout_started", Bundle().apply {
putDouble("value", 25.00)
putString("currency", "USD")
})
startPayment()
}
private fun startPayment() {
lifecycleScope.launch {
val session = createCheckoutSession()
Yuno.startCheckout(
activity = this@PaymentWithAnalyticsActivity,
checkoutSession = session.id,
countryCode = "US",
yunoCreatePayment = { token ->
analytics.logEvent("begin_checkout", Bundle())
createPayment(token)
},
yunoPaymentResult = { result ->
when (result.status) {
PaymentStatus.SUCCEEDED -> {
analytics.logEvent(FirebaseAnalytics.Event.PURCHASE, Bundle().apply {
putString("transaction_id", result.paymentId)
putDouble("value", 25.00)
putString("currency", "USD")
})
navigateToSuccess()
}
PaymentStatus.FAILED -> {
analytics.logEvent("payment_failed", Bundle().apply {
putString("reason", result.error?.code ?: "unknown")
})
}
else -> {}
}
}
)
}
}
}Example 8: ViewModel Architecture
class PaymentViewModel : ViewModel() {
private val _paymentState = MutableStateFlow<PaymentState>(PaymentState.Idle)
val paymentState: StateFlow<PaymentState> = _paymentState
sealed class PaymentState {
object Idle : PaymentState()
object Loading : PaymentState()
data class Success(val paymentId: String) : PaymentState()
data class Error(val message: String) : PaymentState()
}
fun processPayment(activity: ComponentActivity) {
viewModelScope.launch {
_paymentState.value = PaymentState.Loading
try {
val session = createCheckoutSession()
Yuno.startCheckout(
activity = activity,
checkoutSession = session.id,
countryCode = "US",
yunoCreatePayment = { token ->
createPayment(token)
},
yunoPaymentResult = { result ->
_paymentState.value = when (result.status) {
PaymentStatus.SUCCEEDED -> PaymentState.Success(result.paymentId)
PaymentStatus.FAILED -> PaymentState.Error(
result.error?.message ?: "Payment failed"
)
else -> PaymentState.Idle
}
}
)
} catch (e: Exception) {
_paymentState.value = PaymentState.Error(e.message ?: "Unknown error")
}
}
}
}
// Usage in Compose
@Composable
fun PaymentScreen(viewModel: PaymentViewModel = viewModel()) {
val state by viewModel.paymentState.collectAsState()
val context = LocalContext.current as ComponentActivity
when (val currentState = state) {
is PaymentViewModel.PaymentState.Idle -> {
Button(onClick = { viewModel.processPayment(context) }) {
Text("Pay Now")
}
}
is PaymentViewModel.PaymentState.Loading -> {
CircularProgressIndicator()
}
is PaymentViewModel.PaymentState.Success -> {
Text("Payment successful!")
}
is PaymentViewModel.PaymentState.Error -> {
Text("Error: ${currentState.message}", color = Color.Red)
}
}
}Example 9: Multi-Step Checkout
@Composable
fun MultiStepCheckoutScreen() {
var currentStep by remember { mutableStateOf(CheckoutStep.CART) }
val context = LocalContext.current as ComponentActivity
when (currentStep) {
CheckoutStep.CART -> {
CartScreen(onProceed = { currentStep = CheckoutStep.SHIPPING })
}
CheckoutStep.SHIPPING -> {
ShippingScreen(onProceed = { currentStep = CheckoutStep.PAYMENT })
}
CheckoutStep.PAYMENT -> {
Column {
Text("Payment", fontSize = 24.sp)
Button(onClick = {
processPayment(context) { success ->
if (success) currentStep = CheckoutStep.CONFIRMATION
}
}) {
Text("Pay $25.00")
}
}
}
CheckoutStep.CONFIRMATION -> {
ConfirmationScreen()
}
}
}
enum class CheckoutStep {
CART, SHIPPING, PAYMENT, CONFIRMATION
}Example 10: Themed Payment UI
@Composable
fun ThemedPaymentScreen() {
MaterialTheme(
colorScheme = darkColorScheme(
primary = Color(0xFF007bff),
background = Color(0xFF1a1a1a),
surface = Color(0xFF2a2a2a)
)
) {
Surface {
PaymentContent()
}
}
}
// Apply Yuno theme
fun applyYunoTheme(context: Context) {
Yuno.setTheme(R.style.YunoSDKTheme)
}Backend API Helper
object YunoAPIClient {
private val client = OkHttpClient()
private val gson = Gson()
suspend fun createCheckoutSession(amount: Int, currency: String = "USD"): CheckoutSession {
return withContext(Dispatchers.IO) {
val json = gson.toJson(mapOf(
"amount" to mapOf("currency" to currency, "value" to amount),
"customer_id" to "cus_123",
"country" to "US"
))
val request = Request.Builder()
.url("https://api.example.com/checkout")
.post(json.toRequestBody("application/json".toMediaType()))
.build()
val response = client.newCall(request).execute()
gson.fromJson(response.body?.string(), CheckoutSession::class.java)
}
}
suspend fun createPayment(token: String, sessionId: String): Payment {
return withContext(Dispatchers.IO) {
val json = gson.toJson(mapOf(
"one_time_token" to token,
"checkout_session" to sessionId
))
val request = Request.Builder()
.url("https://api.example.com/payment")
.post(json.toRequestBody("application/json".toMediaType()))
.build()
val response = client.newCall(request).execute()
gson.fromJson(response.body?.string(), Payment::class.java)
}
}
}Updated about 18 hours ago