Using mobile SDKs
Read time: 5 minutes
Last edited: Nov 04, 2021
This guide explores some best practices for using LaunchDarkly’s mobile SDKs.
Mobile app development contains plenty of challenges. Your app will face wildly variable conditions: many different devices and runtime environments, and unstable data connections. We’ve done our best to provide robust and efficient performance in our mobile SDKs. In addition, we provide these recommendations to improve the quality of your user experience.
Every millisecond counts during app launch. Your app is likely to initialize many different components before presenting a live interface to the user. The LaunchDarkly SDK is one of them.
When initializing, the LaunchDarkly SDK attempts these steps:
- Open a network connection to the feature server
- Download relevant flag data
- If the SDK has cached flag data from a previous session, then trigger event handlers for flags that have changed since they were cached
To avoid delays caused by LaunchDarkly connection setup, initialize the
LDClient object asynchronously so that it doesn’t block other code from executing.
The asynchronous initialization process is different for each SDK.
We recommend using
LdClient.InitAsync(key, user) to initialize the SDK, as it runs asynchronously. The alternative method,
LdClient.Init(key, user, timeout) blocks until either it has retrieved flag data or it has exceeded the timeout period.
The Android SDK’s
LDClient.init() method takes, as its fourth parameter, a timeout integer which specifies the maximum number of seconds the SDK can wait for a response from the server.
Depending on how
init() is called, the SDK may block the current thread until either the flags are retrieved or the timeout period is exceeded. If
init() is called in the main app thread, the rest of the app startup will be blocked until this call completes, resulting in poor user experience.
To ensure that
LDClient.init() doesn’t block the rest of the app, use any of these techniques:
init()a timeout value of
init()method returns an
LDClientimmediately but continues creating the connection in the background. If cached flag data is available from a previous execution, any invocation of a
variation()method will use that cached data until the SDK receives fresh data. Otherwise, it will use the fallback value specified in the invocation. You can also use change listeners to respond when the SDK updates the flag cache.
- Call this overload for
init()which returns a
Future. Wait for it to complete on a separate thread/executor to implement a timeout behavior without blocking the application using
- Move the
init()call to its own thread.
LDClient.start() executes asynchronously to avoid blocking the main thread. To execute code as soon as flags have been retrieved,
start() supports an optional
You can also provide a
startWaitSeconds timeout value to set a maximum waiting period for establishing the connection. A
timedOut boolean will be supplied to the
completion closure, indicating whether the connection timed out.
LaunchDarkly delivers flag updates to your app as soon as possible. This is great for ensuring that flag evaluations are up to date with the current flag settings, but may cause problems depending on how the flag is used. For example, consider a user interface configured by flags. If the flags change in the middle of a user session, the user may be confused or alarmed by the interface changing without warning.
For each flag used by your app, decide on a policy for how updates to the flag should be handled while the app is running. You may want to ignore updates to certain flags if they happen in the middle of a user session, whereas other flags, such as kill switches, should update immediately.
These policies can be implemented as wrapper methods around the LaunchDarkly SDK, rather than configuration changes to the SDK itself.
The LaunchDarkly mobile SDKs automatically provide and fill two custom user attributes:
device. These attributes are automatically populated with information about the user's operating system and hardware, so that it's easier to target specific configurations. Because of this, we recommend that your code provide a custom attribute that contains the app version number.
This combination of attributes is particularly useful for targeting the release of new features. For example, consider a “dark mode” feature being added to an app. Versions 10 to 14 contain early, incomplete versions of the feature. These versions are available to all users, but the “dark mode” feature is only enabled for testers. With version 15, the feature is considered complete and enabled for all users. Unfortunately, some users are still using an older version of the app. When the feature is enabled, they encounter bugs.
Including the app version number in the user attributes makes it possible for you to add a flag rule which targets that version. This is also useful for situations when you must disable a feature due to code issues, which you then fix in a later release. By targeting the app version, you can re-enable the feature only for those users running the corrected code.
How big is the SDK? How much will it increase the download size of my app?
SDK size depends on the platform, SDK, SDK version, and platform-specific dependencies you are using. We try to keep our SDKs small, though on some platforms they introduce some larger dependencies. In practice, they’re likely to be one of the smaller dependencies in your app.
How does using the SDK affect memory and battery usage?
Our mobile SDKs consume resources differently depending on whether the host app is running in the foreground or background.
When running in the foreground, the SDK maintains a persistent HTTPS connection to LaunchDarkly. When a flag changes, LaunchDarkly uses the Server-Sent Events (SSE) protocol to notify the app of changes. The alternative method of receiving updates is for the SDK to poll the LaunchDarkly service with regular short requests.
Most evidence shows that when appropriately configured, persistent HTTPS connections result in longer battery life than polling for our connection and data transfer patterns. A 2013 study showed that an open SSE connection with low-frequency event updates (under 120 seconds) and heartbeats has negligible impact on battery life.
Our app will be reviewed by Apple for inclusion in the App Store. Will Apple reviewers raise issues around our use of LaunchDarkly, and how can we avoid or resolve these issues?
Apple’s App Store policies and the actions of their reviewers are beyond our control or ability to predict. Apple has, in the past, raised concerns about code which is present in an app but which doesn’t seem to be reachable during testing. Customers who’ve encountered this problem told us that they resolved it by enabling all features for the app version being tested, then disabling unlaunched features before release.
What data collection information should be added to our submission to the Apple App Store?
Since December 2020, the Apple App Store requires apps you submit to provide information about their privacy practices, including the practices of third-party partners whose code is integrated into the app. If you integrate a LaunchDarkly SDK into your app and submit it to the Apple App Store, you must disclose which data LaunchDarkly collects. To learn more about the data which LaunchDarkly may collect, read Apple App Store data collection policy.