Videoları önizleme

Önizleme videosu, kullanıcıları TV uygulamanızla derin bağlantı kurmaya teşvik etmenin mükemmel bir yoludur. Önizlemeler, kısa kliplerden tam film fragmanlarına kadar değişiklik gösterebilir.

Önizleme oluştururken aşağıdaki yönergeleri göz önünde bulundurun:

  • Önizlemede reklam gösterme. Reklamları istemci tarafında birleştirirseniz önizleme videolarına dönüştürülemez. Reklamları sunucu tarafına yapıştırırsanız Önizlemeler için reklamsız bir video sağlama.
  • En yüksek kalite için önizleme videolarının en boy oranı 16:9 veya 4:3 olmalıdır. Görüntüleyin Video programı özellikleri önizleme videoları için önerilen boyutları kullanın.
  • Önizleme videosu ve poster resmi farklı en boy oranlarına sahip olduğunda Ana ekran, önizlemeyi oynatmadan önce poster görünümünü videonun en boy oranına göre yeniden boyutlandırır. Video sinemaskop olmamalıdır. Örneğin, poster resmi oranı ASPECT_RATIO_MOVIE_POSTER (1:1,441) ancak video oranı 16:9 olduğunda poster görünümü 16:9 bölgesine dönüşür.
  • Bir önizleme oluşturduğunuzda, önizlemenin içeriği herkes tarafından erişilebilir veya (DRM kapsamında) korunuyor. Her durum için farklı prosedürler geçerlidir. Bu sayfa her ikisini de açıklar.

Ana ekranda önizlemeyi oynatın

Video türlerinden herhangi birini kullanarak önizleme oluşturursanız ExoPlayer tarafından desteklenir ve önizleme herkes tarafından erişilebilirse önizlemeyi doğrudan ana ekranda oynatabilirsiniz.

PreviewProgram derlediğinizde setPreviewVideoUri() öğesini herkesin erişebileceği bir HTTPS ile kullanın URL'sini ekleyin. Önizleme şunlardan biri olabilir: video veya audio.

Kotlin

val previewVideoUrl = Uri.parse("https://www.example.com/preview.mp4")
val builder = PreviewProgram.Builder()
builder.setChannelId(channelId)
    // ...
    .setPreviewVideoUri(previewVideoUrl)

Java

Uri previewVideoUrl = Uri.parse("https://www.example.com/preview.mp4");
PreviewProgram.Builder builder = new PreviewProgram.Builder();
builder.setChannelId(channelId)
    // ...
    .setPreviewVideoUri(Uri.parse(previewVideoUrl));

Bir yüzeyde önizleme oluşturma

Videonuz DRM korumalıysa veya Google Ad Manager tarafından desteklenmeyen bir medya türündeyse ExoPlayer, TvInputService kullanın. Android TV ana ekranı, hizmetinize bir Surface iletir onSetSurface() numaralı telefonu arayarak. Uygulamanız, onTune() üzerinden doğrudan bu yüzeyde video çiziyor.

Doğrudan yüzey oluşturma, uygulamanızın nelerin ve nasıl oluşturulduğunu kontrol etmenizi sağlar oluşturulur. Kanal ilişkilendirmesi gibi meta veriler ekleyebilirsiniz.

Manifest dosyasında TvInputService'inizi bildirin

Uygulamanızda TvInputService özelliği bulunmalıdır böylece ana ekran önizlemenizi oluşturabilir.

Hizmet beyanınıza şunu belirten bir intent filtresi ekleyin: TvInputService isteyebilirsiniz. Ayrıca, hizmet meta verilerini ayrı bir XML kaynağı olarak bildirin. İlgili içeriği oluşturmak için kullanılan hizmet bildirimi, amaç filtresi ve hizmet meta veri beyanı gösteriliyor aşağıdaki örnekte:

<service android:name=".rich.PreviewInputService"
    android:permission="android.permission.BIND_TV_INPUT">
    <!-- Required filter used by the system to launch our account service. -->
    <intent-filter>
        <action android:name="android.media.tv.TvInputService" />
    </intent-filter>
    <!-- An XML file which describes this input. -->
    <meta-data
        android:name="android.media.tv.input"
        android:resource="@xml/previewinputservice" />
</service>

Hizmet meta verilerini ayrı bir XML dosyasında tanımlayın. Hizmet meta veri dosyası, XML kaynakları dizininde bulunur. ve manifest'ini kullanabilirsiniz. Önceki örnekteki manifest girişlerini kullanarak res/xml/previewinputservice.xml adresinde boş bir XML dosyası oluşturun tv-input etiketi:

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

TV Giriş Çerçevesi bu etiketi içermelidir. Ancak, yalnızca canlı kanalları yapılandırmak için kullanılır. Video oluşturduğunuz için etiket boş olmalıdır.

Video URI'si oluşturma

Önizleme videonuzun bir PreviewProgram için video URI'si oluşturmalısınız. URI, uygulamanızın içerik için kullandığı tanımlayıcıyla bitmelidir. Böylece, TvInputService içinde içeriği daha sonra alabilir.

Tanımlayıcınız Long türündeyse TvContractCompat.buildPreviewProgramUri():

Kotlin

val id: Long = 1L // content identifier
val componentName = new ComponentName(context, PreviewVideoInputService.class)
val previewProgramVideoUri = TvContractCompat.buildPreviewProgramUri(id)
   .buildUpon()
   .appendQueryParameter("input", TvContractCompat.buildInputId(componentName))
   .build()

Java

Long id = 1L; // content identifier
ComponentName componentName = new ComponentName(context, PreviewVideoInputService.class);
previewProgramVideoUri = TvContractCompat.buildPreviewProgramUri(id)
       .buildUpon()
       .appendQueryParameter("input", TvContractCompat.buildInputId(componentName))
       .build();

Tanımlayıcınız Long türünde değilse URI'yi Uri.withAppendedPath():

Kotlin

val previewProgramVideoUri = Uri.withAppendedPath(PreviewPrograms.CONTENT_URI, "content-identifier")
       .buildUpon()
       .appendQueryParameter("input", TvContractCompat.buildInputId(componentName))
       .build()

Java

previewProgramVideoUri = Uri.withAppendedPath(PreviewPrograms.CONTENT_URI, "content-identifier")
       .buildUpon()
       .appendQueryParameter("input", TvContractCompat.buildInputId(componentName))
       .build();

Uygulamanız onTune(Uri videoUri). olması için Android TV'nin önizleme videosunu başlatması gerekir.

Hizmet oluşturma

Aşağıdaki örnekte, kendi şablonunuzu oluşturmak için TvInputService eklentisinin nasıl genişletileceği gösterilmektedir PreviewInputService. Hizmetin, oynatma için bir MediaPlayer kullandığını unutmayın. kodunuz, mevcut herhangi bir video oynatıcıyı kullanabilir.

Kotlin

import android.content.Context
import android.media.MediaPlayer
import android.media.tv.TvInputService
import android.net.Uri
import android.util.Log
import android.view.Surface
import java.io.IOException

class PreviewVideoInputService : TvInputService() {

    override fun onCreateSession(inputId: String): TvInputService.Session? {
        return PreviewSession(this)
    }

    private inner class PreviewSession(
        internal var context: Context
    ) : TvInputService.Session(context) {
    
        internal var mediaPlayer: MediaPlayer? = MediaPlayer()

        override fun onRelease() {
            mediaPlayer?.release()
            mediaPlayer = null
        }

        override fun onTune(uri: Uri): Boolean {
            // Let the TvInputService know that the video is being loaded.
            notifyVideoUnavailable(VIDEO_UNAVAILABLE_REASON_TUNING)
            // Fetch the stream url from the TV Provider database
            // for content://android.media.tv/preview_program/
            val id = uri.lastPathSegment
            // Load your video in the background.
            retrieveYourVideoPreviewUrl(id) { videoUri ->
                if (videoUri == null) {
                  Log.d(TAG, "Could not find video $id")
                  notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN)
                }

                try {
                    mPlayer.setDataSource(getApplicationContext(), videoUri)
                    mPlayer.prepare()
                    mPlayer.start()
                    notifyVideoAvailable()
                } catch (IOException e) {
                    Log.e(TAG, "Could not prepare media player", e)
                    notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN)
                }
              }
          return true
        }

        override fun onSetSurface(surface: Surface?): Boolean {
            mediaPlayer?.setSurface(surface)
            return true
        }

        override fun onSetStreamVolume(volume: Float) {
            // The home screen may fade in and out the video's volume.
            // Your player should be updated accordingly.
            mediaPlayer?.setVolume(volume, volume)
        }

        override fun onSetCaptionEnabled(b: Boolean) {
            // enable/disable captions here
        }
    }

    companion object {
        private const val TAG = "PreviewInputService"
    }
}

Java

import android.content.Context;
import android.media.MediaPlayer;
import android.media.tv.TvInputService;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.Surface;
import java.io.IOException;

public class PreviewVideoInputService extends TvInputService {
    private static final String TAG = "PreviewVideoInputService";

    @Nullable
    @Override
    public Session onCreateSession(String inputId) {
        return new PreviewSession(this);
    }

    private class PreviewSession extends TvInputService.Session {

        private MediaPlayer mPlayer;

        PreviewSession(Context context) {
            super(context);
            mPlayer = new MediaPlayer();
        }

        @Override
        public boolean onTune(Uri channelUri) {
            // Let the TvInputService know that the video is being loaded.
            notifyVideoUnavailable(VIDEO_UNAVAILABLE_REASON_TUNING);
            // Fetch the stream url from the TV Provider database
            // for content://android.media.tv/preview_program/
            String id = uri.getLastPathSegment();
            // Load your video in the background.
            retrieveYourVideoPreviewUrl(id, new MyCallback() {
              public void callback(Uri videoUri) {
                if (videoUri == null) {
                  Log.d(TAG, "Could not find video" + id);
                  notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN);
                }

                try {
                    mPlayer.setDataSource(getApplicationContext(), videoUri);
                    mPlayer.prepare();
                    mPlayer.start();
                    notifyVideoAvailable();
                } catch (IOException e) {
                    Log.e(TAG, "Could not prepare media player", e);
                    notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN);
                }
              }
            });
            return true;
        }

        @Override
        public boolean onSetSurface(@Nullable Surface surface) {
            if (mPlayer != null) {
                mPlayer.setSurface(surface);
            }
            return true;
        }

        @Override
        public void onRelease() {
            if (mPlayer != null) {
                mPlayer.release();
            }
            mPlayer = null;
        }

        @Override
        public void onSetStreamVolume(float volume) {
            if (mPlayer != null) {
                // The home screen may fade in and out the video's volume.
                // Your player should be updated accordingly.
                mPlayer.setVolume(volume, volume);
            }
        }

        @Override
        public void onSetCaptionEnabled(boolean enabled) {
            // enable/disable captions here
        }
    }
}