Skip to main content
Skip table of contents

Thumbnail previews

To test this feature and view the example code, please see the Android SDK 4 Example Code Quick Start guide.

The SDK can display thumbnails to show the user a preview of where in the stream a seek using the scrubber bar will take them.

For more information about the thumbnail mosaic structure and how it is described in WebVTT, see  https://docs.jwplayer.com/platform/docs.

NAGRA suggests there should be no more than 300 Standard Definition thumbnails for any asset.

Prerequisites

A test stream with an accompanying set of image file(s) containing a mosaic of thumbnails and the associated WebVTT file describing the timing and placement of the thumbnails within the mosaic.

Example code

Design/layout

The layout of your application needs to accommodate the placement of a thumbnail image in the desired location. For example an ImageView whose horizontal position can be adjusted to reflect the destination of the potential seek position:

JAVA
<ImageView
android:id="@+id/thumbnail_preview"
android:layout_width="200dp"
android:layout_height="130dp"
android:layout_marginBottom="10dp"
android:adjustViewBounds="true"
android:background="@android:color/black"
android:contentDescription="preview"
android:scaleType="fitCenter"
android:visibility="invisible"/>

Preparation

The API footprint for this feature is very simple, the application simply needs to implement the ThumbnailsListener interface and instantiate the AssetThumbnails class. For example:

JAVA
private AssetThumbnails mThumbnailHandler = new AssetThumbnails();

private ThumbnailsListener mThumbnailListener = new ThumbnailsListener() {
  @Override
  public void prepared() {
    mThumbnailMap = mThumbnailHandler.thumbnails();
    // Calling this method absolves the SDK of responsibility for the thumbnail bitmaps,
    // any further calls to .thumbnails() without calling .prepareThumbs() will return null.
    mProgress.setOnSeekBarChangeListener(mThumbUpdater);
  }

  @Override
  public void failed(ThumbnailError thumbnailError, String s) {
    mThumbnailMap = null;
  }
};

Then it is a case of calling the AssetThumbnails class prepareThumbnails() method supplying the URL of the WebVTT file and a reference to the instance of the listener, for example:

JAVA
mThumbnailHandler.prepareThumbnails(url, mThumbnailListener);

Determining the thumbnail to paint

The prepared map of thumbnails stored above can be queried using the following example method which returns the relevant Drawable for the provided progress in milliseconds.

JAVA
private Drawable getThumb(long progress) {
  ColorDrawable placeholder = new ColorDrawable(Color.BLACK);
  if (mThumbnailMap == null) {
    return placeholder;
  }

  Long[] startTimes = mThumbnailMap.first;
  for(long key : startTimes){
    if(key >= progress) {
      return new BitmapDrawable(this.getResources(), mThumbnailMap.second.get(key));
    }
  }

  return placeholder;
}

Event handling (handheld)

To react to touch related seeking events, an OnSeekBarChangeListener needs to be declared with overrides for the onStartTrackingTouch(),  onProgressChanged() and  onStopTrackingTouch() methods to react to the seeking start, changes and seeking stop respectively. These methods allow your application to be able to hide, show and update the position of the thumbnails as appropriate.

JAVA
private OnSeekBarChangeListener mThumbUpdater = new OnSeekBarChangeListener() {
  @Override
  public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
    mSeekedTime = progress;
    if (!fromuser || !mThumbnailsVisible) {
      // We're not interested in programmatically generated changes to
      // the progress bar's position.
      return;
    }

    int duration = mPlayer.getDuration();

    if (duration > 0) {
      int width = bar.getWidth() - bar.getPaddingLeft() - bar.getPaddingRight();
      int thumbCenter =  (width * bar.getProgress()) / bar.getMax() + bar.getThumb().getBounds().width()/2;

      mThumbnailPreview.setX(thumbCenter);
      mThumbnailPreview.setImageDrawable(getThumb(mSeekedTime));
      mThumbnailPreview.setVisibility(VISIBLE);
    }
  }

  @Override
  public void onStartTrackingTouch(SeekBar bar) {
    setSeeking(true);
  }

  @Override
  public void onStopTrackingTouch(SeekBar bar) {
    if (mSeeking) {
      mPlayer.seekTo(mSeekedTime);
    }
    hideThumbnail();
    setSeeking(false);
  }
};

Teardown

The AssetThumbnails class has a reset() method which must be called on destruction of the view.

JAVA
@Override
public void onDestroyView() {
  mThumbnailHandler.reset();
}


JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.