Development
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.

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:
- Using the local profile assistant app (LPA) activation flow
- Using the eSIM token as an intent
- 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:
- You sign the AAB or the APK with your key, be it a development or a production key, and get the SHA-256 signature.
- Get the package name of your application.
- 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):
- DeviceAppID-REF-DO: This is the SHA-256 signature of your application.
- PKG-REF-DO: This is the package name of your application.
- 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.
- Once the operator/eSIM provider has added these values to the eSIM profile metadata you can start using the
EuiccManager
API. - 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:
- Using the Apple Universal Link for eSIM
- Using the integrated methods to install an eSIM profile
Using the Apple Universal Link for eSIM
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.