พัฒนาบริการอินพุตทีวี

บริการอินพุตทีวีแสดงแหล่งที่มาของสตรีมสื่อ และช่วยให้คุณสามารถนำเสนอเนื้อหาสื่อใน ทีวีแบบดั้งเดิมในรูปแบบช่องและรายการ เมื่อใช้บริการอินพุตทีวี คุณจะให้ การควบคุมโดยผู้ปกครอง ข้อมูลคู่มือรายการทีวี และการจัดประเภทเนื้อหา บริการอินพุตทีวีทำงานได้ กับแอป Android System TV แอปนี้จะควบคุมและนำเสนอเนื้อหาของช่องในท้ายที่สุด บนทีวี แอป System TV พัฒนาขึ้นสำหรับอุปกรณ์โดยเฉพาะและไม่สามารถเปลี่ยนแปลงได้ แอปของบุคคลที่สาม ดูข้อมูลเพิ่มเติมเกี่ยวกับเฟรมเวิร์กอินพุตทีวี (TIF) สถาปัตยกรรมและองค์ประกอบได้ เฟรมเวิร์กอินพุตทีวี

สร้างบริการอินพุตทีวีโดยใช้ไลบรารีที่ใช้ร่วมกัน TIF

TIF Companion Library เป็นเฟรมเวิร์กที่มีความยืดหยุ่น การใช้งานฟีเจอร์บริการอินพุตทีวีทั่วไป OEM ใช้เพื่อสร้าง สำหรับ Android 5.0 (API ระดับ 21) ถึง Android 7.1 (API ระดับ 25) เท่านั้น

อัปเดตโปรเจ็กต์

ไลบรารีที่ใช้ร่วมกัน TIF มีให้บริการสําหรับ OEM เดิมใน androidtv-sample-input ที่เก็บได้ ดูที่เก็บดังกล่าวเพื่อดูตัวอย่างวิธีรวมไลบรารีไว้ในแอป

ประกาศบริการอินพุตทีวีในไฟล์ Manifest

แอปของคุณต้องมีรุ่นที่รองรับ TvInputService ที่ระบบใช้เพื่อเข้าถึงแอปของคุณ TIF ไลบรารีที่ใช้ร่วมกันจะมีคลาส BaseTvInputService ซึ่ง ตั้งค่าการใช้งาน TvInputService ตามค่าเริ่มต้น ที่คุณสามารถปรับแต่งได้ สร้างคลาสย่อยของ BaseTvInputService และประกาศคลาสย่อยในไฟล์ Manifest เป็นบริการ

ภายในการประกาศไฟล์ Manifest ให้ระบุ BIND_TV_INPUT เพื่ออนุญาต เพื่อเชื่อมต่ออินพุตทีวีกับระบบ บริการของระบบ ทำการผูกข้อมูลและ สิทธิ์BIND_TV_INPUT แอป System TV ส่งคำขอไปยังบริการอินพุตทีวี ผ่านอินเทอร์เฟซของ TvInputManager

ในการประกาศบริการ ให้ใส่ตัวกรอง Intent ที่ระบุ TvInputService เป็นการดำเนินการกับ Intent และประกาศข้อมูลเมตาของบริการเป็นทรัพยากร XML แยกต่างหากด้วย แสดงการประกาศบริการ ตัวกรอง Intent และการประกาศข้อมูลเมตาของบริการ ในตัวอย่างต่อไปนี้

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

กำหนดข้อมูลเมตาของบริการในไฟล์ XML แยกต่างหาก บริการ ไฟล์ XML ข้อมูลเมตาต้องมีอินเทอร์เฟซการตั้งค่าที่อธิบายอินพุตของทีวี การกำหนดค่าเริ่มต้นและการสแกนช่อง ไฟล์ข้อมูลเมตาควรประกอบด้วย เพื่อระบุว่าผู้ใช้สามารถบันทึกเนื้อหาได้หรือไม่ สำหรับข้อมูลเพิ่มเติม ข้อมูลเกี่ยวกับวิธีรองรับการบันทึกเนื้อหาในแอปได้ที่ รองรับการบันทึกเนื้อหา

ไฟล์ข้อมูลเมตาของบริการอยู่ในไดเรกทอรีทรัพยากร XML ของแอปและต้องตรงกับชื่อทรัพยากรที่คุณประกาศใน ไฟล์ Manifest ในการใช้รายการไฟล์ Manifest จากตัวอย่างก่อนหน้านี้ คุณจะต้อง สร้างไฟล์ XML ที่ res/xml/richtvinputservice.xml โดยมีค่า เนื้อหาต่อไปนี้

<?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" />

กำหนดแชแนลและสร้างกิจกรรมการตั้งค่าของคุณ

บริการอินพุตทีวีของคุณต้องกำหนดอย่างน้อยหนึ่งช่องที่ผู้ใช้ เข้าถึงได้ผ่านแอป System TV คุณควรลงทะเบียนช่องของคุณ ในฐานข้อมูลระบบ และระบุกิจกรรมการตั้งค่าที่ระบบ เรียกใช้เมื่อไม่พบช่องสำหรับแอปของคุณ

ขั้นแรก ให้แอปของคุณอ่านและเขียนไปยังระบบอิเล็กทรอนิกส์ คู่มือการเขียนโปรแกรม (EPG) ซึ่งมีข้อมูลรวมถึงช่องและรายการที่มีให้บริการ แก่ผู้ใช้ได้ หากต้องการอนุญาตให้แอปทำงานเหล่านี้ และซิงค์กับ EPG หลังจากรีสตาร์ทอุปกรณ์ ให้เพิ่มองค์ประกอบต่อไปนี้ลงในไฟล์ Manifest ของแอป

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

เพิ่มองค์ประกอบต่อไปนี้เพื่อให้แอปปรากฏใน Google Play Store เป็นแอปที่ให้บริการช่องเนื้อหาใน Android TV

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

ถัดไป ให้สร้างชั้นเรียนที่ขยาย EpgSyncJobService ชั้นเรียนนามธรรมนี้ทำให้คุณสามารถสร้างบริการจัดหางาน สร้างและอัปเดตช่องในฐานข้อมูลระบบ

ในคลาสย่อย ให้สร้างและแสดงรายการช่องทั้งหมดใน getChannels() หากช่องมาจากไฟล์ XMLTV ใช้คลาส XmlTvParser หรือสร้าง แชแนลแบบเป็นโปรแกรมโดยใช้คลาส Channel.Builder

สำหรับแต่ละช่อง ระบบจะเรียก getProgramsForChannel() เมื่อต้องการรายการโปรแกรมที่สามารถดูได้ภายในกรอบเวลาที่กำหนด บนช่อง แสดงรายการออบเจ็กต์ Program รายการสำหรับ ใช้ชั้นเรียน XmlTvParser เพื่อรับโปรแกรมจาก ไฟล์ XMLTV หรือสร้างไฟล์โดยใช้โปรแกรม ชั้นเรียนProgram.Builder

สำหรับออบเจ็กต์ Program แต่ละรายการ ให้ใช้ InternalProviderData เพื่อตั้งค่าข้อมูลโปรแกรม เช่น ประเภทวิดีโอของโปรแกรม หากคุณมีโปรแกรมไม่มากนัก ต้องการให้ช่องเล่นซ้ำแบบวนซ้ำ เมธอด InternalProviderData.setRepeatable() ที่มีค่า trueเมื่อตั้งค่าข้อมูลเกี่ยวกับโปรแกรม

หลังจากที่คุณใช้งานบริการงานแล้ว ให้เพิ่มลงในไฟล์ Manifest ของแอปโดยทำดังนี้

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

ขั้นตอนสุดท้าย ให้สร้างกิจกรรมการตั้งค่า กิจกรรมการตั้งค่า เพื่อซิงค์ข้อมูลช่องและโปรแกรม วิธีหนึ่งที่จะทำได้คือ ให้ผู้ใช้ทำเอง ผ่าน UI ในกิจกรรม คุณอาจให้แอปดำเนินการโดยอัตโนมัติด้วยก็ได้ เมื่อกิจกรรมเริ่มต้น เมื่อกิจกรรมการตั้งค่าต้องซิงค์ช่องและ แอปควรเริ่มบริการงาน

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));

ใช้เมธอด requestImmediateSync() เพื่อซิงค์ ใช้บริการงาน ผู้ใช้ต้องรอให้การซิงค์เสร็จสมบูรณ์ คุณจึงควร ทำให้ระยะเวลาการส่งคำขอสั้นลง

ใช้เมธอด setUpPeriodicSync() เพื่อรับบริการงาน ซิงค์ข้อมูลช่องและรายการในเบื้องหลังเป็นระยะๆ:

Kotlin

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

Java

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

ไลบรารีที่ใช้ร่วมกัน TIF นำเสนอวิธีการเพิ่มเติมที่โอเวอร์โหลด requestImmediateSync() ที่ให้คุณระบุระยะเวลาของ ข้อมูลแชแนลที่จะซิงค์เป็นมิลลิวินาที วิธีการเริ่มต้นจะซิงค์ ของข้อมูลช่อง

นอกจากนี้ TIF Companion Library ยังมีวิธีการเพิ่มเติมซึ่งทำงานหนักเกินไปสำหรับ setUpPeriodicSync() ที่ให้คุณระบุระยะเวลาของ ข้อมูลช่องเพื่อทำการซิงค์ และความถี่ในการซิงค์เป็นระยะ เมธอดที่เป็นค่าเริ่มต้นจะซิงค์ข้อมูลช่อง 48 ชั่วโมงทุก 12 ชั่วโมง

ดูรายละเอียดเพิ่มเติมเกี่ยวกับข้อมูลช่องและ EPG ได้ที่ ใช้งานข้อมูลของช่อง

จัดการคำขอปรับแต่งและการเล่นสื่อ

เมื่อผู้ใช้เลือกช่องที่ต้องการ แอป System TV จะใช้ Session ที่แอปของคุณสร้างขึ้นเพื่อปรับให้เข้ากับช่องที่ขอ และเล่นเนื้อหา TIF Companion Library มี ที่คุณสามารถขยายเพื่อจัดการกับการเรียกใช้แชแนลและเซสชันจากระบบ

คลาสย่อย BaseTvInputService จะสร้างเซสชันที่ คำขอการปรับแต่ง ลบล้าง onCreateSession() เมธอด สร้างเซสชันที่ขยายเวลาจาก ชั้นเรียน BaseTvInputService.Session และโทรหา super.sessionCreated() ในเซสชันใหม่ ในรายการต่อไปนี้ ตัวอย่างเช่น onCreateSession() แสดงผล RichTvInputSessionImpl ออบเจ็กต์ที่ขยาย BaseTvInputService.Session:

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

เมื่อผู้ใช้ใช้แอปทีวีของระบบเพื่อเริ่มดูช่องใดช่องหนึ่งของคุณ ระบบจะเรียกใช้เมธอด onPlayChannel() ของเซสชัน ลบล้าง วิธีนี้เหมาะสำหรับการเริ่มต้นช่องแบบพิเศษก่อน เริ่มเล่นได้

จากนั้นระบบจะรับโปรแกรมที่กำหนดเวลาไว้ในปัจจุบัน และเรียกใช้ เมธอด onPlayProgram() ของเซสชัน โดยระบุโปรแกรม และเวลาเริ่มต้นเป็นมิลลิวินาที ใช้เมนู TvPlayer เพื่อเริ่มเล่นโปรแกรม

โค้ดมีเดียเพลเยอร์ควรใช้ TvPlayer ในการจัดการ เหตุการณ์การเล่นที่เฉพาะเจาะจง ชั้นเรียน TvPlayer จะจัดการฟีเจอร์ต่างๆ เช่น การควบคุมการเปลี่ยนเวลาโดยไม่เพิ่มความซับซ้อน การใช้งาน BaseTvInputService

ในเมธอด getTvPlayer() ของเซสชัน ให้ย้อนกลับ มีเดียเพลเยอร์ที่ใช้ TvPlayer แอปตัวอย่างของบริการอินพุตทีวีใช้มีเดียเพลเยอร์ที่ใช้ ExoPlayer

สร้างบริการอินพุตทีวีโดยใช้เฟรมเวิร์กอินพุตทีวี

หากบริการอินพุตทีวีของคุณไม่สามารถใช้ไลบรารีที่ใช้ร่วมกัน TIF ได้ คุณจะต้องมี เพื่อใช้คอมโพเนนต์ต่อไปนี้

  • TvInputService ความพร้อมใช้งานในเบื้องหลังเป็นเวลานานสำหรับ อินพุตทีวี
  • TvInputService.Session จะรักษาสถานะอินพุตทีวีและสื่อสาร ด้วยแอปโฮสติ้ง
  • TvContract อธิบายช่องและรายการที่พร้อมให้รับชมทางทีวี อินพุต
  • TvContract.Channels แสดงข้อมูลเกี่ยวกับช่องทีวี
  • TvContract.Programs อธิบายรายการทีวีที่มีข้อมูล เช่น รายการ ชื่อและเวลาเริ่มต้น
  • TvTrackInfo แสดงถึงแทร็กเสียง วิดีโอ หรือคำบรรยาย
  • TvContentRating อธิบายการจัดประเภทเนื้อหา อนุญาตให้มีเนื้อหาที่กำหนดเอง รูปแบบการให้คะแนน
  • TvInputManager จัดเตรียม API ให้กับแอป System TV และจัดการ การโต้ตอบกับอินพุตและแอปทีวี

นอกจากนี้ คุณยังต้องทำดังนี้

  1. ประกาศบริการอินพุตทีวีของคุณในไฟล์ Manifest ตามที่อธิบายไว้ในประกาศบริการอินพุตทีวีใน ไฟล์ Manifest
  2. สร้างไฟล์ข้อมูลเมตาของบริการ
  3. สร้างและลงทะเบียนช่องและข้อมูลโปรแกรมของคุณ
  4. สร้างกิจกรรมการตั้งค่า

กำหนดบริการอินพุตทีวีของคุณ

สำหรับบริการของคุณ คุณสามารถขยายเวลาคลาส TvInputService ต การติดตั้งใช้งาน TvInputService คือ bound service ที่บริการของระบบ เป็นไคลเอ็นต์ที่เชื่อมโยงกับแท็กดังกล่าว วิธีการในวงจรชีวิตของบริการ ที่คุณต้องนำไปใช้แสดงอยู่ในรูปที่ 1

เมธอด onCreate() จะเริ่มต้นและเริ่มต้น HandlerThread ซึ่งจัดเตรียมเธรดกระบวนการแยกต่างหากจากเธรด UI ไปยัง จัดการการทำงานที่ขับเคลื่อนด้วยระบบ ในตัวอย่างต่อไปนี้ onCreate() จะเริ่มต้น CaptioningManager และเตรียมจัดการ ACTION_BLOCKED_RATINGS_CHANGED และการกระทำ ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED รายการ เหล่านี้ การดำเนินการที่อธิบายเจตนาของระบบที่เริ่มทำงานเมื่อผู้ใช้เปลี่ยนการตั้งค่าการควบคุมโดยผู้ปกครอง และเมื่อ มีการเปลี่ยนแปลงในรายการการให้คะแนนที่ถูกบล็อก

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

รูปที่ 1 วงจรของ TvInputService

โปรดดู ควบคุมเนื้อหาสำหรับข้อมูลเพิ่มเติมเกี่ยวกับการทำงานกับเนื้อหาที่ถูกบล็อกและการให้ การควบคุมโดยผู้ปกครอง ดูการดำเนินการอื่นๆ ที่ขับเคลื่อนด้วยระบบได้ที่ TvInputManager ที่คุณอาจต้องจัดการในบริการอินพุตทีวีของคุณ

TvInputService สร้าง TvInputService.Session ที่ใช้ Handler.Callback ในการรับมือกับการเปลี่ยนแปลงสถานะของโปรแกรมเล่น ด้วย onSetSurface(), TvInputService.Session จะกำหนด Surface ที่มีค่า เนื้อหาวิดีโอ ดูผสานรวมโปรแกรมเล่นกับแพลตฟอร์ม สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการทำงานร่วมกับ Surface ในการแสดงผลวิดีโอ

TvInputService.Session จะจัดการ วันที่ onTune() เมื่อผู้ใช้เลือกช่องและแจ้งเตือนแอป System TV ถึงการเปลี่ยนแปลงเนื้อหาและ ข้อมูลเมตาของเนื้อหา เมธอด notify() เหล่านี้จะอธิบายไว้ใน ควบคุมเนื้อหาและจัดการการเลือกแทร็ก เพิ่มเติมในการฝึกอบรมนี้

กำหนดกิจกรรมการตั้งค่า

แอป System TV ใช้งานได้กับกิจกรรมการตั้งค่าที่คุณกำหนดสำหรับอินพุตของทีวี ต้องระบุกิจกรรมการตั้งค่า และต้องระบุระเบียนช่องอย่างน้อย 1 รายการสำหรับฐานข้อมูลระบบ แอปทีวีระบบจะเรียกกิจกรรมการตั้งค่าเมื่อไม่พบช่องสำหรับอินพุตทีวี

กิจกรรมการตั้งค่าจะอธิบายถึงช่องต่างๆ ที่มีให้ใช้งานผ่านทีวีแก่แอประบบทีวี ดังที่แสดงในบทเรียนถัดไป สร้าง และอัปเดตข้อมูลช่อง

ข้อมูลอ้างอิงเพิ่มเติม