Skip to content

Most visited

Recently visited


Render Video Directly on a Surface

Direct surface rendering lets your app control what is rendered and how it is rendered. You can overlay metadata such as channel attribution. You can also render secured content for protected playback.

To implement direct rendering, you must build your own TvInputService. The Android TV home screen passes a Surface to your service by calling onSetSurface(). Your app draws video directly on this surface from onTune().

This page explains how to build a TvInputService and configure your app to render preview material by itself, rather than relying on the Android TV home screen.

Declare your TvInputService in the manifest

Your app must provide a TvInputService-compatible service that the system uses to access your app.

In your service declaration, include an intent filter that specifies TvInputService as the action to perform with the intent. Also declare the service metadata as a separate XML resource. The service declaration, intent filter, and service metadata declaration are shown in the following example:

<service android:name=".rich.PreviewInputService"
    <!-- Required filter used by the system to launch our account service. -->
        <action android:name="" />
    <!-- An XML file which describes this input. This provides pointers to
    the PreviewInputSetupActivity to the system/TV app. -->
        android:resource="@xml/previewinputservice" />

Define the service metadata in a separate XML file. The service metadata file is located in the XML resources directory for your app and must match the name of the resource you declared in the manifest. Using the manifest entries from the previous example, you would create the XML file at res/xml/previewinputservice.xml, with the following contents:

<?xml version="1.0" encoding="utf-8"?>

Create a video URI

To indicate that your preview video should be rendered by your app, rather than the Android TV home screen, create a video URI for a PreviewProgram:

componentName = new ComponentName(context, PreviewInputService.class.getName());
Uri videoUri = TvContractCompat.buildPreviewProgramUri(previewProgramId)
        .appendQueryParameter("input", TvContractCompat.buildInputId(componentName));

Use the videoUri to update a preview program of a launcher channel. Specify the videoUri in the PreviewProgram.Builder with setPreviewVideoUri when updating a preview program:

PreviewProgram.Builder builder = new PreviewProgram.Builder(previewProgram);
       .setDescription("Program description")


Your app calls onTune(Uri videoUri) to make Android TV start the preview video.

Create a service

The following example shows how to extend TvInputService to create your own PreviewInputService. Note that the service uses a MediaPlayer for playback, but your code can use any available video player.

import android.content.Context;
import android.util.Log;
import android.view.Surface;


public class PreviewInputService extends TvInputService {
   public Session onCreateSession(String s) {
       Log.d("PreviewInputService", s);
       return new PreviewSession(this);

   private class PreviewSession extends Session {
       MediaPlayer mMediaPlayer = null;
       Context mContext;

       public PreviewSession(Context context) {
           mContext = context;
           mMediaPlayer = new MediaPlayer();

       public void onRelease() {
           if(mMediaPlayer != null) {
               mMediaPlayer = null;

       public boolean onTune(Uri uri) {
          // fetch the stream url from the TV Provider database
          // for content://
          Uri videoUri = fetchStreamUrlFromTvProviderDatabase(uri);
          try {
          } catch (IOException e) {
              Log.e("PreviewInputService", "Could not prepare media player", e);
              return false;
          return true;

       public boolean onSetSurface(@Nullable Surface surface) {
           return true;

       public void onSetStreamVolume(float v) {
           // set stream volume here

       public void onSetCaptionEnabled(boolean b) {
           // enable/disable captions here
This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields


Follow Google Developers on WeChat

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience. (April 2018 — Developer Survey)