Amazon Developer

as

Settings
Sign out
Notifications
Alexa
Amazon Appstore
Ring
AWS
Documentation
Support
Contact Us
My Cases
Get Started
Design and Develop
Publish
Reference
Support

VegaAppState

The notion of app state in the normal React Native context applies to the application process. An app as a whole is in front or backgrounded. On Vega there's a different notion. An app process can have separate interactive components that may be backgrounded or foregrounded. Therefore, the AppState module provided through 'react-native' does not support fetching and listening for app state changes for multiple interactive components that are part of the same application process.

On Vega, foregrounded (or active) means an interactive component can have visible UI. Backgrounded means all UI for that component is not visible. The app process itself is neither backgrounded or foregrounded.

Interactive components may have one or more windows. Whether or not a given window is an active responder to handle input events, like text input or clicks, is a separate matter. App state does not refer to the responder state of a particular window owned by a interactive component. It refers to the state of the component itself and in turn all of the UI elements it displays.

React Native for Vega provides new custom hooks and the KeplerAppStateManager for interactive components to listen to app state changes.

Methods

useVegaAppStateManager

useKeplerAppStateManager() is a custom hook that returns a KeplerAppStateManager instance that can be used to query and listen to app state changes. Please follow the React's Rules of Hooks when calling this hook.


useKeplerAppStateManager: () => IKeplerAppStateManager;


useGetCurrentKeplerAppStateCallback = (): () => KeplerAppStateStatus

Deprecated. Use getCurrentState from VegaAppStateManager instead.

useGetCurrentKeplerAppStateCallback is a custom hook that returns a callback that, when invoked, returns the current app state of your interactive component. Please follow the React's Rules of Hooks when calling this hook. The returned callback function takes no parameters and returns KeplerAppStateStatus, which is described below in the types section.

Note: Calling the hook does not return the app state. You have to invoke the callback function returned by the hook to get your interactive component's app state.


useAddKeplerAppStateListenerCallback = (): KeplerAppStateCallback

Deprecated. Use addEventListener from VegaAppStateManager instead.

useAddKeplerAppStateListenerCallback is a custom hook that returns a callback that, when invoked, adds a listener for the given event. Please follow the React's Rules of Hooks when calling this hook. The returned callback function, typed as KeplerAppStateCallback, takes two parameters, the event name (KeplerAppStateEvent) to subscribe to and the callback function (OnEventCallback) to invoke when the event occurs. The callback function returns a handle to the subscription. Call remove() to remove the subscription.

Note: Calling the hook does not register an app state listener. You have to invoke the callback function returned by the hook to register an app state listener.

Note: This method can also be called with a OnAppStateEventCallback callback (instead of OnEventCallback), but this variant is deprecated.


useAddKeplerAppStateListenerWithReplayCallback = (): () => KeplerAppStateWithReplay

Deprecated. Use addEventListenerWithReplay from VegaAppStateManager instead.

useAddKeplerAppStateListenerWithReplayCallback is a custom hook that returns a callback that, when invoked, adds a listener for the given event. The callback is immediately invoked if any past events have occurred before the app subscribed to the listeners (events will be replayed). Otherwise it behaves like useAddVegaAppStateListenerCallback. Please follow the React's Rules of Hooks when calling this hook. The returned callback function takes no parameters and returns KeplerAppStateWithReplay, which is described below in the types section.

Note: Replayed events will be sent in the order in which their respective listeners are added.

Note: Only the first listener of a particular event will receive the replayed event.

Note: Calling the hook does not register an app state listener. You have to invoke the callback function returned by the hook to register an app state listener.


useComponentInstance = (): () => IComponentInstance

Deprecated. Use getComponentInstance from VegaAppStateManager instead.

useComponentInstance is a custom hook that provides an interface, IComponentInstance, which represents an application component. This interface includes properties such as the component's name and type.


Classes

VegaAppStateManager

getCurrentState()


getCurrentState(): KeplerAppStateStatus

getCurrentState returns the current app state of your interactive component. It takes no parameters and returns KeplerAppStateStatus, which is described below in the types section.


addEventListener()


addEventListener(eventName: KeplerAppStateEvent, callback: OnEventCallback): EventSubscription 

Adds a listener for the given event.

addEventListener adds a listener for the given event. It takes two parameters, the event name (KeplerAppStateEvent) to subscribe to and the callback function (OnEventCallback) to invoke when the event occurs. Returns a handle to the subscription. Call remove() to remove the subscription.

This API is available starting from version 2.1.0 of @amazon-devices/react-native-kepler.


addAppStateListener()

Deprecated. Use addEventListener instead.


addAppStateListener(eventName: KeplerAppStateEvent, callback: OnEventCallback): EventSubscription 

Adds a listener for the given event.

addAppStateListener adds a listener for the given event. It takes two parameters, the event name (KeplerAppStateEvent) to subscribe to and the callback function (OnEventCallback) to invoke when the event occurs. Returns a handle to the subscription. Call remove() to remove the subscription.

Note: This is an older api that has same functionality as addEventListener. Api is kept for backward compatibility.


addEventListenerWithReplay()


addEventListenerWithReplay(eventName: KeplerAppStateEvent, callback: OnEventWithReplayCallback): EventSubscription 

addEventListenerWithReplay adds a listener for the given event and this will capture and replay the events that came before it was attached.

Note: Replayed events will be sent in the order in which their respective listeners are added.

Note: Only the first listener of a particular event will receive the replayed event.


getComponentInstance()


getComponentInstance(): IComponentInstance 

getComponentInstance returns an interface of type IComponentInstance, which represents an application component. This interface includes properties such as the component's name and type.


Types

type KeplerAppStateStatus = 'active' | 'background' | 'inactive' | 'unknown';

  • active: The app is running in the foreground.
  • background: The app is running in the background. The user is either in another app or on the home screen.
  • inactive: This is a transition state that currently never happens for typical React Native apps.
  • unknown : Initial value until the current app state is determined.

type KeplerAppStateEvent = 'change' | 'memoryWarning' | 'blur' | 'focus' | 'reconfigure' | 'displayChange';

  • change: This even is received when the app state has changed.
  • memoryWarning: Received when the app receives a memory warning.
  • focus: Received when the app gains focus (the user is interacting with the app).
  • blur: Received when the user is not actively interacting with the app.
  • reconfigure: Received when an application reconfiguration event occurs.
  • displayChange - Received when a display is connected or disconnected.

type KeplerAppReconfigureReason = 'homePressed';

KeplerReconfigureReasonData

Copied to clipboard.


interface KeplerReconfigureReasonData {
{
    rootTag: number;
    reconfigureReason: KeplerAppReconfigureReason;
}

KeplerAppStateWithReplay

Copied to clipboard.


interface KeplerAppStateWithReplay {
    isReplayed: boolean;
    appStateData?: KeplerAppStateChangeData | /** @deprecated Use VegaAppStateChangeData instead */ KeplerAppStateChange; 
    /** @deprecated Use appStateData instead */
    appState?: KeplerAppStateChange;
}

type KeplerAppDisplayStatus = 'displayDisconnected' | 'displayConnected';

type KeplerAppStateChangeData = KeplerAppStateStatus | KeplerReconfigureReasonData | KeplerAppDisplayStatus;

type KeplerAppStateChange = KeplerAppStateChangeData;

Deprecated. Use VegaAppStateChangeData instead.

type OnEventCallback = (event: KeplerAppStateChangeData) => void;

type OnEventWithReplayCallback = (event: KeplerAppStateWithReplay) => void;

type OnAppStateEventCallback = (event: KeplerAppStateChange) => void;

Deprecated. Use OnEventCallback instead.

type OnAppStateEventWithReplayCallback = (event: KeplerAppStateWithReplay) => void;

Deprecated. Use OnEventWithReplayCallback instead.

Sample Application

Copied to clipboard.


import {
    KeplerAppStateChangeData,
    KeplerAppStateStatus,
    KeplerAppStateWithReplay,
    KeplerReconfigureReasonData,
    KeplerAppDisplayStatus,
    IKeplerAppStateManager,
    useKeplerAppStateManager
} from '@amazon-devices/react-native-kepler';
import React, { useEffect, useState } from 'react';
import { AppRegistry, StyleSheet, Text, View } from 'react-native';

const styles = StyleSheet.create({
    container: {
        flex: 1,
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center'
    },
    displayText: {
        fontSize: 20,
        fontWeight: 'bold',
        color: 'white'
    },
    commentText: {
        fontSize: 16,
        color: 'white'
    }
});
const KeplerAppStateApp = () => {
    const keplerAppStateManager: IKeplerAppStateManager = useKeplerAppStateManager();
    const [appStateData, setAppState] = useState<KeplerAppStateStatus>(
        keplerAppStateManager.getCurrentState
    );
    const [homePressedCounter, setHomePressedCounter] = useState(0);
    const [displayDisconnectCounter, setDisplayDisconnectCounter] = useState(0);
    const [displayConnectCounter, setDisplayConnectCounter] = useState(0);
    const [appFocusState, setAppFocusState] = useState('FOCUSED');

    useEffect(() => {
        console.log('KeplerAppState demo: Adding event listeners');

        const changeSubscription = keplerAppStateManager.addEventListener(
            'change',
            handleAppStateChange
        );
        const memoryWarningSubscription = keplerAppStateManager.addEventListener(
            'memoryWarning',
            handleMemoryWarning
        );
        const reconfigureSubscription = keplerAppStateManager.addEventListener(
            'reconfigure',
            handleReconfigure
        );
        const focusSubscription = keplerAppStateManager.addEventListener(
            'focus',
            handleFocus
        );
        const blurSubscription = keplerAppStateManager.addEventListener(
            'blur',
            handleBlur
        );
        const displayChangeSubscription = keplerAppStateManager.addEventListener(
            'displayChange',
            handleDisplayChange
        );
        // Handle replayed events with addEventListenerWithReplay method from useVegaAppStateManager hook
        const changeWithReplaySubscription = keplerAppStateManager.addEventListenerWithReplay(
            'change',
            handleAppStateChangeWithReplayedEvents
        );
        const reconfigureWithReplaySubscription = keplerAppStateManager.addEventListenerWithReplay(
            'reconfigure',
            handleReconfigureWithReplayedEvents
        );
        const memoryWarningWithReplaySubscription = keplerAppStateManager.addEventListenerWithReplay(
            'memoryWarning',
            handleMemoryWarningWithReplayedEvents
        );
        const focusWithReplaySubscription = keplerAppStateManager.addEventListenerWithReplay(
            'focus',
            handleFocusWithReplayedEvents
        );
        const blurWithReplaySubscription = keplerAppStateManager.addEventListenerWithReplay(
            'blur',
            handleBlurWithReplayedEvents
        );
        const displayChangeWithReplaySubscription = keplerAppStateManager.addEventListenerWithReplay(
            'displayChange',
            handleDisplayChangeWithReplayedEvents
        );
        // Cleanup subscriptions on unmount
        return () => {
            console.log('KeplerAppState demo: Removing event listeners');

            // Individually remove each listener
            changeSubscription.remove();
            memoryWarningSubscription.remove();
            reconfigureSubscription.remove();
            focusSubscription.remove();
            blurSubscription.remove();
            displayChangeSubscription.remove();
            changeWithReplaySubscription.remove();
            reconfigureWithReplaySubscription.remove();
            memoryWarningWithReplaySubscription.remove();
            focusWithReplaySubscription.remove();
            blurWithReplaySubscription.remove();
            displayChangeWithReplaySubscription.remove();
        };
    }, []);
    // The empty dependency array means this effect runs once when the component mounts and
    // cleans up when it unmounts

    const handleAppStateChange = (nextAppState: KeplerAppStateChangeData) => {
        if (
            appStateData.match(/inactive|background/) &&
            nextAppState === 'active'
        ) {
            console.log('KeplerAppState demo has come to the foreground');
        }
        setAppState(nextAppState as KeplerAppStateStatus);
        console.log(`KeplerAppState change: ${nextAppState}`);
    };

    const handleMemoryWarning = () => {
        console.log('KeplerAppState demo has received memory warning');
    };

    const handleReconfigure = (reason: KeplerAppStateChangeData) => {
        const reconfigureReasonData = reason as KeplerReconfigureReasonData;
        console.log(
            `KeplerAppState demo has received reconfigure : ${JSON.stringify(
                reconfigureReasonData
            )}`
        );
        if (reconfigureReasonData.reconfigureReason === 'homePressed') {
            setHomePressedCounter((prevCounter) => prevCounter + 1);
        }
    };

    const handleFocus = () => {
        setAppFocusState('FOCUSED');
        console.log('KeplerAppState demo has received Focus Event');
    };

    const handleBlur = () => {
        setAppFocusState('BLURRED');
        console.log('KeplerAppState demo has received Blur Event');
    };

    const handleDisplayChange = (reason: KeplerAppStateChangeData) => {
        const displayChangeData = reason as KeplerAppDisplayStatus;
        console.log(
            `KeplerAppState demo has received display event : ${JSON.stringify(
                displayChangeData
            )}`
        );
        if (displayChangeData === 'displayConnected') {
            setDisplayConnectCounter((prevCounter) => prevCounter + 1);
        }
        if (displayChangeData === 'displayDisconnected') {
            setDisplayDisconnectCounter((prevCounter) => prevCounter + 1);
        }
    };

    const handleAppStateChangeWithReplayedEvents = (appStateData: KeplerAppStateWithReplay) => {
        if(appStateData.isReplayed){
            console.log(`KeplerAppState demo has received replayed change event : ${JSON.stringify(appStateData)}`);
        }
        else{
            console.log(`KeplerAppState demo has received change event: ${JSON.stringify(appStateData)}`);
        }

        if (appStateData.match(/inactive|background/) && appStateData.appStateData === 'active') {
            console.log('KeplerAppState demo has come to the foreground');
        }
        setAppState(appStateData.appStateData as KeplerAppStateStatus);
    };

    const handleReconfigureWithReplayedEvents = (appStateData: KeplerAppStateWithReplay) => {
        if(appStateData.isReplayed){
            console.log(`KeplerAppState demo has received replayed reconfigure event : ${JSON.stringify(appStateData)}`);
        }
        else{
            console.log(`KeplerAppState demo has received reconfigure event: ${JSON.stringify(appStateData)}`);
        }

        const reconfigureReasonData = appStateData.appStateData as KeplerReconfigureReasonData;
        if (reconfigureReasonData.reconfigureReason === 'homePressed') {
            setHomePressedCounter((prevCounter) => prevCounter + 1);
        }
    };

    const handleMemoryWarningWithReplayedEvents = (appStateData : KeplerAppStateWithReplay) => {
        if(appStateData.isReplayed){
            console.log(`KeplerAppState demo has received replayed memory warning event : ${JSON.stringify(appStateData)}`);
        }
        else{
            console.log(`KeplerAppState demo has received memory warning event: ${JSON.stringify(appStateData)}`);
        }
    };

    const handleFocusWithReplayedEvents = (appStateData : KeplerAppStateWithReplay) => {
        if(appStateData.isReplayed){
            console.log(`KeplerAppState demo has received replayed Focus event : ${JSON.stringify(appStateData)}`);
        }
        else{
            console.log(`KeplerAppState demo has received Focus event: ${JSON.stringify(appStateData)}`);
        }

        setAppFocusState('FOCUSED');
    };

    const handleBlurWithReplayedEvents = (appStateData : KeplerAppStateWithReplay) => {
        if(appStateData.isReplayed){
            console.log(`KeplerAppState demo has received replayed Blur event : ${JSON.stringify(appStateData)}`);
        }
        else{
            console.log(`KeplerAppState demo has received Blur event: ${JSON.stringify(appStateData)}`);
        }
        setAppFocusState('BLURRED');
    };

    const handleDisplayChangeWithReplayedEvents = (appStateData: KeplerAppStateWithReplay) => {
        if(appStateData.isReplayed){
            console.log(`KeplerAppState demo has received replayed display event : ${JSON.stringify(appStateData)}`);
        }
        else{
            console.log(`KeplerAppState demo has received display event: ${JSON.stringify(appStateData)}`);
        }

        if (appStateData.appStateData === 'displayConnected') {
            console.log('KeplerAppState demo has received displayConnected event');
        } else if (appStateData.appStateData === 'displayDisconnected') {
            console.log('KeplerAppState demo has received displayDisconnected event');
        }
        setAppState(appStateData.appStateData as KeplerAppStateStatus);
    };

    return (
        <View style={styles.container}>
            <Text style={styles.displayText}>Current state is: {appStateData}</Text>
            <Text style={styles.commentText}>
                (When UI is displaying, the state will always be active
            </Text>
            <Text style={styles.commentText}>
                in KeplerScript applications)
            </Text>
            <Text style={styles.displayText}>
                HomeButton Counter: {homePressedCounter}
            </Text>
            <Text style={styles.displayText}>
                Display Connection Counter: {displayConnectCounter}
            </Text>
            <Text style={styles.displayText}>
                Display Disconnection Counter: {displayDisconnectCounter}
            </Text>
            <Text style={styles.displayText}>
                Current Focus state is: {appFocusState}
            </Text>
        </View>
    );
};

export default KeplerAppStateApp;
AppRegistry.registerComponent('KeplerAppStateApp', () => KeplerAppStateApp);

Example app for addEventListenerWithReplay from VegaAppStateManager usage

Copied to clipboard.


import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import {
    KeplerAppStateWithReplay,
    KeplerAppStateStatus,
    KeplerAppStateEvent,
    IKeplerAppStateManager,
    useKeplerAppStateManager
} from '@amazon-devices/react-native-kepler';

const styles = StyleSheet.create({
    container: {
        flex: 1,
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center',
        padding: 20
    },
    stateText: {
        fontSize: 20,
        fontWeight: 'bold',
        marginBottom: 10
    },
    eventText: {
        fontSize: 16,
        marginBottom: 5
    }
});

const AppStateMonitor = () => {
    const keplerAppStateManager: IKeplerAppStateManager = useKeplerAppStateManager();
    const [currentState, setCurrentState] = useState<KeplerAppStateStatus>(
        keplerAppStateManager.getCurrentState
    );
    const [lastEvent, setLastEvent] = useState<string>('');

    useEffect(() => {
        // Monitor app state changes
        const subscriptions = [
            keplerAppStateManager.addEventListenerWithReplay(
                'change' as KeplerAppStateEvent,
                (event: KeplerAppStateWithReplay) => {
                    const state = event.appStateData as KeplerAppStateStatus;
                    setCurrentState(state);
                    setLastEvent(`State change: ${state} (${event.isReplayed ? 'Replayed' : 'New'})`);
                }
            ),

            // Monitor focus events
            keplerAppStateManager.addEventListenerWithReplay(
                'focus' as KeplerAppStateEvent,
                (event: KeplerAppStateWithReplay) => {
                    setLastEvent(`Focus event (${event.isReplayed ? 'Replayed' : 'New'})`);
                }
            ),

            // Monitor display changes
            keplerAppStateManager.addEventListenerWithReplay(
                'displayChange' as KeplerAppStateEvent,
                (event: KeplerAppStateWithReplay) => {
                    setLastEvent(
                        `Display change: ${event.appStateData} (${event.isReplayed ? 'Replayed' : 'New'})`
                    );
                }
            )
        ];

        // Cleanup function
        return () => {
            subscriptions.forEach(subscription => subscription.remove());
        };
    }, []);

    return (
        <View style={styles.container}>
            <Text style={styles.stateText}>
                Current App State: {currentState}
            </Text>
            <Text style={styles.eventText}>
                Last Event: {lastEvent}
            </Text>
        </View>
    );
};

export default AppStateMonitor;


Last updated: May 13, 2026