導航:首頁 > 操作系統 > androidtv開發焦點控制

androidtv開發焦點控制

發布時間:2025-05-14 03:20:10

1. Andorid TV 開發之連接機頂盒及常用 adb 命令

國內的 Android TV 應用雖然是在 TV 上顯示,但是實際上大都運行在各類機頂盒中(當然也可以運行在智能電視本身定製的 Android 系統中),這些機頂盒運行的都是各個廠商基於 Android 各個版本系統定製的 ROM,並不是 Google 原生的Android TV 系統。

開發手機 app 應用,手機開啟調試模式,用數據線連上手機,就能對手機進行 debug 開發。然而,機頂盒並沒有手機的 micro usb 介面,並不能連數據線進行直接調試(據說,用 USB to USB 數據線連接機頂盒,也無法識別機頂盒),這時需要使用 adb 命令連接和調試機頂盒。打開 Android Studio 的 Terminal 或者 cmd( windows )、終端( mac ),輸入 adb 出現如下結果,證明 adb命令可以正常使用,否則參照 adb 錯誤「 'adb' 不是內部或外部命令,也不是可運行的程序或批處理文件 ( windows ) 或 在 MAC OS X 安裝 ADB (Android 調試橋)
( mac )開啟 adb 命令。

如果沒有提示任何錯誤信息,表示連接機頂盒成功,接著輸入
adb devices 查看連接的機頂盒的狀態信息。
如果提示 xxxxx refused connect 證明還未獲取機頂盒的調試許可權,需要和機頂盒廠家獲取調試工具、開啟調試功能的方法、調試埠等(許多機頂盒的廠商都留有調試後門),也可以 root 機頂盒的系統。

adb connect [ip]:[port] 連接機頂盒(默認埠為薯則雀5555)
adb devices 查看所有連接設備 名稱、ip、埠已經數早狀態( device 或 offline )
adb install [apk 安裝包所在路徑(如:d:\a.apk)] 將對應路徑的 apk 安裝包安裝到機頂盒
adb install -r [apk 安裝包所在路徑(如:d:\a.apk)] 將對應路徑的apk 安裝包強制(覆蓋)安裝到機頂盒
adb -s [設備名稱或設備IP:埠] install [apk 安裝包所在路徑(如:d:/a.apk)] 當 adb 連接多個設備時,將 apk 安裝到指定設備中

adb uninstall [應用包名,例如:com.example.tmall] 卸載應用(通過包名指定)
adb shell 進入系統目錄(通過 exit 退出)
adb shell am start -n [包名]/盯碧[包名+類名] 啟動指定類名的 Activity

adb shell input text **** 在已經獲取焦點的EditText中輸入內容
adb shell ps 查看當前終端中的進程信息
adb shell mpsys activity activites 查看當前終端所以前後台Acitivity的堆棧
adb shell logcat > d:\log.txt 列印日誌到本地文件(會列印緩存的日誌,可能會有昨天等之前日誌。windows下,按 ctrl+c 停止日誌列印)
adb logcat *:D > d:\log.txt 過濾出 D 級別以上的日誌,列印日誌到本地文件( 在 macOS 下需要給 *:W 這樣以 * 作為 tag 的參數加雙引號,如 adb logcat "*:W" )

awesome-adb

Android ADB 命令大全(通過 ADB 命令查看 wifi 密碼、MAC 地址、設備信息、操作文件、查看文件、日誌信息、卸載、啟動和安裝 APK 等)

連接上機頂盒的一小步,是機頂盒開發的一大步。

2. Android移動應用中的焦點分析

簡單一點理解,在移動應用中,焦點就是當前正在處理事件的位置。在手機應用中,最有可能用到焦點的就是EditText,如果同一個界面中有多個EditText,通常情況下同一時間只有一個能夠輸入內容,此時,這個EditText就獲取了焦點。

在Android中,對焦點的設置分為兩種情況,TouchMode和非TouchMode。現在的手機基本都是觸摸屏,我們用手指觸摸屏幕來操作Android應用時,處於TouchMode。除了TouchMode之外,還有非TouchMode,利用外接設備來操作早衫應用。比如鍵盤。使用Genymotion模擬器的時候,一個陸兄腔界面上有多個控制項時,可以用電腦tab鍵來進行移動,被選中的控制項會高亮顯示,這時候就是非TouchMode,被選中的控制項獲得了焦點。

在手機應用中,用到焦點的時候並不多,但是TV應用中,需要用遙控器來操作選中控制項,這時候就需要對焦點進行處理了。關於焦點,常用方法如下:

在View類中, isFocusable() 和 isFocusableInTouchMode() 獲取到的結果都是false,也就是說,直接繼承自View的控制項是不能獲取焦點的。我們常用控制項中對這兩個方法進行了改寫,比如EditText,這兩個方法都是true,而Button則只有 isFocusable() 返回true。這也就是為什麼我們用tab鍵選取Button的時候能夠高亮顯示,而滑鼠點擊(模擬觸控)的時候不能高亮顯示的原因了。如果想在點擊的時候也能高亮顯示Button,需要手動設置 setFocusableInTouchMode(true) ,就可以了。

如果想對控制項的焦點狀態進行監聽,需要設置 setOnFocusChangeListener() ,只要控制項的焦點狀態發生變化(獲得或者失去焦點),都會調用 onFocusChange 方法

關於焦點的移動,默認的演算法會尋找指定方向上最近的可以獲取焦點的元素(非TouchMode)。另外在創建控制項的時候,也可以指定尋找焦點的方向,設置nextFocusDown、nextFocusLeft、nextFocusRight 和 nextFocusUp的值為指定元素就可以了。看以下例子:

這里指定了上面的button向上尋找焦點時,下一個元素是id為bottom的元素,也就是說,上面的Button在獲取了焦點之後,繼續按向上鍵,系統會將焦點移動到id為bottom的元素上,而不是繼續向上。

在開發手機應用的過程中,對焦點的處理並不多,它與事件是兩個不同的體系,通常情況下焦點和事件是相互獨立並不沖突。但是在Button的點擊事件中會有一點問題。如果我們隊一個button設置了 setFocusableInTouchMode(true) ,使他可以獲取焦點,那麼我們點擊這個button的時候,第一次點擊並不會執行 onClick() 方法,而是執行 onFocusChange() 。第二次點擊的時候才會執行 onClick() 方法。看起來好像 onFocusChange() 消耗了點擊事件,實際上並不是的。

這個問題我們看一下源碼就清楚了:

onClick() 方法是在onTouchEvent的ACTION_UP里調用的,看一下View的onTouchEvent方法:

可以看到,只有當focusTaken為false的時候才會執行onClick,focusTaken的值默認是false的,但是在 isFocusable() && isFocusableInTouchMode() && !isFocused() 為true的時候,會去 requestFocus 獲取焦點,並將值賦給focusTaken。

關鍵在於 isFocused() ,如果當前Button沒塵碼有獲取焦點, isFocused() 返回false, !isFocused() 值為ture,Button就會去獲取焦點,從而導致 focusTaken 為true, onClick 方法就不會執行了,只有Button已經獲取了焦點的時候才會執行onClick方法。

3. Android TV 焦點原理源碼解析

相信很多剛接觸AndroidTV開發的開發者,都會被各種焦點問題給折磨的不行。不管是學技術還是學習其他知識,都要學習和理解其中原理,碰到問題我們才能得心應手。下面就來探一探Android的焦點分發的過程。

Android焦點事件的分發是從ViewRootImpl的processKeyEvent開始的,源碼如下:

源碼比較長,下面我就慢慢來講解一下具體的每一個細節。

dispatchKeyEvent方法返回true代表焦點事件被消費了。

ViewGroup的dispatchKeyEvent()方法的源碼如下:

(2)ViewGroup的dispatchKeyEvent執行流程

(3)下面再來瞧瞧view的dispatchKeyEvent方法的具體的執行過程

驚奇的發現執行了onKeyListener中的onKey方法,如果onKey方法返回true,那麼dispatchKeyEvent方法也會返回true

可以得出結論:如果想要修改ViewGroup焦點事件的分發,可以這么干:

注意:實際開發中,理論上所有焦點問題都可以通過給dispatchKeyEvent方法增加監聽來來攔截來控制。

(1)dispatchKeyEvent方法返回false後,先得到按鍵的方向direction值,這個值是一個int類型參數。這個direction值是後面來進行焦點查找的。

(2)接著會調用DecorView的findFocus()方法一層一層往下查找已經獲取焦點的子View。
ViewGroup的findFocus方法如下:

View的findFocus方法

說明:判斷view是否獲取焦點的isFocused()方法, (mPrivateFlags & PFLAG_FOCUSED) != 0 和view 的isFocused()方法是一致的。

其中isFocused()方法的作用是判斷view是否已經獲取焦點,如果viewGroup已經獲取到了焦點,那麼返回本身即可,否則通過mFocused的findFocus()方法來找焦點。mFocused其實就是ViewGroup中獲取焦點的子view,如果mView不是ViewGourp的話,findFocus其實就是判斷本身是否已經獲取焦點,如果已經獲取焦點了,返回本身。

(3)回到processKeyEvent方法中,如果findFocus方法返回的mFocused不為空,說明找到了當前獲取焦點的view(mFocused),接著focusSearch會把direction(遙控器按鍵按下的方向)作為參數,找到特定方向下一個將要獲取焦點的view,最後如果該view不為空,那麼就讓該view獲取焦點。

(4)focusSearch方法的具體實現。

focusSearch方法的源碼如下:

可以看出focusSearch其實是一層一層地網上調用父View的focusSearch方法,直到當前view是根布局(isRootNamespace()方法),通過注釋可以知道focusSearch最終會調用DecorView的focusSearch方法。而DecorView的focusSearch方法找到的焦點view是通過FocusFinder來找到的。

(5)FocusFinder是什麼?

它其實是一個實現 根據給定的按鍵方向,通過當前的獲取焦點的View,查找下一個獲取焦點的view這樣演算法的類。焦點沒有被攔截的情況下,Android框架焦點的查找最終都是通過FocusFinder類來實現的。

(6)FocusFinder是如何通過findNextFocus方法尋找焦點的。

下面就來看看FocusFinder類是如何通過findNextFocus來找焦點的。一層一層往下看,後面會執行findNextUserSpecifiedFocus()方法,這個方法會執行focused(即當前獲取焦點的View)的findUserSetNextFocus方法,如果該方法返回的View不為空,且isFocusable = true && isInTouchMode() = true的話,FocusFinder找到的焦點就是findNextUserSpecifiedFocus()返回的View。

(7)findNextFocus會優先根據XML里設置的下一個將獲取焦點的View ID值來尋找將要獲取焦點的View。

看看View的findUserSetNextFocus方法內部都幹了些什麼,OMG不就是通過我們xml布局裡設置的nextFocusLeft,nextFocusRight的viewId來找焦點嗎,如果按下Left鍵,那麼便會通過nextFocusLeft值里的View Id值去找下一個獲取焦點的View。

可以得出以下結論:

1. 如果一個View在XML布局中設置了focusable = true && isInTouchMode = true,那麼這個View會優先獲取焦點。

2. 通過設置nextFocusLeft,nextFocusRight,nextFocusUp,nextFocusDown值可以控制View的下一個焦點。

Android焦點的原理實現就這些。總結一下:

為了方便同志們學習,我這做了張導圖,方便大家理解~

閱讀全文

與androidtv開發焦點控制相關的資料

熱點內容
賣手錶的app哪裡可以賣 瀏覽:51
放管伺服器怎麼辦理 瀏覽:627
手機號碼如何加密 瀏覽:424
沈陽程序員培訓學校 瀏覽:538
一般伺服器如何配置 瀏覽:895
圖片怎樣加密發郵件 瀏覽:619
萬虹電腦文件夾密碼忘記了怎麼辦 瀏覽:631
rc108單片機 瀏覽:867
戰雷如何改變伺服器 瀏覽:674
mactelnet命令 瀏覽:51
壓縮袋壓縮了拿出來 瀏覽:401
安卓手機相機怎麼設置許可權 瀏覽:121
美女程序員轉行做主播 瀏覽:671
辦理解壓房產 瀏覽:575
道路工程概論pdf 瀏覽:390
超棒數學速演算法大全 瀏覽:938
小米易語言登錄源碼 瀏覽:32
磚牆內加密鋼筋 瀏覽:994
鄉關何處pdf 瀏覽:85
小豬領贊小程序源碼 瀏覽:337