จัดการฮาร์ดแวร์ทีวี

ฮาร์ดแวร์ของทีวีแตกต่างจากอุปกรณ์ Android อื่นๆ อย่างมาก ทีวีไม่มีฟีเจอร์ฮาร์ดแวร์บางอย่างที่พบในอุปกรณ์ Android อื่นๆ เช่น หน้าจอสัมผัส กล้อง และตัวรับสัญญาณ GPS นอกจากนี้ ทีวียังต้องพึ่งพาอุปกรณ์ฮาร์ดแวร์รองอย่างสมบูรณ์ กล่าวคือผู้ใช้ต้องใช้รีโมตคอนโทรลหรือเกมแพดเพื่อโต้ตอบกับแอป TV (หากต้องการดูข้อมูลเกี่ยวกับวิธีการป้อนข้อมูลต่างๆ โปรดดูจัดการตัวควบคุมทีวี)

เมื่อสร้างแอปสำหรับทีวี ให้พิจารณาข้อจำกัดด้านฮาร์ดแวร์และข้อกำหนดในการทำงานบนฮาร์ดแวร์ทีวีอย่างรอบคอบ ตรวจสอบว่าแอปทำงานบนทีวีหรือไม่ และจัดการฟีเจอร์ฮาร์ดแวร์ที่ไม่รองรับ

ตรวจหาอุปกรณ์ทีวี

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

วิธีที่แนะนำในการพิจารณาว่าแอปทำงานบนอุปกรณ์ทีวีหรือไม่คือการใช้เมธอด PackageManager.hasSystemFeature เพื่อตรวจสอบว่าอุปกรณ์ทำงานในโหมดทีวีหรือไม่ โค้ดตัวอย่างต่อไปนี้แสดงวิธีตรวจสอบว่าแอปทำงานบนอุปกรณ์ทีวีหรือไม่

Kotlin

const val TAG = "DeviceTypeRuntimeCheck"

val isTelevision = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
if (isTelevision) {
    Log.d(TAG, "Running on a TV Device")
} else {
    Log.d(TAG, "Running on a non-TV Device")
}

Java

public static final String TAG = "DeviceTypeRuntimeCheck";

boolean isTelevision = getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
if (isTelevision) {
    Log.d(TAG, "Running on a TV Device");
} else {
    Log.d(TAG, "Running on a non-TV Device");
}

จัดการฟีเจอร์ฮาร์ดแวร์ที่ไม่รองรับ

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

ฟีเจอร์ฮาร์ดแวร์ทีวีที่ไม่รองรับ

ทีวีมีวัตถุประสงค์ที่แตกต่างจากอุปกรณ์อื่นๆ จึงไม่มีฟีเจอร์ฮาร์ดแวร์ที่อุปกรณ์ที่ทำงานด้วยระบบ Android อื่นๆ มักจะมี ด้วยเหตุนี้ ระบบ Android จึงไม่รองรับฟีเจอร์ต่อไปนี้สำหรับอุปกรณ์ทีวี

ฮาร์ดแวร์ ข้อบ่งชี้ฟีเจอร์ของ Android
หน้าจอสัมผัส android.hardware.touchscreen
โปรแกรมจำลองหน้าจอสัมผัส android.hardware.faketouch
โทรศัพท์ android.hardware.telephony
กล้อง android.hardware.camera
Near Field Communication (NFC) android.hardware.nfc
GPS android.hardware.location.gps
ไมโครโฟน android.hardware.microphone
เซ็นเซอร์ android.hardware.sensor
หน้าจอในแนวตั้ง android.hardware.screen.portrait

หมายเหตุ: ตัวควบคุมทีวีบางรุ่นมีไมโครโฟน ซึ่งไม่เหมือนกับฟีเจอร์ฮาร์ดแวร์ไมโครโฟนที่อธิบายไว้ที่นี่ ระบบรองรับไมโครโฟนของตัวควบคุมอย่างเต็มรูปแบบ

ดูรายการฟีเจอร์ ฟีเจอร์ย่อย และข้อบ่งชี้ทั้งหมดได้ใน ข้อมูลอ้างอิงเกี่ยวกับฟีเจอร์

ประกาศข้อกำหนดด้านฮาร์ดแวร์สำหรับทีวี

แอป Android สามารถประกาศข้อกำหนดด้านฟีเจอร์ฮาร์ดแวร์ในไฟล์ Manifest ของแอปเพื่อช่วยให้มั่นใจว่าแอปจะไม่ได้รับการติดตั้งในอุปกรณ์ที่ไม่มีฟีเจอร์เหล่านั้น หากคุณกำลังขยายแอปที่มีอยู่เพื่อใช้ในทีวี ให้ตรวจสอบไฟล์ Manifest ของแอปอย่างละเอียดเพื่อดูการประกาศข้อกำหนดด้านฮาร์ดแวร์ที่อาจทำให้ติดตั้งในอุปกรณ์ทีวีไม่ได้

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

<uses-feature android:name="android.hardware.touchscreen"
        android:required="false"/>
<uses-feature android:name="android.hardware.faketouch"
        android:required="false"/>
<uses-feature android:name="android.hardware.telephony"
        android:required="false"/>
<uses-feature android:name="android.hardware.camera"
        android:required="false"/>
<uses-feature android:name="android.hardware.nfc"
        android:required="false"/>
<uses-feature android:name="android.hardware.location.gps"
        android:required="false"/>
<uses-feature android:name="android.hardware.microphone"
        android:required="false"/>
<uses-feature android:name="android.hardware.sensor"
        android:required="false"/>
<!-- Some TV devices have an ethernet connection only -->
<uses-feature android:name="android.hardware.wifi"
        android:required="false"/>

หมายเหตุ: ฟีเจอร์บางอย่างมีฟีเจอร์ย่อย เช่น android.hardware.camera.front ตามที่อธิบายไว้ใน ข้อมูลอ้างอิงฟีเจอร์ อย่าลืมทำเครื่องหมายฟีเจอร์ย่อยที่ใช้ในแอปของคุณเป็นrequired="false"ด้วย

แอปทั้งหมดที่มีไว้สำหรับใช้ในอุปกรณ์ทีวีต้องประกาศว่าไม่จำเป็นต้องใช้ฟีเจอร์หน้าจอสัมผัส ตามที่อธิบายไว้ในเริ่มต้นใช้งานแอปทีวี หากปกติแล้วแอปใช้ฟีเจอร์อย่างน้อย 1 รายการที่อุปกรณ์ทีวีไม่รองรับ ให้เปลี่ยนการตั้งค่าแอตทริบิวต์ android:required เป็น false สำหรับฟีเจอร์เหล่านั้นในไฟล์ Manifest

ข้อควรระวัง: การประกาศฟีเจอร์ฮาร์ดแวร์ตามที่กำหนดโดยการตั้งค่าเป็น true จะทำให้แอปของคุณติดตั้งในอุปกรณ์ทีวีหรือปรากฏใน Launcher ของหน้าจอหลักของ Android TV ไม่ได้

ระวังสิทธิ์ที่บ่งบอกถึงฟีเจอร์ฮาร์ดแวร์

การประกาศไฟล์ Manifest uses-permission บางรายการบอกเป็นนัยถึงฟีเจอร์ฮาร์ดแวร์ ลักษณะการทำงานนี้หมายความว่าการขอสิทธิ์บางอย่างในไฟล์ Manifest ของแอปอาจทำให้แอปของคุณไม่สามารถติดตั้งและใช้งานในอุปกรณ์ทีวีได้ สิทธิ์ที่ขอโดยทั่วไปต่อไปนี้จะสร้างข้อกำหนดฟีเจอร์ฮาร์ดแวร์โดยนัย

สิทธิ์ ฟีเจอร์ฮาร์ดแวร์โดยนัย
RECORD_AUDIO android.hardware.microphone
CAMERA android.hardware.camera และ
android.hardware.camera.autofocus
ACCESS_COARSE_LOCATION

android.hardware.location

android.hardware.location.network (ระดับ API เป้าหมาย 20 หรือต่ำกว่าเท่านั้น)

ACCESS_FINE_LOCATION

android.hardware.location

android.hardware.location.gps (ระดับ API เป้าหมาย 20 หรือต่ำกว่าเท่านั้น)

ACCESS_WIFI_STATE
CHANGE_WIFI_STATE

android.hardware.wifi

อุปกรณ์ทีวีบางเครื่องมีการเชื่อมต่ออีเทอร์เน็ตเท่านั้น

ดูรายการคำขอสิทธิ์ทั้งหมดที่บ่งบอกถึงข้อกำหนดฟีเจอร์ฮาร์ดแวร์ได้ในคู่มือ uses-feature หากแอปขอฟีเจอร์ใดฟีเจอร์หนึ่งที่ระบุไว้ก่อนหน้านี้ ให้ใส่การประกาศ uses-feature ในไฟล์ Manifest สำหรับฟีเจอร์ฮาร์ดแวร์โดยนัยซึ่งระบุว่าไม่จำเป็นต้องใช้ android:required="false"

หมายเหตุ: หากแอปกำหนดเป้าหมายเป็น Android 5.0 (ระดับ API 21) ขึ้นไปและใช้สิทธิ์ ACCESS_COARSE_LOCATION หรือ ACCESS_FINE_LOCATION ผู้ใช้จะยังคงติดตั้งแอปในอุปกรณ์ทีวีได้ แม้ว่าอุปกรณ์ทีวีจะไม่มีการ์ดเครือข่ายหรือเครื่องรับ GPS ก็ตาม

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับการกรองและการประกาศฟีเจอร์ในไฟล์ Manifest ได้ที่คู่มือ uses-feature

ตรวจสอบฟีเจอร์ฮาร์ดแวร์

เฟรมเวิร์ก Android จะแจ้งให้คุณทราบหากฟีเจอร์ฮาร์ดแวร์ไม่พร้อมใช้งานในอุปกรณ์ที่แอปทำงานอยู่ ใช้เมธอด hasSystemFeature(String) เพื่อตรวจสอบฟีเจอร์ที่เฉพาะเจาะจงขณะรันไทม์ เมธอดนี้ใช้อาร์กิวเมนต์สตริงเดียวที่ระบุฟีเจอร์ที่ต้องการตรวจสอบ

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีตรวจหาความพร้อมใช้งานของฟีเจอร์ฮาร์ดแวร์ที่รันไทม์

Kotlin

// Check whether the telephony hardware feature is available.
if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
    Log.d("HardwareFeatureTest", "Device can make phone calls")
}

// Check whether android.hardware.touchscreen feature is available.
if (packageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
    Log.d("HardwareFeatureTest", "Device has a touchscreen.")
}

Java

// Check whether the telephony hardware feature is available.
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
    Log.d("HardwareFeatureTest", "Device can make phone calls");
}

// Check whether android.hardware.touchscreen feature is available.
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
    Log.d("HardwareFeatureTest", "Device has a touchscreen.");
}

หน้าจอสัมผัส

อุปกรณ์ทีวีส่วนใหญ่ไม่มีหน้าจอสัมผัสหรือความสามารถในการป้อนข้อมูลด้วยเคอร์เซอร์ และอาศัยรีโมตคอนโทรลแบบปุ่มบังคับทิศทาง (D-pad) ในการไปยังส่วนต่างๆ โดยสมบูรณ์ แอป TV ต้องรองรับรีโมตคอนโทรลแบบ D-pad เสมอ

ดูข้อมูลเพิ่มเติมเกี่ยวกับการรองรับการนำทางอย่างเหมาะสมโดยใช้การควบคุมที่เหมาะกับทีวีได้ที่การนำทางในทีวี

ประกาศการรองรับการสัมผัส

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

หากแอปของคุณอนุญาตให้ใช้โหมดการสัมผัส คุณสามารถประกาศการรองรับการสัมผัสสำหรับทั้งแอปหรือสำหรับกิจกรรมแต่ละรายการได้โดยเพิ่มองค์ประกอบ android.software.leanback.supports_touch <property> ที่ตั้งค่าเป็น true ไว้ภายในองค์ประกอบ <application> หรือ <activity> ใน AndroidManifest.xml ดังนี้

<application ...>
    <property
        android:name="android.software.leanback.supports_touch"
        android:value="true|false" />
    ...
</application>

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

กล้อง

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

<uses-feature android:name="android.hardware.camera" android:required="false" />

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

Kotlin

// Check whether the camera hardware feature is available.
if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
    Log.d("Camera test", "Camera available!")
} else {
    Log.d("Camera test", "No camera available. View and edit features only.")
}

Java

// Check whether the camera hardware feature is available.
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
    Log.d("Camera test", "Camera available!");
} else {
    Log.d("Camera test", "No camera available. View and edit features only.");
}

GPS

ทีวีเป็นอุปกรณ์ที่ติดตั้งอยู่กับที่ภายในอาคารและไม่มีตัวรับสัญญาณระบบดาวเทียมนำร่อง (GPS) ในตัว หากแอปใช้ข้อมูลตำแหน่ง คุณยังคงอนุญาตให้ผู้ใช้ค้นหาตำแหน่งหรือใช้ผู้ให้บริการตำแหน่งแบบคงที่ เช่น รหัสไปรษณีย์ที่กำหนดค่าไว้ระหว่างการตั้งค่าอุปกรณ์ทีวีได้

Kotlin

// Request a static location from the location manager.
val locationManager = this.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val location = locationManager.getLastKnownLocation("static")
if (location == null) {
    Log.e(TAG, "Location is null")
    return
}

// Attempt to get postal code from the static location object.
val geocoder = Geocoder(this)
val address: Address? =
        try {
            geocoder.getFromLocation(location.latitude, location.longitude, 1)?.firstOrNull()
                    ?.apply {
                        Log.d(TAG, postalCode)
                    }
        } catch (e: IOException) {
            Log.e(TAG, "Geocoder error", e)
            null
        }

Java

// Request a static location from the location manager.
LocationManager locationManager = (LocationManager) this.getSystemService(
        Context.LOCATION_SERVICE);
Location location = locationManager.getLastKnownLocation("static");

// Attempt to get postal code from the static location object.
Geocoder geocoder = new Geocoder(this);
Address address = null;
try {
  address = geocoder.getFromLocation(location.getLatitude(),
          location.getLongitude(), 1).get(0);
  Log.d("Postal code", address.getPostalCode());

} catch (IOException e) {
  Log.e(TAG, "Geocoder error", e);
}

หยุดเล่นชั่วคราวระหว่างโหมดใช้พลังงานต่ำ

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

หากต้องการหลีกเลี่ยงการเล่นระหว่างโหมดใช้พลังงานต่ำ ให้ลบล้าง onStop และหยุดเนื้อหาที่กำลังเล่นอยู่

Kotlin

override fun onStop() {
    // App-specific method to stop playback.
    stopPlayback()
    super.onStop()
}

Java

@Override
public void onStop() {
  // App-specific method to stop playback.
  stopPlayback();
  super.onStop();
}

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