劉 馬 飛
(無(wú)錫職業(yè)技術(shù)學(xué)院物聯(lián)網(wǎng)技術(shù)學(xué)院 江蘇 無(wú)錫 214121)
大客車通常需要在客車內(nèi)安裝車載播放器,以便在長(zhǎng)途行車時(shí)提供娛樂(lè)節(jié)目、電影給乘客觀賞。目前車載播放器通常采使用獨(dú)立的DVD播放器或移動(dòng)硬盤播放機(jī),不但系統(tǒng)成本高,而且DVD播放器更換影片必須使用DVD影碟、移動(dòng)硬盤播放機(jī)更換影片必須通過(guò)移動(dòng)硬盤拷貝,使用不夠方便。
由于基于Android的中控大屏由于具有豐富的娛樂(lè)功能、方便與手機(jī)和網(wǎng)絡(luò)互聯(lián)的優(yōu)點(diǎn),已經(jīng)成為高端新能源客車的流行配置。Android在4.2版本以后支持雙屏異顯[1]功能,可以實(shí)現(xiàn)在兩塊屏幕上同時(shí)顯示不同的內(nèi)容。因此只需在Android中控大屏的基礎(chǔ)上,額外配備一個(gè)車載顯示屏,通過(guò)設(shè)計(jì)相應(yīng)播放器程序,便可低成本地實(shí)現(xiàn)為乘客播放視頻的功能,播放器程序使用Android中控大屏作為播放器操控界面(主屏),視頻播放輸出在車載顯示屏(副屏),而且操作體驗(yàn)良好;此外由于Android設(shè)備方便聯(lián)網(wǎng),使得播放器的影片可通過(guò)網(wǎng)絡(luò)下載,使用更方便快捷。
本文介紹了利用Android雙屏異顯功能的車載視頻播放器的設(shè)計(jì)和實(shí)現(xiàn)。該車載播放器可低成本地滿足大客車為乘客播放視頻的需要,使用操作靈活簡(jiǎn)便,有較廣闊的市場(chǎng)應(yīng)用價(jià)值。
所謂雙屏異顯即在同一軟硬件平臺(tái)上實(shí)現(xiàn)同時(shí)驅(qū)動(dòng)兩塊LCD屏幕,并且這兩塊屏幕所顯示的內(nèi)容可以不同[1]。Android在4.2版本以后支持雙屏異顯功能,默認(rèn)情況下兩塊屏幕顯示內(nèi)容一致,需要基于特定平臺(tái)的雙屏異顯方案進(jìn)行編寫程序方可實(shí)現(xiàn)兩個(gè)屏幕顯示不同內(nèi)容。
Presentation 是Google在Android4.2版本以后提供的通用雙屏方案,是Google官方提供的一個(gè)特殊的dialog,用來(lái)將特定內(nèi)容顯示到其他非主屏顯示器上,從而輕松實(shí)現(xiàn)在兩塊屏幕上同時(shí)顯示不同的內(nèi)容。Presentation在創(chuàng)建時(shí),需要綁定顯示屏,并根據(jù)這個(gè)目標(biāo)顯示屏以及其大小來(lái)配置context和 resource。目前系統(tǒng)提供通過(guò)MediaRouter接口和通過(guò)DisplayManager 接口兩種方式將Presentation與目標(biāo)顯示屏進(jìn)行綁定[2-3]。本文雙屏實(shí)現(xiàn)時(shí)采用通過(guò)DisplayManager 接口進(jìn)行顯示屏綁定。
本車載視頻播放器具有以下功能:
(1) 播放視頻顯示輸出在副屏,視頻播放操作控制在主屏進(jìn)行,主屏可通過(guò)應(yīng)用程序界面和桌面小部件(widget)對(duì)播放器進(jìn)行播放控制。不播放視頻時(shí),副屏顯示歡迎界面。
(2) 桌面程序可顯示當(dāng)前播放視頻名稱,并可進(jìn)行播放/暫停、停止、播上一部以及播下一部操作。
(3) 應(yīng)用程序界面包含播放文件列表供播放選擇,并顯示當(dāng)前播放文件、播放時(shí)間總長(zhǎng)以及當(dāng)前播放時(shí)間,并支持通過(guò)拖動(dòng)進(jìn)度條對(duì)變更視頻播放位置。
(4) Android系統(tǒng)開(kāi)機(jī)后,播放器后臺(tái)啟動(dòng),在副屏顯示歡迎界面。
(5) 播放器監(jiān)測(cè)Android設(shè)備外存中可播放的視頻文件的刪除或新增操作,自動(dòng)變更播放器播放視頻列表。
Android平臺(tái)播放音視頻通常使用自帶的組件MediaPlayer,在進(jìn)行視頻播放時(shí)通常還需要利用SurfaceView等設(shè)置視頻輸出的界面控件[4-5]。通常Android音頻播放器通過(guò)Service實(shí)現(xiàn)后臺(tái)播放的需求,當(dāng)Android跳轉(zhuǎn)到其他程序,播放器程序轉(zhuǎn)到后臺(tái)運(yùn)行不顯示時(shí),音樂(lè)仍然繼續(xù)播放[6-7]。而Android視頻播放器由于轉(zhuǎn)到后臺(tái)運(yùn)行后視頻畫(huà)面已不可見(jiàn),通常不需要支持后臺(tái)播放功能[8-9]。與一般視頻播放器不一樣,服務(wù)于大客車為乘客播放視頻的雙屏異顯視頻播放器的視頻輸出是在副屏,因此需要通過(guò)Service支持后臺(tái)播放功能,當(dāng)主屏操控程序轉(zhuǎn)到后臺(tái)運(yùn)行不可見(jiàn)時(shí),副屏的視頻仍需持續(xù)播放,同時(shí)要求Android系統(tǒng)開(kāi)機(jī)后便啟動(dòng)雙屏顯示功能。依據(jù)功能要求,本文設(shè)計(jì)的車載視頻播放器軟件總體模塊如圖1所示。
圖1 車載視頻播放器軟件總體模塊
模塊各功能如下:
(1) 后臺(tái)服務(wù)SndDisplayService為本播放器實(shí)現(xiàn)的核心,其包括用于播放視頻的MediaPlayer和SurfaceView對(duì)象、繼承于Presentation的DifferentDislay類完成副屏的顯示控制、用于接收桌面程序操作的VideoWidgetReceiver、用于視頻文件變動(dòng)監(jiān)聽(tīng)完成維護(hù)視頻文件列表的繼承于ContentObserver的VideoObserver類。
(2) AutoStartBroadcastReceiver 繼承于Android核心組件BroadcastReceiver[10],并通過(guò)在AndroidManifest.xml中靜態(tài)注冊(cè)該廣播接收器接收系統(tǒng)開(kāi)機(jī)啟動(dòng)信號(hào)BOOT_COMPLETED,重寫其onReceive方法,在該方法中通過(guò)調(diào)用startService啟動(dòng)后臺(tái)服務(wù)SndDisplayService。
(3) MainActivity 是主操作界面,列表顯示外存所有視頻文件供點(diǎn)擊進(jìn)行播放,并顯示當(dāng)前播放的視頻文件信息,播放總時(shí)間長(zhǎng)度和當(dāng)前播放時(shí)間,通過(guò)按鈕選擇暫停/播放、靜音/取消靜音、停止播放、播上一部和播下一部等操作,并可通過(guò)拖動(dòng)進(jìn)度改變當(dāng)前播放視頻播放時(shí)間。
(4) AppWidget為桌面小部件(widget)[11],可顯示當(dāng)前正在播放視頻名稱,并可進(jìn)行相應(yīng)的暫停/播放、播上一部、播下一部和停止播放操作。
后臺(tái)服務(wù)SndDisplayService為本播放器實(shí)現(xiàn)的核心,AppWidget桌面程序和主程序界面MainActivity均發(fā)送操作指令到后臺(tái)服務(wù)SndDisplayService實(shí)現(xiàn)播放控制。本雙屏異顯播放器總體運(yùn)行流程如圖2所示。
圖2 軟件運(yùn)行流程
(1) Android系統(tǒng)開(kāi)機(jī)啟動(dòng)后,靜態(tài)注冊(cè)的廣播接收器AutoStartBroadcastReceiver接收開(kāi)機(jī)啟動(dòng)信號(hào),通過(guò)startService開(kāi)啟后臺(tái)服務(wù)SndDisplayService。
(2) 后臺(tái)服務(wù)在onCreate操作中完成初始化媒體播放器初始化,同時(shí)通過(guò)動(dòng)態(tài)兩個(gè)內(nèi)建廣播接收器對(duì)象。廣播接收器對(duì)象VideoWidgetReceiver用于接收Widget桌面程序的操作指令,廣播接收器對(duì)象VideoObserver監(jiān)測(cè)外部存儲(chǔ)視頻媒體庫(kù)文件變動(dòng)維護(hù)播放視頻文件列表。后臺(tái)服務(wù)啟動(dòng)關(guān)閉時(shí),注銷相應(yīng)的廣播接收器。
后臺(tái)服務(wù)啟動(dòng)后,便可通過(guò)MainActivity主程序界面和AppWidget桌面程序進(jìn)行播放器操控。
(3) 播放器主程序界面MainActivity在前臺(tái)運(yùn)行時(shí),通過(guò)bindService與后臺(tái)服務(wù)進(jìn)行綁定后,主界面通過(guò)使用startService對(duì)后臺(tái)服務(wù)進(jìn)行播放操控,而后臺(tái)服務(wù)通過(guò)綁定操作獲得的回調(diào)接口將播放狀態(tài)反饋回MainActivity。
(4) AppWidget和后臺(tái)服務(wù)通過(guò)發(fā)送廣播方式,進(jìn)行視頻播放操控以及播放狀態(tài)更新。
為了支持視頻后臺(tái)播放,因此后臺(tái)服務(wù) SndDisplayService類需要包含MediaPlayer和SurfaceView對(duì)象、雙屏異顯中完成副屏的顯示控制DifferentDislay類、用于接收桌面程序操作的VideoWidgetReceiver類對(duì)象、用于視頻文件變動(dòng)監(jiān)聽(tīng)完成維護(hù)視頻文件列表的VideoObserver類、用于記錄播放器狀態(tài)的相應(yīng)變量以及用于向應(yīng)用程序界面返回相應(yīng)狀態(tài)的回調(diào)接口。
后臺(tái)服務(wù)與AppWidget交互方式如圖3所示。AppWidget桌面程序通過(guò)發(fā)送廣播的方式發(fā)送相應(yīng)操作指令,如表1所示。后臺(tái)服務(wù)SndDisplayService內(nèi)部VideoWidgetReceiver廣播接收器對(duì)象的onReceive方法接收操作指令后,對(duì)MediaPlayer對(duì)象進(jìn)行相應(yīng)操作控制。因此需要服務(wù)啟動(dòng)時(shí)動(dòng)態(tài)注冊(cè)廣播接收器VideoWidgetReceiver對(duì)象,接收上述操作指令。
圖3 后臺(tái)服務(wù)與AppWidget交互方式
指令標(biāo)記op功能VIDEO_PLAY開(kāi)始/繼續(xù)播放VIDEO_PAUSE播放暫停VIDEO_STOP停止播放VIDEO_NEXT播下一部VIDEO_PREV播上一部
MediaPlayer播放器狀態(tài)發(fā)生變更后,通過(guò)發(fā)送廣播方式告知AppWidget桌面程序進(jìn)行狀態(tài)變更以及當(dāng)前播放視頻,相應(yīng)廣播動(dòng)作如表2所示。因此桌面小部件AppWidget需要靜態(tài)注冊(cè)接收上述廣播動(dòng)作,并在onReceive方法中進(jìn)行相應(yīng)顯示狀態(tài)更新。
表2 桌面小部件接收廣播ACTION
后臺(tái)服務(wù)與主程序界面交互設(shè)計(jì)如圖4所示。主程序界面MainActivity通過(guò)附帶操作指令調(diào)用startService實(shí)現(xiàn)主界面?zhèn)鬟f后臺(tái)服務(wù)到進(jìn)行播放器控制。后臺(tái)服務(wù)通過(guò)重寫onStartCommand方法,接收操作指令并操作MediaPlayer組件完成相應(yīng)處理。
圖4 后臺(tái)服務(wù)與主程序界面交互方式
主程序界面提供播放器全部操作,相應(yīng)操作指令如表3所示。
表3 主程序界面操作指令
雙屏異顯播放器播需要支持后臺(tái)播放功能,當(dāng)主程序界面轉(zhuǎn)回前臺(tái)顯示時(shí),需要獲知后臺(tái)播放器當(dāng)前的播放狀態(tài)和播放視頻,因此必需將后臺(tái)播放器的狀態(tài)信息同步到主程序界面。為了方便后臺(tái)播放服務(wù)SndDisplayService發(fā)回狀態(tài)信息,在主程序界面onResume中通過(guò)bindService對(duì)已經(jīng)啟動(dòng)的后臺(tái)服務(wù)進(jìn)行捆綁服務(wù)操作。后臺(tái)服務(wù)定義回調(diào)接口,主程序界面在服務(wù)綁定完成時(shí)實(shí)現(xiàn)回調(diào)接口,在后臺(tái)服務(wù)中調(diào)用該接口,便可實(shí)現(xiàn)發(fā)回信息給主程序界面。
后臺(tái)服務(wù)定義PlayStateCallback回調(diào)接口用于向主程序界面返回當(dāng)前播放狀態(tài)和播放視頻,PlayTimeCallback回調(diào)接口用于返回當(dāng)前播放時(shí)間,以及VideoListCallback回調(diào)接口用于對(duì)主界面顯示的視頻列表進(jìn)行更新同步。
后臺(tái)服務(wù)SndDisplayService啟動(dòng)時(shí),需要初始化MediaPlayer組件的輸出與副屏進(jìn)行綁定。首先通過(guò)DisplayManager獲取當(dāng)前顯示屏映射數(shù)組,在該映射數(shù)組中下標(biāo)序號(hào)0為主屏,序號(hào)1為副屏;然后以副屏為參數(shù)創(chuàng)建DifferentDislay類對(duì)象;最后設(shè)置媒體播放器的輸出為副屏的surfaceView控件。
程序定義EntityVideo類記錄每個(gè)視頻文件的文件名、播放、文件路徑等信息。Android系統(tǒng)為多媒體類型的文件(圖片、音頻、視頻等)建立了媒體庫(kù),從而完成多媒體數(shù)據(jù)的維護(hù)工作,并可通過(guò)ContentProvider提供給其他程序使用。后臺(tái)服務(wù)SndDisplayService需要在服務(wù)啟動(dòng)時(shí),通過(guò)getContentResolver來(lái)查詢系統(tǒng)媒體庫(kù)中外部存儲(chǔ)所有支持格式的視頻文件,從而構(gòu)建視頻文件列表。
由于播放文件列表是在后臺(tái)服務(wù)啟動(dòng)時(shí)通過(guò)getContentResolver獲取,當(dāng)播放器主界面后臺(tái)運(yùn)行時(shí)用戶可能新增或刪除了視頻媒體文件,因此需要對(duì)視頻文件列表進(jìn)行維護(hù),避免用戶點(diǎn)擊播放下一部視頻時(shí),視頻文件已經(jīng)刪除導(dǎo)致播放器異常操作情況。因此需要服務(wù)啟動(dòng)時(shí)動(dòng)態(tài)注冊(cè)廣播接收器VideoObserver監(jiān)聽(tīng)外部存儲(chǔ)中視頻文件的變動(dòng)情況。
當(dāng)外部存儲(chǔ)中出現(xiàn)新增或刪除視頻文件時(shí),廣播接收器VideoObserver將可獲知該變動(dòng),重寫其onChange方法,在該方法中重新獲取視頻文件列表。如果程序界面正在前臺(tái)運(yùn)行時(shí),通過(guò)VideoListcallback回調(diào)接口進(jìn)行界面視頻文件列表更新。
設(shè)計(jì)程序安裝到RK3288平臺(tái)(Android 5.1)上運(yùn)行,RK3288通過(guò)VGA和HDMI連接兩個(gè)顯示器,其中VGA連接主顯示屏,HDMI連接副顯示屏。系統(tǒng)開(kāi)機(jī)啟動(dòng)完成后,將自動(dòng)完成車載播放器后臺(tái)服務(wù)初始化工作,開(kāi)啟雙屏異顯模式,副屏顯示歡迎畫(huà)面,如圖5所示。
圖5 系統(tǒng)啟動(dòng)時(shí)副屏歡迎界面
初始化完成后,主屏便可以通過(guò)桌面小部件和程序主界面進(jìn)行播放控制。桌面小部件可進(jìn)行播放/暫停、上一首、下一首以及停止播放的簡(jiǎn)單控制操作以及顯示當(dāng)前正在播放的視頻名稱,如圖6所示。
(a) 未播放 (b) 正在播放圖6 桌面小部件
程序主界面提供車載播放器的全部控制功能,如圖7所示,副屏顯示當(dāng)前正在播放視頻輸出畫(huà)面如圖8所示。程序主界面以列表方式顯示外部存儲(chǔ)上所有可播放的視頻文件,供用戶進(jìn)行點(diǎn)擊播放。當(dāng)開(kāi)始播放視頻后,程序主界面顯示當(dāng)前播放影片名稱、當(dāng)前播放時(shí)間,并可通過(guò)拖動(dòng)進(jìn)度條對(duì)調(diào)整當(dāng)前播放影片的播放播放時(shí)間。
圖7 播放視頻時(shí)主屏程序界面
圖8 播放視頻時(shí)副屏
通過(guò)程序運(yùn)行結(jié)果分析表明,本設(shè)計(jì)成功實(shí)現(xiàn)了雙屏異顯模式下,車載視頻播放器的相應(yīng)功能。
本文介紹了利用Android雙屏異顯功能的車載視頻播放器的設(shè)計(jì)和實(shí)現(xiàn)。該車載播放器視頻輸出在副屏,主屏通過(guò)主程序界面或桌面小部件進(jìn)行播放控制,可低成本地滿足大客車為乘客播放視頻的需要。當(dāng)然如果要將該車載視頻播放器進(jìn)行實(shí)際商用部署,還應(yīng)該解決以下兩個(gè)問(wèn)題:(1) 由于一般Android應(yīng)用程序可強(qiáng)行停止,會(huì)導(dǎo)致車載播放器程序重啟并初始化為未播放狀態(tài),因此還需要獲得系統(tǒng)權(quán)限升級(jí)為系統(tǒng)應(yīng)用,避免異屏雙顯播放器被強(qiáng)行停止。(2) 一般Android系統(tǒng)硬件平臺(tái)僅僅包含一路音頻輸出,因此主屏其他程序使用音頻會(huì)對(duì)副屏視頻播放的音頻造成干擾。因此需要設(shè)計(jì)含兩條音頻輸出的硬件平臺(tái),方可實(shí)現(xiàn)副屏視頻播放音頻不受主屏操作的影響。