Roku SDK reference
Read time: 2 minutes
Last edited: Jul 23, 2020
This reference guide documents basic usage of our Roku SDK, and explains in detail how features work. If you want to dig even deeper, our SDKs are open source. To learn more, read Roku Client GitHub repository. The complete API reference is available here. Additionally you can clone and run a sample application using this SDK.
The Roku SDK is written in BrightScript.
Getting started
Building on top of our Getting Started guide, the following steps will get you started with using the LaunchDarkly SDK in your Roku Application.
We provide releases on GitHub. Download the latest release and extract the provided files into your source tree. You may need to rename the paths inside LaunchDarklyTask.xml
depending on your project structure.
For SceneGraph usage add a LaunchDarklyTask
node to your scene and then:
1REM get a reference to to task2launchDarklyNode = m.top.findNode("my-node-name")34REM create configuration5config = LaunchDarklyConfig("MY_MOBILE_KEY", launchDarklyNode)67REM create a user8user = LaunchDarklyUser("user-key")910REM initialize the client11LaunchDarklySGInit(config, user)
For each SceneGraph component you want to use the SDK in you need to initialize an interface to talk to the SceneGraph. This interface provides all the expected client functionality such as evaluation.
1REM create the scenegraph communication wrapper2launchDarkly = LaunchDarklySG(launchDarklyNode)34REM use the client5value = launchDarkly.boolVariation("MY_FLAG_KEY", false)
Creating a client outside of the SceneGraph API is similar. In the legacy API you do not need LaunchDarklySGInit
or the LaunchDarklySG
functions.
1REM get a reference to the task2launchDarklyNode = m.top.findNode("MY_NODE_NAME")34REM create configuration5config = LaunchDarklyConfig("MY_MOBILE_KEY", launchDarklyNode)67REM create a user8user = LaunchDarklyUser("user-key")91011REM create message port12messagePort = createObject("roMessagePort")1314REM initialize the client15launchDarkly = LaunchDarkly(config, user, messagePort)161718REM use the client19value = launchDarkly.boolVariation("MY_FLAG_KEY", false)
If not using the SceneGraph you need to poll events to drive the client in your standard event loop.
1while (true)23 REM do not wait forever or timers will break4 msg = wait(3000, messagePort)567 if launchDarkly.handleMessage(msg) then8 REM this message was for the client9 else10 REM handle non client messages11 end if12end while
Variation
The *variation
methods determine which variation of a feature flag a user receives.
1REM typed variations2myInt = launchDarkly.intVariation("MY_FLAG_KEY", 123)34myBool = launchDarkly.boolVariation("MY_FLAG_KEY", false)56myString = launchDarkly.stringVariation("MY_FLAG_KEY", "hello world!")78myObjectOrArray = launchDarkly.jsonVariation("MY_FLAG_KEY", {"value": 123})910REM generic variation11myValue = launchDarkly.variation("MY_FLAG_KEY", false)
*variation
calls take a feature flag key and a default value.
The default value will only be returned if an error is encountered—for example, if the feature flag key doesn't exist or the user doesn't have a key specified.
VariationDetail
For each variation type there is also an associated version that returns the reason a particular value was returned. For example:
1details = launchDarkly.intVariationDetail("MY_FLAG_KEY", 123)
These variation methods return an object containing the keys value
, reason
, and variationIndex
. The value
field is the result of the evaluation. The reason
field is an object that explains why the result happened, for example details about a rule match. The reason object will always contain a kind
field. Lastly the (potentially null) variationIndex
field contains the id of the particular value returned.
Customizing your client
You can create a client configuration object with:
1REM for a legacy Roku application2config = LaunchDarklyConfig("YOUR_MOBILE_KEY")34REM for a SceneGraph Roku Application5config = LaunchDarklyConfig("YOUR_MOBILE_KEY", CLIENT_SCENEGRAPH_NODE)
We support the following configuration options for both SceneGraph and non SceneGraph usage:
1config.setAppURI(String)23config.setEventsURI(String)45config.setStreamURI(String)678config.setPollingIntervalSeconds(Integer)910config.setOffline(Boolean)111213config.addPrivateAttribute(String)1415config.setAllAttributesPrivate(Boolean)161718config.setEventsCapacity(Integer)1920config.setEventsFlushIntervalSeconds(Integer)2122config.setStreaming(Boolean)
Logging
Log levels
You can configure the SDK log level. For example to set the level to info
:
1config.setLogLevel(LaunchDarklyLogLevels().info)
The SDK supports the following Levels:
1LaunchDarklyLogLevels().error2LaunchDarklyLogLevels().warn3LaunchDarklyLogLevels().info4LaunchDarklyLogLevels().debug5LaunchDarklyLogLevels().none
A custom logging backend can be provided. This will be different depending on if you are using the SceneGraph API or the Legacy API.
Legacy API Custom Logger
1function CustomLogger() as Object2 return {3 log: function(level as Integer, message as String)45 print level message6 end function7 }8end function910config.setLogger(CustomLogger())
SceneGraph API Custom Logger
1<!-- /components/CustomLogger.xml -->23<component name="CustomLogger" extends="Task">4 <interface>5 <field id="log" type="assocarray" alwaysNotify="true"/>6 </interface>78 <script type="text/brightscript" uri="pkg:/components/CustomLogger.brs"/>9</component>
1REM /components/CustomLogger.brs23function init()45 m.messagePort = createObject("roMessagePort")678 m.top.observeField("log", m.messagePort)910end function1112function mainThread() as Void13 while (true)1415 msg = wait(0, m.messagePort)161718 if type(msg) = "roSGNodeEvent" then19 if field = "log" then20 value = msg.getData()2122 print value.level value.message23 end if24 end if25 end while26end function
To use the logger create the SceneGraph logger node and then:
1config.setLoggerNode(myLoggerNode)
Users
You can create a user object with:
1user = LaunchDarklyUser("my-user-key")
User objects can be customized with:
1user.setFirstName(String)23user.setLastName(String)45user.setEmail(String)67user.setName(String)89user.setAvatar(String)1011user.setCustom(AssociativeArray)
A user can be marked as anonymous with:
1user.setAnonymous(Boolean)
Users can have specific fields marked as private with:
1user.addPrivateAttribute(String)
Track
The track method allows you to record custom events in your application with LaunchDarkly:
1REM without optional data2launchDarkly.track("YOUR_EVENT_KEY")34REM with optional data5launchDarkly.track("YOUR_EVENT_KEY", {"customField": 123})67REM with optional numeric metric8launchDarkly.track("YOUR_EVENT_KEY", invalid, 52.3)
Flush
Internally, the LaunchDarkly SDK keeps an event buffer for analytics events. These are flushed periodically in a background thread. In some situations (for example, if you're testing out the SDK in a simulator), you may want to manually call flush to process events immediately.
1launchDarkly.flush()
Changing the user context
If your app is used by multiple users on a single device, you may want to change users and have separate flag settings for each user. To achieve this, the SDK supports switching between different user contexts.
1user = LaunchDarklyUser("abc")23launchDarkly.identify(user)
The identify
call will load any saved flag values for the new user and immediately trigger an update of the latest flags from LaunchDarkly. Since this method re-fetches flag settings for the new user, it should not be called at high frequency. The intended use case for switching user contexts is the login / logout flow.
All flags
You can get an associative array of flagKey
-> flagValue
for all flags from the client with:
1allFlags = launchDarkly.allFlags()