How do I use my custom CSS/JS Bitmovin Player UI on iOS and Android?

I’ve built a custom Bitmovin Player UI for my web app. Is it possible to reuse it with the iOS and Android Player SDKs?

I built the custom UI according to this sample:

Thank you.

1 Like

Yes. You can use your custom Web UI for Bitmovin Player with the native iOS and Android SDKs.

On iOS, include your custom CSS and JS files in the bundle and add them to your PlayerConfig:

Check the iOS sample project below:

On Android, include your custom CSS and JS files in the assets folder and add them to your PlayerConfig.

Check the Android sample project below:

2 Likes

A small addition to that: You don’t have to include the UI locally, it can also be referenced via a weblink. This way whenever something in your UI changes, you don’t have to redeploy the mobile apps.

1 Like

I was scrolling down and bump into this ticket which actually fits pretty much on the issue I’m struggling now.

I am using a custom UI player that has pretty much of the UIFactory.modernSmallScreenUI code, I could make the UI suits my requirements for now on the website, however when I use it for android, I use the .js and .css files to setup the stylingconfig but I haven’t made to work correctly, just the UI doesn’t show.

the code I am implementing in the .js file is:

import {
    SettingsPanel,
    Container,
    VideoQualitySelectBox,
    PlaybackSpeedSelectBox,
    ControlBar,
    UIContainer,
    PlaybackTimeLabel,
    PlaybackTimeLabelMode,
    SeekBar,
    SeekBarLabel,
    SubtitleOverlay,
    FullscreenToggleButton,
    BufferingOverlay,
    TitleBar,
    PlaybackToggleOverlay,
    SettingsToggleButton,
    SettingsPanelItem,
    SettingsPanelPage,
    SubtitleSettingsPanelPage,
    SettingsPanelPageOpenButton,
    VolumeToggleButton,
    MetadataLabelContent,
    MetadataLabel,
    ErrorMessageOverlay,
    PlayerUtils,
    SubtitleSelectBox,
    SubtitleSettingsLabel,
    CloseButton,
    PlaybackToggleButton,
  } from "bitmovin-player-ui";

 export const modernSmallScreenUI = () => {
    let subtitleOverlay = new SubtitleOverlay();

    let mainSettingsPanelPage = new SettingsPanelPage({
      components: [
        new SettingsPanelItem('video quality', new VideoQualitySelectBox()),
        new SettingsPanelItem('speed', new PlaybackSpeedSelectBox()),
     ],
    });

    let settingsPanel = new SettingsPanel({
      components: [
        mainSettingsPanelPage,
      ],
      hidden: true,
      pageTransitionAnimation: false,
      hideDelay: -1,
    });

    let subtitleSettingsPanelPage = new SubtitleSettingsPanelPage({
      settingsPanel: settingsPanel,
      overlay: subtitleOverlay,
    });

    let subtitleSettingsOpenButton = new SettingsPanelPageOpenButton({
      targetPage: subtitleSettingsPanelPage,
      container: settingsPanel,
      ariaLabel: 'settings subtitles',
      text: 'open',
    });

    const subtitleSelectBox = new SubtitleSelectBox();

    mainSettingsPanelPage.addComponent(
      new SettingsPanelItem(
        new SubtitleSettingsLabel({
          text: 'subtitle settings',
          opener: subtitleSettingsOpenButton,
        }),
        subtitleSelectBox,
        {
          role: 'menubar',
        },
      ));

    settingsPanel.addComponent(subtitleSettingsPanelPage);

    settingsPanel.addComponent(new CloseButton({ target: settingsPanel }));
    subtitleSettingsPanelPage.addComponent(new CloseButton({ target: settingsPanel }));

    let controlBar = new ControlBar({
      components: [
        new Container({
          components: [
            new PlaybackToggleButton(),
            new PlaybackTimeLabel({ timeLabelMode: PlaybackTimeLabelMode.CurrentTime, hideInLivePlayback: true }),
            new SeekBar({ label: new SeekBarLabel() }),
            new PlaybackTimeLabel({ timeLabelMode: PlaybackTimeLabelMode.TotalTime, cssClasses: ['text-right'] }),
            new FullscreenToggleButton({cssClasses:['ui-fullscreentogglebutton']}),
          ],
          cssClasses: ['controlbar-top'],
        }),
      ]
    });

    return new UIContainer({
      components: [
        subtitleOverlay,
        new BufferingOverlay(),
        new PlaybackToggleOverlay(),
        controlBar,
        new TitleBar({
          components: [
            new MetadataLabel({ content: MetadataLabelContent.Title }),
            new VolumeToggleButton(),
            new SettingsToggleButton({ settingsPanel: settingsPanel }),
            new CloseButton(),
          ],
        }),
        settingsPanel,
        new ErrorMessageOverlay(),
      ],
      cssClasses: ['ui-skin-smallscreen'],
      hideDelay: 2000,
      hidePlayerStateExceptions: [
        PlayerUtils.PlayerState.Prepared,
        PlayerUtils.PlayerState.Paused,
        PlayerUtils.PlayerState.Finished,
      ],
    });
  }

that folder is located alongside the css file, in assets that is in android root, and then I call them like this:

  StyleConfig styleConfig = new StyleConfig();
        styleConfig.setPlayerUiCss("file:///android_asset/bitmovin-custom-min.css");
        styleConfig.setPlayerUiJs("file:///android_asset/bitmovin-custom-min.js");
        this._playerConfig.setStyleConfig(styleConfig);
        this._player = Player.create(reactContext, this._playerConfig);
        this._playerView = new PlayerView(reactContext, this._player);
        this._playerView.setUiVisible(false);

The video shows but the UI controls doesn’t, thanks in advance.

Hi @carrerafandres2496,

as you are calling this._playerView.setUiVisible(false) you are explicitly disabling any web UI on the PlayerView, so either remove this line or set it to true.

Hi @jarhoax

Yeah I realised after debugging, but still the UI doesn’t shows after setting the value to true. The thing is I have an react project (only for creating the video UI player) where I’m creating the UI player and for suing the bundlejs and css files to set the stlyling config. I am not sure if I’m doing something wrong through that process.

I just checked your .js file content you shared and stripping most of the player ui’s code in there won’t work. For example there needs to be a UI Manager returned by UIFactory.buildDefaultSmallScreenUI(...).

I’m looping in @davidsteinacher here as he sure has valuable input here as well.

Hi,

as @jarhoax already said, on iOS and Android we require the window.bitmovin.playerui.UIFactory.buildDefaultSmallScreenUI(this.player, uiConfig); being present and returning an UIManager. (Assuming you are using v3 of our SDK and v3 of the UI)

See our implementation of it for reference.

1 Like