Lifecycle Management

    Lifecycle Management


    Article summary

    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

    inactive

    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.
    Note: All PVS apps must call discovery.contentAccess and discovery.signIn while in the inactive state.

    suspended

    Inactive App has been suspended to RAM so no resources are available, but will maintain state.
    Note: Only ES1 Devices currently support the suspended lifecycle state.

    foreground (Active)

    Application is visible full screen, receives inputs, and can play media.

    background (Active)

    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

    inactive

    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 foreground or background states.
    Note: All PVS apps must call discovery.contentAccess and discovery.signIn while in the inactive state.

    inactive (from suspended)

    When returning from suspended your App may need to refresh any sessions, timers, or tokens that it uses to run smoothly. suspended Apps have had their CPU usage frozen for un unknown amount of time.

    foreground

    The only responsibility here is to provide a great experience for your users!

    background

    Consider reducing video quality

    suspended

    The inactive state and the suspended state are effectively the same. However, when an app transitions out of the suspended state, it may need to update its timers or clocks to ensure they are current.

    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 playing

    • It could move your App into inactive, and then Lifecycle Management shortly after

    • It could move your App into inactive, and then suspended shortly after

    • It 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

    userExit

    The User explicitly selected an exit control that is rendered within your App UX.

    remoteButton

    The User pressed the last button on their remote from your App’s Home page.

    error

    Your App encountered an unrecoverable error, and needs to be exited. See Metrics.error().

    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

    Example State Flows

    Cold Launch

    image.png

    Hot Launch

    image.png

    User Opens Platform Settings

    image.png


    Was this article helpful?