- Print
Lifecycle Management
- Print
The App lifecycle is how the platform informs your App how to behave based on its state. These lifecycle states determine which features and APIs should be used and when.
What are the App States
States are how your App understands whether it is the user's primary focus and if certain capabilities, e.g. receiving remote key presses, are available. The states your App can be in are as follows.
Lifecycle State | Description |
---|---|
not running | Application is not running and not loaded in memory |
| Application is loaded but not visible. It does not receive any remote/keyboard input and cannot play media. It must free any non-required memory (such as AV buffers) and minimize network and CPU usage (ie: disable or reduce the frequency of timers, disabling animations, closing web sockets). It should replace the UI with a full-screen loading splash screen so that this will be the first thing displayed when transitioning into Active or Background state. |
| Inactive App has been suspended to RAM so no resources are available, but will maintain state. |
| Application is visible full screen, receives inputs, and can play media. |
| Application is partially or not visible, can play media, and does not receive key press events except for play and pause. |
What is an App State Transition
A state transition is when the platform moves your App from one state, for example going from inactive
, to another, foreground
.
This image represents all of the possible states your App can transition to and from:
When your App is first loaded it will stay in the transitory initializing
state. The platform will never transition your App out of the initializing
state until you call ready()
. Once ready()
is called, your App will be moved to the inactive
state.
Note: All PVS apps must call discovery.contentAccess
and discovery.signIn
while in the inactive
state.
Your App will not transition to foreground
without going through either inactive
or background
first.
App Responsibility for each State
When your App transitions into a new state, it should handle some responsibilities to ensure the efficient running of all Apps.
Lifecycle State | Responsibilities |
---|---|
| Free any unrequired memory (such as AV buffers) and minimize network and CPU usage (ie: disable or reduce the frequency of timers, disabling animations, closing web sockets). It may replace the UI with a full-screen loading splash screen so that this will be the first thing displayed when transitioning into the |
| When returning from |
| The only responsibility here is to provide a great experience for your users! |
| Consider reducing video quality |
| The |
Managing your App's Lifecycle
Getting your app Ready
In order to give your App complete control over when it is presented to the user, the X1 Platform provides the Lifecycle.ready()
method. This allows the X1 Platform to wait for your App to be functionally and visually prepared for the user, and prevents the X1 Platform from waiting any longer than necessary.
This needs to be called before your App can be put into the foreground
. This must only be called once. If your app is going to respond to any event(s) then it’s a best practice to listen()
to those events before calling ready()
.
Your App is ready when these three requirements are met.
Requirement | Description |
---|---|
Response Time | The time it takes for your App to show a response to a user key-press must be less than 100ms. For example, user selects 'play' and it either starts playing or a 'loading' icon appears within 100ms. |
Playback Start | The amount of time between a user requesting playback and the asset starting playback must be less than 3 seconds. |
Deep Linking | Your App must support Deep Linking |
Here is an example that listens for deep links, and then calls ready()
:
import { Lifecycle, Discovery } from '@firebolt-js/sdk'
Discovery.listen('navigateTo', (value) => {
if (value.action == 'entity') {
// navigate to the entity page
callMyCustomNavigateFunction(value.data.entityId)
}
}
Lifecycle.ready()
This example shows how an App can use the Discovery.listen()
to ready itself for when the user wants to go to a specific piece of content. When the App is .ready() it will give the user the ability to find that content.
Note that callMyCustomNavigateFunction
is just a placeholder for your own, much better-named method.
Responding to State Transitions
Lifecycle.listen()
is how your App will know it’s being moved from state to state. This allows your App to behave accordingly. Aside from calling ready()
it’s the most fundamental aspect of using the App Lifecycle API.
Here is an example of an App that listens to all of the Lifecycle events, and handles some of them:
import { Lifecycle } from '@firebolt-js/sdk'
Lifecycle.listen( (event, value) => {
// this code runs for every lifecycle event
if (value.state === 'foreground') {
// the user is now being presented your app as the main experience
} else if (value.state === 'inactive') {
// Stop playing video, e.g. video.src = ‘’
if (value.previous === 'suspended') {
// when your app goes from suspended to inactive, you probably want to refresh and tokens/sessions/timers, etc.
}
}
})
Note that each if/else
clause is left empty, as you know better what your app will do then we do!
The suspended state will allow the app to be brought to a foreground or background state more quickly, without requiring a full app initialization and creation of a new browser session – the result will be a much faster app experience for users.
Suspended State
A suspended app may be called back into focus, and it will go through the inactive state on its way to a foreground state for the user to begin interacting with your app.
While in the inactive state, your app should:
Reduce its resource footprint.
Shut down all non-essential scripts (including analytics/‘phone home’ calls)
Non-essential listener calls should be terminated.
Tear down all UI elements. Some apps may choose to display a static image.
The device will automatically reclaim any AV decoder in use, but your app should take any steps to disengage the media pipeline.
Some apps may rely on a clock and/or a counter even while in an inactive state. To ensure compatibility when returning from a suspended state, clocks and counters should be re-initialized when brought to inactive.
Closing your App
Once in a while, you will need to close your app; for example, the user pressed the last
remote button at the top of your app UI.
The Lifecycle.close()
method instructs the platform to stop presenting your App to the user. This method has a mandatory reason
parameter that gives your App a way to influence which state it might be transitioned to.
The X1 Platform will make the determination of how it will transition your App and it can be one of four possible transitions –
It could move your App into
background
, so that video may continue playingIt could move your App into
inactive
, and then Lifecycle Management shortly afterIt could move your App into
inactive
, and thensuspended
shortly afterIt could move your App into
inactive
, and leave it there until the user decides to return
In order to help the X1 Platform determine why your App is requesting to be closed, one of the following values must be provided:
Reason | Description |
---|---|
| The User explicitly selected an exit control that is rendered within your App UX. |
| The User pressed the |
| Your App encountered an unrecoverable error, and needs to be exited. See |
Even if your App is closed it may not be unloaded.
Unloading your App
A user may need more CPU and/or memory, and if your App is not demanded, the X1 Platform will send an unloading
event. When that happens it is strongly recommended that you do any final operations your App needs to do, and then call Lifecylce.finished()
.
After receiving the unloading
event, your App can handle any Metrics or other clean-up tasks.
There is a small amount of time that your App can perform these processes, so do them quickly.
It’s also recommended that your App Listening for Events during this time.
Once the App has gone through these phases it should call Lifecylce.finished()
.
This allows the X1 Platform to ensure that the device optimizes memory and CPU giving users the best experience available.
Navigation Intents
Generally, when an Application is deep-linked, the deep link parameters are sent via the initial launch URL. However, as an application may already be in an inactive
, foreground
, or background
state, the App must also support responding to deep-links without a reload.
In the X1 Platform, these are called "Navigation Intents".
Some of the use cases enabled via Navigation Intents are:
Allow a user click on your content in the platform EPG experience when your App is already loaded and in the
inactive
state.Allow a user to quickly go to their “Most recently watched” programs from the X1 Platform home screen into your App with a single action.
Allow a user to navigate from one part of your App to a particular piece of content by using the Voice Remote
Allow a user to navigate from outside of your App to a particular piece of content by using the Voice Remote without waiting for a full cold launch of your App
Allow a user to navigate to a specific non-entity "section" of your site, Example: Tell my App to pull up my “Recently Watched List” via my remote.
Here is an example of handling Navigation Intents in your App:
import { Discovery } from '@firebolt-js/sdk'
Discovery.listen('navigateTo', (value) => {
// navigate to a specific program entity
if (value.action === 'entity') {
// navigate to the player page for episodes
if (value.data.programType === 'episode') {
myAppPlayContent(value.data.entityId, value.data.assetId)
}
// navigate to an entity details page for a series
else if (value.data.programType === 'series') {
myAppNavigateToEntityPage(value.data.entityId)
}
}
// navigate to a non-program section of the site
else if (value.action === 'section')
{
// navigate to the recently watched section of your app
if (value.data.sectionName === '<your custom recently watched section name>') {
myAppNavigateToSection(value.data.sectionName)
}
}
}
Lifecycle.ready()
Note that this is just an example to show usage of the navigateTo
event. All of the myAppXXX
methods are made up.
Fast App Switching
The X1 Platform allows your App to be pre-loaded on device start-up and suspended after use, allowing subsequent fast access to the application, collectively known as Quickstart. In order for your App to support Fast App Switching, you must implement the following functionality and the associated event handlers and APIs:
Getting your App Ready
Responding to State Transitions
Navigation Intents