Android 處理TV硬件

2018-08-02 17:57 更新

編寫:awong1900 - 原文:http://developer.android.com/training/tv/start/hardware.html

TV硬件和其他Android設(shè)備有實質(zhì)性的不同。TV不包含一些其他Android設(shè)備具備的硬件特性,如觸摸屏,攝像頭,和GPS。TV操作也完全依賴于其他輔助硬件設(shè)備。為了讓用戶與TV應(yīng)用交互,他們必須使用遙控器或者游戲手柄。當我們創(chuàng)建TV應(yīng)用時,必須小心的考慮到TV硬件的限制和操作要求。

本節(jié)課程討論如何檢查應(yīng)用是不是運行在TV上,怎樣去處理不支持的硬件特性,和討論處理TV設(shè)備控制器的要求。

TV設(shè)備的檢測

如果我們創(chuàng)建的應(yīng)用同時支持TV設(shè)備和其他設(shè)備,我們可能需要檢測應(yīng)用當前運行在哪種設(shè)備上,并調(diào)整應(yīng)用的執(zhí)行。例如,如果有一個應(yīng)用通過Intent啟動,應(yīng)用應(yīng)該檢查設(shè)備特性然后決定是應(yīng)該啟動TV方面的activity還是手機的activity。

檢查應(yīng)用是否運行在TV設(shè)備上,推薦的方式是用UiModeManager.getCurrentModeType())方法檢測設(shè)備是否運行在TV模式。下面的示例代碼展示了如何檢查應(yīng)用是否運行在TV設(shè)備上:

public static final String TAG = "DeviceTypeRuntimeCheck";

UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE);
if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
    Log.d(TAG, "Running on a TV Device")
} else {
    Log.d(TAG, "Running on a non-TV Device")
}

處理不支持的硬件特性

基于應(yīng)用的設(shè)計和功能,我們可能需要在某些硬件特性不可用的情況下工作。這節(jié)討論哪些硬件特性對于TV是典型不可用的,如何去檢測缺少的硬件特性,并且去用這些特性的推薦替代方法。

不支持的TV硬件特性

TV和其他設(shè)備有不同的目的,因此它們沒有一些其他Android設(shè)備通常有的硬件特性。由于這個原因,TV設(shè)備的Android系統(tǒng)不支持以下特性:

硬件Android特性描述
觸屏android.hardware.touchscreen
觸屏模擬器android.hardware.faketouch
電話android.hardware.telephony
攝像頭android.hardware.camera
藍牙android.hardware.bluetooth
近場通訊(NFC)android.hardware.nfc
GPSandroid.hardware.location.gps
麥克風 [1]android.hardware.microphone
傳感器android.hardware.sensor

[1] 一些TV控制器有麥克風,但不是這里描述的麥克風硬件特性??刂破鼷溈孙L是完全被支持的。

查看Features Reference獲得完全的特性和子特性列表,和它們的描述。

聲明TV硬件需求

Android應(yīng)用能通過在manifest中定義硬件特性需求來確保應(yīng)用不能被安裝在不提供這些特性的設(shè)備上。如果我們正在擴展應(yīng)用到TV上,仔細地審查我們的manifest的硬件特性需求,它有可能阻止應(yīng)用安裝到TV設(shè)備上。

即使我們的應(yīng)用使用了TV上不存在的硬件特性(如觸屏或者攝像頭),應(yīng)用也可以在沒有那些特性的情況下工作,需要修改應(yīng)用的manifest來表明這些特性不是必須的。接下來的manifest代碼片段示范了如何聲明在TV設(shè)備中不可用的硬件特性,盡管我們的應(yīng)用在非TV設(shè)備上可能會用上這些特性。

<uses-feature android:name="android.hardware.touchscreen"
        android:required="false"></uses>
<uses-feature android:name="android.hardware.faketouch"
        android:required="false"></uses>
<uses-feature android:name="android.hardware.telephony"
        android:required="false"></uses>
<uses-feature android:name="android.hardware.camera"
        android:required="false"></uses>
<uses-feature android:name="android.hardware.bluetooth"
        android:required="false"></uses>
<uses-feature android:name="android.hardware.nfc"
        android:required="false"></uses>
<uses-feature android:name="android.hardware.gps"
        android:required="false"></uses>
<uses-feature android:name="android.hardware.microphone"
        android:required="false"></uses>
<uses-feature android:name="android.hardware.sensor"
        android:required="false"></uses>

Note:一些特性有子特性,如android.hardware.camera.front,參考:Feature Reference。確保應(yīng)用中任何子特性也標記為required="false"。

所有想用在TV設(shè)備上的應(yīng)用必須聲明觸屏特性不被需要,在創(chuàng)建TV應(yīng)用的第一步有描述。如果我們的應(yīng)用使用了一個或更多的上面列表上的特性,改變manifest特性的android:required屬性為false

Caution:表明一個硬件特性是必須的,設(shè)置它的值為true可以阻止應(yīng)用在TV設(shè)備上安裝或者出現(xiàn)在AndroidTV的主屏幕啟動列表上。

一旦我們決定了應(yīng)用的硬件特性選項,那就必須檢查在運行時這些特性的可用性,然后調(diào)整應(yīng)用的行為。下一節(jié)討論如何檢查硬件特性和改變應(yīng)用行為的建議處理。

更多關(guān)于filter和在manifest里聲明特性,參考:uses-feature。

聲明權(quán)限會隱含硬件特性

一些uses-permission manifest聲明隱含了硬件特性。這些行為意味著在應(yīng)用中請求一些權(quán)限能導(dǎo)致應(yīng)用不能安裝和使用在TV設(shè)備上。下面普通的權(quán)限請求包含了一個隱式的硬件特性需求:

權(quán)限隱式的硬件需求
RECORD_AUDIOandroid.hardware.microphone
CAMERAandroid.hardware.camera and android.hardware.camera.autofocus
ACCESS_COARSE_LOCATIONandroid.hardware.location and android.hardware.location.network
ACCESS_FINE_LOCATIONandroid.hardware.location and android.hardware.location.gps

包含隱式硬件特性需求的完整權(quán)限需求列表,參考:uses-feature。如果我們的應(yīng)用請求了上面列表上的特性的任何一個,在manifest中設(shè)置它的隱式硬件特性為不需要(android:required="false")。

檢查硬件特性

在應(yīng)用運行時,Android framework能告訴硬件特性是否可用。用hasSystemFeature(String))方法在運行時檢查特定的特性。這個方法只需要一個字符串參數(shù),即想檢查的特性名字。

接下來的示例代碼展示了如何在運行時檢測硬件特性的可用性:

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

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

觸屏

因為大部分的TV沒有觸摸屏,在TV設(shè)備上,Android不支持觸屏交互。此外,用觸屏交互和坐在離顯示器3米外觀看是相互矛盾的。

在TV設(shè)備中,我們應(yīng)該設(shè)計出支持遙控器方向鍵(D-pad)遠程操作的交互模式。更多關(guān)于正確地支持TV友好的控制器操作的信息,參考Creating TV Navigation。

攝像頭

盡管TV通常沒有攝像頭,但是我們?nèi)匀豢梢蕴峁┡恼障嚓P(guān)的TV應(yīng)用,如果應(yīng)用有拍照,查看和編輯圖片功能,在TV上可以關(guān)閉拍照功能但仍可以允許用戶查看甚至編輯圖片。如果我們決定在TV上使用攝像相關(guān)的應(yīng)用,在manifest里添加接下來的特性聲明:

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

如果在缺少攝像頭情況下運行應(yīng)用,在我們應(yīng)用中添加代碼去檢測是否攝像頭特性可用,并且調(diào)整應(yīng)用的操作。接下來的示例代碼展示了如何檢測一個攝像頭的存在:

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

GPS

TV是固定的室內(nèi)設(shè)備,并且沒有內(nèi)置的全球定位系統(tǒng)(GPS)接收器。如果我們應(yīng)用使用定位信息,我們?nèi)钥梢栽试S用戶搜索位置,或者用固定位置提供商代替,如在TV設(shè)置中設(shè)置郵政編碼。

// 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 or zip 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("Zip code", address.getPostalCode());

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

處理控制器

TV設(shè)備需要輔助硬件設(shè)備與應(yīng)用交互,如一個基本形式的遙控器或者游戲手柄。這意味著我們應(yīng)用必須支持D-pad(十字方向鍵)輸入。它也意味著我們應(yīng)用可能需要處理手柄掉線和更多類型的手柄輸入。

D-pad最低控制要求

默認的TV設(shè)備控制器是D-pad。通常,我們可以用遙控器的上,下,左,右,選擇,返回,和Home鍵操作應(yīng)用。如果應(yīng)用是一個游戲而需要游戲手柄額外的控制,它也應(yīng)該嘗試允許用D-pad操作。這種情況下,應(yīng)用也應(yīng)該警告用戶需要手柄,并且允許他們用D-pad優(yōu)雅的退出游戲。更多關(guān)于在TV設(shè)備如理D-pad的操作,參考Creating TV Navigation。

處理手柄掉線

TV的手柄通常是藍牙設(shè)備,它為了省電而定期的休眠并且與TV設(shè)備斷開連接。這意味著如果不處理這些重連事件,應(yīng)用可能被中斷或者重新開始。這些事件可以發(fā)生在下面任何情景中:

  • 當在看幾分鐘的視頻,D-Pad或者游戲手柄進入了睡眠模式,從TV設(shè)備上斷開連接并且隨后重新連接。
  • 在玩游戲時,新玩家用不是當前連接的游戲手柄加入游戲。
  • 在玩游戲時,一個玩家離開游戲并且斷開游戲手柄。

任何TV應(yīng)用activity相關(guān)于斷開和重連事件。這些事件必須在應(yīng)用的manifest配置去處理。接下來的示例代碼展示了如何確保一個activity去處理配置改變,包括鍵盤或者操作設(shè)備連接,斷開連接,或者重新連接:

<activity
  android:name="com.example.android.TvActivity"
  android:label="@string/app_name"
  android:configChanges="keyboard|keyboardHidden|navigation"
  android:theme="@style/Theme.Leanback">

  <intent-filter>
    <action android:name="android.intent.action.MAIN" ></action>
    <category android:name="android.intent.category.LEANBACK_LAUNCHER" ></category>
  </intent-filter>
  ...
</activity>

這個配置改變屬性允許應(yīng)用通過重連事件繼續(xù)運行,比較而言Android framework強制重啟應(yīng)用會導(dǎo)致一個不好的用戶體驗。

處理D-pad變種輸入

TV設(shè)備用戶可能有超過一種類型的控制器來操作TV。例如,一個用戶可能有基本D-pad控制器和一個游戲控制器。游戲控制器用于D-pad功能的按鍵代碼可能和物理十字鍵提供的不相同。

我們的應(yīng)用應(yīng)該處理游戲控制器D-pad的變種輸入,這樣用戶不需要通過手動切換控制器去操作應(yīng)用。更多信息關(guān)于處理這些變種輸入,參考Handling Controller Actions。


下一節(jié): 創(chuàng)建TV布局 >


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號