TV giriş hizmeti geliştirme

TV giriş hizmeti, medya akış kaynağını temsil eder ve medya içeriğinizi geleneksel, TV yayını tarzında kanallar ve programlar olarak sunmanıza olanak tanır. TV giriş hizmetiyle ebeveyn denetimleri, program rehberi bilgileri ve içerik derecelendirmeleri sağlayabilirsiniz. TV giriş hizmeti, Android sistemi TV uygulamasıyla çalışır. Bu uygulama, nihai olarak kanal içeriğini TV'de kontrol edip sunar. Sistem TV uygulaması, cihaz için özel olarak geliştirilmiştir ve üçüncü taraf uygulamaları tarafından değiştirilemez. TV Giriş Çerçevesi (TIF) mimarisi ve bileşenleri hakkında daha fazla bilgi için TV Giriş Çerçevesi bölümüne bakın.

TIF Tamamlayıcı Kitaplığı'nı kullanarak TV giriş hizmeti oluşturma

TIF Tamamlayıcı Kitaplığı, yaygın TV giriş hizmeti özelliklerinin genişletilebilir uygulamalarını sağlayan bir çerçevedir. OEM'ler tarafından yalnızca Android 5.0 (API düzeyi 21) ile Android 7.1 (API düzeyi 25) arasındaki sürümler için kanallar oluşturmak üzere tasarlanmıştır.

Projenizi güncelleyin

TIF Tamamlayıcı Kitaplığı, androidtv-sample-inputs deposundaki OEM'ler tarafından eski kullanım için kullanılabilir. Kitaplığın bir uygulamaya nasıl ekleneceğini gösteren örnek için bu depoya bakın.

Manifest'te TV giriş hizmetinizi bildirin

Uygulamanız, sistemin uygulamanıza erişmek için kullandığı TvInputService uyumlu bir hizmet sağlamalıdır. TIF Tamamlayıcı Kitaplığı, özelleştirebileceğiniz varsayılan TvInputService uygulamasını sağlayan BaseTvInputService sınıfını sağlar. Bir BaseTvInputService alt sınıfı oluşturun ve manifest dosyanızdaki alt sınıfı bir hizmet olarak bildirin.

Hizmetin TV girişini sisteme bağlamasına izin vermek için manifest beyanında BIND_TV_INPUT iznini belirtin. Bir sistem hizmeti, bağlamayı gerçekleştirir ve BIND_TV_INPUT iznine sahiptir. Sistem TV uygulaması, istekleri TvInputManager arayüzü üzerinden TV giriş hizmetlerine gönderir.

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.RichTvInputService"
    android:label="@string/rich_input_label"
    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. This provides pointers to
    the RichTvInputSetupActivity to the system/TV app. -->
    <meta-data
        android:name="android.media.tv.input"
        android:resource="@xml/richtvinputservice" />
</service>

Hizmet meta verilerini ayrı bir XML dosyasında tanımlayın. Hizmet meta veri XML dosyası, TV girişinin ilk yapılandırmasını ve kanal taramasını açıklayan bir kurulum arayüzü içermelidir. Meta veri dosyası, kullanıcıların içerik kaydedip kaydedemeyeceğini belirten bir işaret de içermelidir. Uygulamanızda içerik kaydetmeyi nasıl destekleyeceğiniz hakkında daha fazla bilgi için İçerik kaydını destekleme bölümüne bakı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 yer alan manifest girişlerini kullanarak XML dosyasını res/xml/richtvinputservice.xml adresinde aşağıdaki içerikle oluşturursunuz:

<?xml version="1.0" encoding="utf-8"?>
<tv-input xmlns:android="http://schemas.android.com/apk/res/android"
  android:canRecord="true"
  android:setupActivity="com.example.android.sampletvinput.rich.RichTvInputSetupActivity" />

Kanalları tanımlama ve kurulum etkinliğinizi oluşturma

TV giriş hizmetiniz, kullanıcıların sistem TV uygulaması üzerinden eriştiği en az bir kanal tanımlamalıdır. Kanallarınızı sistem veritabanına kaydetmeli ve uygulamanız için bir kanal bulamadığında sistemin çağıracağı bir kurulum etkinliği sağlamalısınız.

Öncelikle, uygulamanızda kullanıcının yararlanabileceği kanallar ve programlar bulunan sistem Elektronik Programlama Rehberi'ne (EPG) okuma ve yazma işlemleri için uygulamanızı etkinleştirin. Uygulamanızın bu işlemleri gerçekleştirmesini sağlamak ve cihaz yeniden başlatıldıktan sonra EPG ile senkronize etmek için aşağıdaki öğeleri uygulama manifestinize ekleyin:

<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED "/>

Uygulamanızın Google Play Store'da Android TV'de içerik kanalları sağlayan bir uygulama olarak görünmesini sağlamak için aşağıdaki öğeyi ekleyin:

<uses-feature
    android:name="android.software.live_tv"
    android:required="true" />

Ardından, EpgSyncJobService sınıfını genişleten bir sınıf oluşturun. Bu soyut sınıf, sistem veritabanında kanal oluşturan ve güncelleyen bir iş hizmeti oluşturmayı kolaylaştırır.

Alt sınıfınızda, getChannels() içerisindeki tam kanal listenizi oluşturun ve döndürün. Kanallarınız bir XMLTV dosyasından geliyorsa XmlTvParser sınıfını kullanın. Aksi takdirde, Channel.Builder sınıfını kullanarak kanalları programatik olarak oluşturun.

Sistem, her kanal için kanalda belirli bir zaman aralığında görüntülenebilecek programların bir listesine ihtiyaç duyduğunda getProgramsForChannel() özelliğini çağırır. Kanal için Program nesnelerinin listesini döndürün. Bir XMLTV dosyasından program almak veya Program.Builder sınıfını kullanarak programlı bir şekilde oluşturmak için XmlTvParser sınıfını kullanın.

Her Program nesnesinde, programın video türü gibi program bilgilerini ayarlamak için bir InternalProviderData nesnesi kullanın. Kanalın bir döngüde tekrarlamasını istediğiniz yalnızca sınırlı sayıda programınız varsa programınızla ilgili bilgileri ayarlarken InternalProviderData.setRepeatable() yöntemini true değeriyle kullanın.

İş hizmetini uyguladıktan sonra uygulama manifestinize ekleyin:

<service
    android:name=".sync.SampleJobService"
    android:permission="android.permission.BIND_JOB_SERVICE"
    android:exported="true" />

Son olarak, bir kurulum etkinliği oluşturun. Kurulum etkinliğiniz, kanal ve program verilerini senkronize etmek için bir yöntem sağlamalıdır. Bunu yapmanın bir yolu, kullanıcının etkinlikteki kullanıcı arayüzü aracılığıyla bunu yapmasıdır. Ayrıca, etkinlik başladığında uygulamanın bunu otomatik olarak yapmasını da sağlayabilirsiniz. Kurulum etkinliğinin kanal ve program bilgilerini senkronize etmesi gerektiğinde, uygulama iş hizmetini başlatmalıdır:

Kotlin

val inputId = getActivity().intent.getStringExtra(TvInputInfo.EXTRA_INPUT_ID)
EpgSyncJobService.cancelAllSyncRequests(getActivity())
EpgSyncJobService.requestImmediateSync(
        getActivity(),
        inputId,
        ComponentName(getActivity(), SampleJobService::class.java)
)

Java

String inputId = getActivity().getIntent().getStringExtra(TvInputInfo.EXTRA_INPUT_ID);
EpgSyncJobService.cancelAllSyncRequests(getActivity());
EpgSyncJobService.requestImmediateSync(getActivity(), inputId,
        new ComponentName(getActivity(), SampleJobService.class));

İş hizmetini senkronize etmek için requestImmediateSync() yöntemini kullanın. Kullanıcının senkronizasyonun tamamlanmasını beklemesi gerekir; bu nedenle istek sürenizi nispeten kısa tutmalısınız.

İş hizmetinin, arka planda kanal ve program verilerini düzenli olarak senkronize etmesini sağlamak için setUpPeriodicSync() yöntemini kullanın:

Kotlin

EpgSyncJobService.setUpPeriodicSync(
        context,
        inputId,
        ComponentName(context, SampleJobService::class.java)
)

Java

EpgSyncJobService.setUpPeriodicSync(context, inputId,
        new ComponentName(context, SampleJobService.class));

TIF Tamamlayıcı Kitaplığı, kanal verilerinin milisaniye cinsinden senkronize edileceği süreyi belirtmenize olanak tanıyan ek bir aşırı yükleme yöntemi (requestImmediateSync()) sunar. Varsayılan yöntem bir saatlik kanal verilerini senkronize eder.

TIF Tamamlayıcı Kitaplığı, senkronize edilecek kanal verilerinin süresini ve periyodik senkronizasyonun ne sıklıkta yapılması gerektiğini belirtmenize olanak tanıyan ek bir setUpPeriodicSync() aşırı yükleme yöntemini de sağlar. Varsayılan yöntem, 48 saatlik kanal verilerini 12 saatte bir senkronize eder.

Kanal verileri ve EPG hakkında daha fazla bilgi için Kanal verileriyle çalışma bölümüne bakın.

İnce ayar isteklerini ve medya oynatma işlemlerini yönetin

Bir kullanıcı belirli bir kanalı seçtiğinde sistem TV uygulaması, istenen kanala göre ayar yapmak ve içeriği oynatmak için uygulamanız tarafından oluşturulan bir Session kullanır. TIF Tamamlayıcı Kitaplığı, sistemden gelen kanal ve oturum çağrılarını yönetmek için genişletebileceğiniz çeşitli sınıflar sunar.

BaseTvInputService alt sınıfınız, ayarlama isteklerini işleyen oturumlar oluşturur. onCreateSession() yöntemini geçersiz kılın, BaseTvInputService.Session sınıfından genişletilmiş bir oturum oluşturun ve yeni oturumunuzla super.sessionCreated() yöntemini çağırın. Aşağıdaki örnekte onCreateSession(), BaseTvInputService.Session genişliğinde bir RichTvInputSessionImpl nesnesi döndürür:

Kotlin

override fun onCreateSession(inputId: String): Session =
        RichTvInputSessionImpl(this, inputId).apply {
            setOverlayViewEnabled(true)
        }

Java

@Override
public final Session onCreateSession(String inputId) {
    RichTvInputSessionImpl session = new RichTvInputSessionImpl(this, inputId);
    session.setOverlayViewEnabled(true);
    return session;
}

Kullanıcı, kanallarınızdan birini görüntülemeye başlamak için sistem TV uygulamasını kullandığında sistem, oturumunuzun onPlayChannel() yöntemini çağırır. Program oynatılmaya başlamadan önce herhangi bir özel kanal başlatma işlemi yapmanız gerekiyorsa bu yöntemi geçersiz kılın.

Daha sonra sistem, o anda planlanmış programı edinir ve oturumunuzun onPlayProgram() yöntemini çağırarak program bilgilerini ve başlangıç zamanını milisaniye cinsinden belirtir. Programı oynatmaya başlamak için TvPlayer arayüzünü kullanın.

Medya oynatıcı kodunuz, belirli oynatma etkinliklerini işlemek için TvPlayer öğesini uygulamalıdır. TvPlayer sınıfı, BaseTvInputService uygulamanıza karmaşıklık katmadan zaman değiştirme kontrolleri gibi özellikleri işler.

Oturumunuzun getTvPlayer() yönteminde, TvPlayer uygulayan medya oynatıcınızı döndürün. TV Giriş Hizmeti örnek uygulaması, ExoPlayer kullanan bir medya oynatıcı uygular.

TV giriş çerçevesini kullanarak TV giriş hizmeti oluşturma

TV giriş hizmetiniz TIF Tamamlayıcı Kitaplığı'nı kullanamıyorsa aşağıdaki bileşenleri uygulamanız gerekir:

  • TvInputService, TV girişi için uzun süreli ve arka planda kullanılabilirlik sağlar
  • TvInputService.Session, TV giriş durumunu korur ve barındıran uygulamayla iletişim kurar
  • TvContract, TV girişi tarafından kullanılabilen kanalları ve programları açıklar
  • TvContract.Channels, TV kanalıyla ilgili bilgileri temsil eder
  • TvContract.Programs, program adı ve başlangıç zamanı gibi verileri içeren bir TV programını tanımlar.
  • TvTrackInfo bir ses, video veya altyazı parçasını temsil eder
  • TvContentRating bir içerik derecelendirmesini tanımlar ve özel içerik derecelendirmesi şemalarına olanak tanır
  • TvInputManager, sistem TV uygulamasına bir API sağlayarak TV girişleri ve uygulamalarla olan etkileşimi yönetir.

Aşağıdakileri de yapmanız gerekir:

  1. TV giriş hizmetinizi manifest dosyasında tanımlama bölümünde açıklandığı gibi manifest dosyasında TV giriş hizmetinizi tanımlayın.
  2. Hizmet meta veri dosyasını oluşturun.
  3. Kanal ve program bilgilerinizi oluşturup kaydedin.
  4. Kurulum etkinliğinizi oluşturun.

TV giriş hizmetinizi tanımlayın

Hizmetiniz için TvInputService sınıfının kapsamını genişletirsiniz. TvInputService uygulaması, sistem hizmetinin ona bağlanan istemci olduğu bağlı bir hizmettir. Uygulamanız gereken hizmet yaşam döngüsü yöntemleri Şekil 1'de gösterilmiştir.

onCreate() yöntemi, sistem kaynaklı işlemleri işlemek için kullanıcı arayüzü iş parçacığından ayrı bir işlem iş parçacığı sağlayan HandlerThread öğesini başlatır ve başlatır. Aşağıdaki örnekte onCreate() yöntemi CaptioningManager öğesini başlatır ve ACTION_BLOCKED_RATINGS_CHANGED ile ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED işlemlerini işlemeye hazırlar. Bu işlemler, kullanıcı ebeveyn denetimi ayarlarını değiştirdiğinde ve engellenen puanlar listesinde bir değişiklik olduğunda tetiklenen sistem amaçlarını açıklar.

Kotlin

override fun onCreate() {
    super.onCreate()
    handlerThread = HandlerThread(javaClass.simpleName).apply {
        start()
    }
    dbHandler = Handler(handlerThread.looper)
    handler = Handler()
    captioningManager = getSystemService(Context.CAPTIONING_SERVICE) as CaptioningManager

    setTheme(android.R.style.Theme_Holo_Light_NoActionBar)

    sessions = mutableListOf<BaseTvInputSessionImpl>()
    val intentFilter = IntentFilter().apply {
        addAction(TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED)
        addAction(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED)
    }
    registerReceiver(broadcastReceiver, intentFilter)
}

Java

@Override
public void onCreate() {
    super.onCreate();
    handlerThread = new HandlerThread(getClass()
      .getSimpleName());
    handlerThread.start();
    dbHandler = new Handler(handlerThread.getLooper());
    handler = new Handler();
    captioningManager = (CaptioningManager)
      getSystemService(Context.CAPTIONING_SERVICE);

    setTheme(android.R.style.Theme_Holo_Light_NoActionBar);

    sessions = new ArrayList<BaseTvInputSessionImpl>();
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(TvInputManager
      .ACTION_BLOCKED_RATINGS_CHANGED);
    intentFilter.addAction(TvInputManager
      .ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED);
    registerReceiver(broadcastReceiver, intentFilter);
}

Şekil 1.TvInputService yaşam döngüsü.

Engellenen içeriklerle çalışma ve ebeveyn denetimi sağlama hakkında daha fazla bilgi için İçeriği kontrol etme bölümüne bakın. TV giriş hizmetinizde gerçekleştirmek isteyebileceğiniz sistem temelli diğer işlemler için TvInputManager adresini ziyaret edin.

TvInputService, oynatıcı durumu değişikliklerini işlemek için Handler.Callback uygulayan bir TvInputService.Session oluşturur. onSetSurface() kullanıldığında TvInputService.Session, Surface öğesini video içeriğiyle ayarlar. Video oluşturmak için Surface ile çalışma hakkında daha fazla bilgi edinmek üzere Oynatıcıyı yüzeyle entegre etme bölümüne bakın.

TvInputService.Session, kullanıcı bir kanal seçtiğinde onTune() etkinliğini yönetir ve sistem TV uygulamasına içerik ve içerik meta verilerindeki değişiklikler konusunda bilgi verir. Bu notify() yöntemleri, bu eğitimin ilerleyen bölümlerinde İçeriği Kontrol Etme ve Kanal seçimini işleme konularında açıklanmıştır.

Kurulum etkinliğinizi tanımlama

Sistem TV uygulaması, TV girişiniz için tanımladığınız kurulum etkinliğiyle çalışır. Kurulum etkinliği gereklidir ve sistem veritabanı için en az bir kanal kaydı sağlamalıdır. Sistem TV uygulaması, TV girişi için bir kanal bulamadığında kurulum etkinliğini çağırır.

Kurulum etkinliği, Kanal verilerini oluşturma ve güncelleme adlı bir sonraki derste gösterildiği gibi, TV girişi üzerinden kullanılabilen kanalları sistem TV uygulamasına açıklar.

Ek referanslar