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