Videoları önizleme

Önizleme videosu, kullanıcıları TV uygulamanızla derin bağlantı kurmaya teşvik etmenin harika 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 videosuna eklemeyin. Sunucu tarafında reklam yerleştiriyorsanız önizlemeler için reklamsız bir video sağlayın.
  • En iyi kalite için önizleme videolarının 16:9 veya 4:3 olması gerekir. Önizleme videolarının önerilen boyutları için Video programı özellikleri bölümüne bakın.
  • Önizleme videosu ile 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. Videonun sinemaskoplu olmaması. Örneğin, poster resim oranı ASPECT_RATIO_MOVIE_POSTER (1:1, 441) ancak video oranı 16:9 ise poster görünümü 16:9 bölgesine dönüşür.
  • Bir önizleme oluşturduğunuzda, içeriğin içeriği herkesin erişimine açık olabilir veya DRM kapsamında korunabilir. Her durumda farklı prosedürler geçerlidir. Bu sayfada her ikisi de açıklanmaktadır.

Önizlemeyi ana ekranda oynat

ExoPlayer tarafından desteklenen video türlerinden herhangi birini kullanarak bir önizleme oluşturursanız ve önizleme herkesin erişimine açıksa önizlemeyi doğrudan ana ekranda oynatabilirsiniz.

Bir PreviewProgram oluştururken, aşağıdaki örnekte gösterildiği gibi, herkese açık bir HTTPS URL'si ile setPreviewVideoUri() kullanın. Önizleme, video veya işitsel olabilir.

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ştur

Videonuz DRM korumalıysa veya ExoPlayer tarafından desteklenmeyen bir medya türündeyse TvInputService kullanın. Android TV ana ekranı, onSetSurface() yöntemini çağırarak hizmetinize bir Surface iletir. Uygulamanız doğrudan onTune() kaynağından bu yüzeye video çizer.

Doğrudan yüzey oluşturma, uygulamanızın neyin ve nasıl oluşturulacağını kontrol etmesini sağlar. Kanal ilişkilendirmesi gibi meta verileri yer paylaşımlı olarak kullanabilirsiniz.

Manifest'te TvInputService'inizi tanımlayın

Ana ekranın önizlemenizi oluşturabilmesi için uygulamanızın TvInputService uygulamasını sağlaması gerekir.

Hizmet bildiriminize, niyetle gerçekleştirilecek işlem olarak TvInputService değerini belirten bir intent filtresi ekleyin. Ayrıca hizmet meta verilerini ayrı bir XML kaynağı olarak bildirin. Hizmet bildirimi, amaç filtresi ve hizmet meta veri bildirimi aşağıdaki örnekte gösterilmiştir:

<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ı, uygulamanızın XML kaynakları dizininde bulunur ve manifest'te beyan ettiğiniz kaynağın adıyla eşleşmelidir. Önceki örnekte verilen manifest girişlerini kullanarak res/xml/previewinputservice.xml konumunda boş tv-input etiketiyle bir XML dosyası oluşturursunuz:

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

TV Giriş Çerçevesi bu etikete sahip olmalıdır. Ancak bu özellik 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 Android TV ana ekranı yerine uygulamanız tarafından oluşturulması gerektiğini belirtmek istiyorsanız PreviewProgram için video URI'si oluşturmanız gerekir. URI, uygulamanızın içerik için kullandığı tanımlayıcıyla bitmelidir. Böylece içeriği daha sonra TvInputService içinde alabilirsiniz.

Tanımlayıcınız türü Long ise TvContractCompat.buildPreviewProgramUri() işlevini kullanın:

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() ile oluşturun:

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, Android TV'nin önizleme videosunu başlatmasını sağlamak için onTune(Uri videoUri) çağrısını yapar.

Hizmet oluşturma

Aşağıdaki örnekte, kendi PreviewInputService oluşturmak için TvInputService hizmetinin kapsamını nasıl genişleteceğiniz gösterilmektedir. Hizmetin oynatma için MediaPlayer kullandığını ancak kodunuzun mevcut herhangi bir video oynatıcıyı kullanabileceğini unutmayın.

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
        }
    }
}