Skip to contentSkip to footer

We value your privacy

Our website uses cookies to provide online services and functionality that we would otherwise not be able to provide. Please click on 'I agree' to confirm the use of cookies on our website.

August 30, 2025

Read time: 10 min

eSIM functionality in Flutter

We used Flutter to create a prepaid mobile plans application and implemented the eSIM functionality for both Android and iOS. We poured over the documentation and forums and have written down our findings.

Blog post image

One of our latest projects was a prepaid mobile plans application for one of Slovenia's largers telecommunications providers. We opted to use Flutter which is a cross-platform framework that allows for a single codebase for multiple operating systems, in this case Android and iOS. One of the main challenges while creating the application for the functionality to install eSIMs straight from the application without using a QR code or any external methods. In this post we'll share our findings and explain how we managed to implement it for both Android and iOS.

eSIM functionality

The APIs for adding eSIMs to a device for this are locked down on both operating systems and you need some special permissions and entitlements, but it's honestly not that hard to do once you get pointed in the right direction.

eSIM profile

An eSIM profile that you get from your eSIM provider usually looks like this:

LPA:1$prod.smdp-plus.rsp.goog$052X-UFXS-CQIY-PNGL

This is an example from https://source.android.com/docs/core/connect/esim-test-profiles. A profile is comprised of two parts, the address (prod.smdp-plus.rsp.goog) and the matching ID (052X-UFXS-CQIY-PNGL).

Android

Android has multiple ways of adding an eSIM directly from an application, but some of them only work on specific devices:

  1. Using the local profile assistant app (LPA) activation flow
  2. Using the eSIM token as an intent
  3. Using the EuiccManager

All of them are described in more detail here: https://source.android.com/docs/core/connect/esim-overview, but we will give a brief overview in the following sections.

Using the local profile assistant app activation flow

This does not require any special permissions or changes to the eSIM profile metadata. We have implemented this flow successfully, however it only appears to work on Samsung devices (maybe some others as well, but the Samsung phones were the only ones among the tested devices that actually worked). This flow depends heavily on the LPA implementation of the manufacturer as the LPA is a system application.

Our implementation follows the documentation that is available here: https://source.android.com/docs/core/connect/esim-overview#activation-code.

Using the eSIM token as an intent

This is a fairly simple approach but apparently only works on Pixel phones or possibly phones close to AOSP (the pure Android source code). This also does not require any special permissions or changes to the eSIM profile metadata. The implementation is as follows:

val lpa = "LPA:1$..."

val intent = Intent(Intent.ACTION_VIEW)

intent.data  = Uri.parse(lpa)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK

startActivity(intent)

As you can see we simply create a new intent, set its data as the eSIM token and we're done. The system opens the eSIM activation settings and we can continue from there.

Using the EuiccManager

Both of the previous approaches do not require any special permissions but they do not work on all devices and they also do not provide any information on whether the eSIM was successfully added. This is where the last approach comes in.

The EuiccManager is the standard way of implementing the eSIM functionality in an application as it works on all Android devices running Android 9 or above, but it does require carrier privileges which in turn require some additional changes from your operator or rather the eSIM provider. The process is as follows:

  1. You sign the AAB or the APK with your key, be it a development or a production key, and get the SHA-256 signature.
  2. Get the package name of your application.
  3. The operator/eSIM provider now needs to add three things to the eSIM profile metadata (read here for more detail: https://source.android.com/docs/core/connect/uicc#rules_on_uicc):
    1. DeviceAppID-REF-DO: This is the SHA-256 signature of your application.
    2. PKG-REF-DO: This is the package name of your application.
    3. PERM-AR-DO: This is an 8-byte mask representing 64 separate permissions.
      • NOTE: This is not used at the moment but is there for future use as written in the documentation. Set it to any value you like, for example 0000000000000001.
  4. Once the operator/eSIM provider has added these values to the eSIM profile metadata you can start using the EuiccManager API.
  5. When attempting to add/update/remove the eSIM subscription Android will verify that the SHA-256 signature and the package name match the application's signature and package name. If this is true you now have carrier privilege over the eSIM profile.

The Android documentation on eSIM is quite good so just follow the steps outlined here to implement it in your app: https://source.android.com/docs/core/connect/esim-overview#euicc-manager.

iOS

On iOS you have two ways of adding an eSIM from your application:

  1. Using the Apple Universal Link for eSIM
  2. Using the integrated methods to install an eSIM profile

This is the easiest way to add an eSIM on iOS, you simply add your token to this URL in place of {LPA_TOKEN} https://esimsetup.apple.com/esim_qrcode_provisioning?carddata={LPA_TOKEN} and open the URL. The system will parse the response and open the system settings for adding an eSIM. That's it, you're done. The downside however is that you don't get any callbacks whether the eSIM was added successfully or not and also you are moved away from your application when the settings open.

Using the integrated methods to install an eSIM profile

To manage eSIMs directly on iOS using the integrated methods you need a so-called eSIM entitlement which is tied to your profile. To receive the entitlement you need to contact an Apple Sales Representative directly and explain your use case. Apple then reviews your application and grants or denies the eSIM entitlement. This can take from a week to multiple months (as read on some forums). We were lucky because Apple got back to us in under two weeks but this was a very large telecommunications provider that already had all the necessary infrastructure and processes in place for eSIM management.

Once you have the eSIM entitlement set up you can start using the CTCellularPlanProvisioning class which is in the Core Telephony framework. The implementation is rather simple:

let ctcp =  CTCellularPlanProvisioning()

func installEsimProfile(address: String, matchingID: String, completion: @escaping (String) -> Void) {
    let ctpr = CTCellularPlanProvisioningRequest();

    ctpr.address = address;
    ctpr.matchingID = matchingID;

    if #available(iOS 12.0, *) {
        ctcp.addPlan(with: ctpr) { (result) in
            switch result {
            case .unknown:
                completion("unknown")
            case .fail:
                completion("error")
            case .success:
                completion("success")
            case .cancel:
                completion("error")
            @unknown default:
                completion("unknown")
            }
        }
    } else {
        completion("error")
    }
}

If the eSIM was added successfully you get a success response and that's it.

Conclusion

We hope you found this short article helpful in implementing your own eSIM application. It is a bit cumbersome and time consuming but you'll get there in the end.