How to add a Splash Screen in Vega Web App

Introduction

A Vega Web App is a widget built on top of the open-source Chromium web engine. This engine is responsible for parsing and rendering web pages, including HTML, CSS, and JavaScript. For further details, please refer to Vega Web App Overview.

In this article, we will outline the process of creating a splash screen and integrating it into your Vega Web App wrapper application. We have provided an example demonstrating how the splash screen can be displayed during the loading of your web application and subsequently hidden once the loading is complete.

SplashScreenManager in Vega

SplashScreenManager allows you to override control of the app’s native splash screen lifecycle, so you can force it to remain visible until it is explicitly hidden. Splash screens can be either static or animated. Both cases are achieved with .png images.

Please refer to the SplashScreenManager APIs under the React Native for Vega reference documentation for a list of available methods.

Assets

Splash screen assets are picked up by the native animation service on app launch. In order to configure them to be picked up, splash screen frame(s) need to be compressed into a .zip file along with a descriptor file.

Images

If your application targets multiple devices, please ensure that the resolution of your splash screen images are appropriate for the target that demands the highest resolution.

  • Use .png image(s)
    • Single .png image for static splash screen
    • Multiple .png images for animated splash screen
  • Put your image(s) in a folder named _loop
    • Even if you only have one image, it needs to be put into _loop
  • Supported image resolutions
    • Multimodal profile: 960x480
    • TV profile: depends on connected display but common ones listed below
      • 1920x1080
      • 3840x2160

Example

_loop
├── loop00000.png
├── loop00001.png
├── ...
└── loop00005.png

Descriptor File

A descriptor file is needed to give the animation service some information about the native splash screen. Data such as image dimensions, frames per second (FPS), and settings for the splash screen can be specified here. This descriptor file will be compressed with _loop into a .zip for the animation service to pick up. To create a descriptor file, create a new .txt file and follow the instructions below:

  • Name your descriptor file desc.txt
  • The first line should be the image width in pixels (e.g., 1920), the image height in pixels (e.g., 1080), and the desired FPS (e.g., 30) separated by spaces.
  • The second line should be c 0 0 _loop
    • c: keep assets after the loop is done
    • 0: loop infinitely until terminated
    • 0: FPS delay until the next command (not relevant for splash screen)
    • _loop: name of the folder

Example

1920 1080 30
c 0 0 _loop

Generate SplashScreenImages.zip

  • From your command line, navigate to the directory where _loop and desc.txt are located.
  • Run the zip -r SplashScreenImages.zip _loop desc.txt command to create a SplashScreenImages.zip file.

:information_source: NOTE: on macOS, right-clicking and selecting “Compress” can lead to an extra outer folder being created, which will cause issues when the native service tries to locate the assets. Please use the zip command from your terminal on the two individual items to avoid this issue.

Example

SplashScreenImages.zip
├── _loop
│   ├── loop00000.png
│   ├── loop00001.png
│   ├── ...
│   └── loop00005.png
└── desc.txt

Placement in the Package

  • If the directory does not exist, please create a new one under your package’s root folder, e.g., <package root>/assets/raw.
  • Place the SplashScreenImages.zip file that you previously created into this directory.

Example

application/
├── assets
│   └── raw
│       └── SplashScreenImages.zip
├── ...
└── src

Usage in the Vega Web App Wrapper App

The following example illustrates the typical usage of the splash screen manager. The code uses “com.amazon.keplerwebapp.main” as a placeholder component name. When implementing your splash screen, make sure to replace this with the appropriate component name.

import React, { useEffect, useRef, useState } from 'react';
import { StyleSheet, View } from 'react-native';
import { WebView } from '@amzn/webview';
import { SplashScreenManager } from '@amzn/react-native-kepler/Libraries/SplashScreenManager/SplashScreenManager';

export const App = () => {
  const webRef = useRef(null);

  // By default splashscreen is shown in app launch, as the splash
  // screen images are bundled in this app (assets/raw/ folder)
  const [isWebAppReady, setIsWebAppReady] = useState(false);

  // Replace with your React Native for Vega app's component name, typically the package name + ".main".
  const packageName = "com.amazon.keplerwebapp.main";

  // Declare that application wants to extend splash screen lifecycle
  SplashScreenManager.preventAutoHideAsync(packageName).catch(err => {
    console.error('Error while preventAutoHideAsync (Splash):', err);
  });

  useEffect(() => {
    async function hideSplashScreen() {
      if (isWebAppReady) {
        // Hide the splash screen and render the WebView content
        await SplashScreenManager.hideAsync(packageName).catch((e) => {
          console.error('Error while hiding splash screen:', err);
        });
      }
    }

    hideSplashScreen().catch((e) => {
      console.error('Error while hiding splash screen:', err);
    });
  }, [isWebAppReady]);
  
  const styles = StyleSheet.create({
    sectionContainer: {
      flex: 1,
    },
  });

  return (
    <View style={styles.sectionContainer}>
      <WebView
        ref={webRef}
        source={...}
        hasTVPreferredFocus={true}
        javaScriptEnabled={true}
        mediaPlaybackRequiresUserAction={false}
        onLoadStart={(event) => {
          console.log(`[onLoadStart] Page loading started. URL: ${event.nativeEvent.url}`);
          setIsWebAppReady(false);
        }}
        onLoad={(event) => {
          console.log(`[onLoad] Page loading completed. URL: ${event.nativeEvent.url}`);
          setIsWebAppReady(true);
        }}
        ...
      />
    </View>
  );
};

Related resources