eSIM profile activation via mobile app

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
eSIM profile activation via mobile app
Complex
from 1 week to 3 months
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Implementing eSIM Profile Activation in Mobile App

eSIM activation is the most painful telecom user experience if implemented wrong. User enters activation code, sees spinner 30 seconds, gets "Activation error." What went wrong — app doesn't know. SM-DP+ server returned SGP.22 error code, LPA processed it, platform wrapped it in opaque resultCode. Task — dig to real cause and show human-readable message.

Activation Code: Formats and Sources

SGP.22 defines two ways to deliver activation code to user:

QR code — standard format: LPA:1$smdp-plus.operator.com$ABC123XYZ. Scanning — via native platform capabilities or built-in app scanner. On iOS can open system activation directly.

Manual Entry — same string code, entered manually. Validate format before sending: LPA:1$ presence, correct SM-DP+ FQDN, Matching ID without forbidden characters.

// Validation of activation code format
fun validateActivationCode(code: String): Boolean {
    val pattern = Regex("""^LPA:1\$[a-zA-Z0-9\-.]+\$[a-zA-Z0-9\-]+(\$[a-zA-Z0-9.]+(\$[01])?)?$""")
    return pattern.matches(code.trim())
}

Android: Step-by-Step Activation with Error Handling

EuiccManager.downloadSubscription() is the main method for carrier-privileged apps:

private fun activateEsimProfile(activationCode: String) {
    val subscription = DownloadableSubscription.forActivationCode(activationCode)

    // switchAfterDownload flag: true — profile activates immediately
    // false — loads in disabled state, activated separately
    euiccManager.downloadSubscription(
        subscription,
        switchAfterDownload = true,
        cancellationSignal = CancellationSignal(),
        executor = mainExecutor
    ) { resultCode, extras ->
        when (resultCode) {
            EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK -> {
                val subscriptionId = extras?.getInt(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ID) ?: -1
                onActivationSuccess(subscriptionId)
            }

            EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR -> {
                // Requires user confirmation
                val intent = extras?.getParcelable<PendingIntent>(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT
                )
                intent?.send() // Opens system consent dialog
            }

            EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR -> {
                val detailedCode = extras?.getInt(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, -1
                ) ?: -1
                val operationCode = detailedCode and 0xFF
                val errorCode = (detailedCode shr 8) and 0xFF
                showActivationError(operationCode, errorCode)
            }
        }
    }
}

Error details via EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE:

Operation Code Error Code Cause Tell User
1 (DOWNLOAD) 2 Invalid activation code "Check activation code"
1 (DOWNLOAD) 3 Code already used "This code already activated"
2 (INSTALL) 8 No eUICC space "Delete unused profile"
3 (SWITCH) 1 SM-DP+ network error "Check internet connection"

iOS: System UI and QR

On iOS without carrier entitlement — only system activation dialog. Opens via URL:

func activateViaNativeUI(activationCode: String) {
    // Form URL for system activation
    let urlString = "com.apple.esim://\(activationCode)"
    if let url = URL(string: urlString), UIApplication.shared.canOpenURL(url) {
        UIApplication.shared.open(url) { success in
            if success {
                // System UI opened, wait for result via Universal Link callback
                startPollingForNewProfile()
            }
        }
    }
}

After activation via system UI — no direct callback to app. Need to poll CTSubscriptionManager or listen for CTSubscriberTokenRefreshed notification.

For carrier apps with entitlement — CTSubscriptionManagerDelegate:

import CoreTelephony

class ESIMActivationManager: NSObject, CTSubscriptionManagerDelegate {
    let subscriptionManager = CTSubscriptionManager()

    func activateProfile(activationCode: String) {
        subscriptionManager.delegate = self
        subscriptionManager.setAccountIdentifier(activationCode)
    }

    func subscriptionManagerCompleted(_ manager: CTSubscriptionManager) {
        DispatchQueue.main.async {
            self.handleActivationComplete()
        }
    }
}

States and Loading UX

eSIM activation takes 15 seconds to 3 minutes — SM-DP+ generates profile, LPA downloads and installs (usually 300–500 KB encrypted data). During this user shouldn't see static spinner.

Proper UX: steps with current state:

  1. Check activation code → Format validation
  2. Connect to operator → SM-DP+ request
  3. Download profile → Progress bar (if LPA provides progress)
  4. Install → Write to eUICC
  5. Activate → Switch to new profile

On Android downloadSubscription doesn't provide step-by-step progress. Fake progress with time estimation looks better than static spinner. Real progress only if using custom LPA via TelephonyManager.setPreferredOpportunisticDataSubscription.

Timeline

eSIM activation via Intent/system UI with error code handling: 1–2 weeks. Full EuiccManager integration for carrier app (Android) + CoreTelephony for iOS: 1–3 months including operator coordination and access setup.