版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
緒論1.1項(xiàng)目背景隨著抖音、快手等小視頻移動(dòng)軟件的興起,手機(jī)、平板進(jìn)行各種娛樂活動(dòng)已經(jīng)成為了許多人閑暇的娛樂工具。但是,當(dāng)遇到自己喜歡的視頻和電視的時(shí)候,想和自己的親人、朋友分享時(shí),手機(jī)和平板這些小屏幕設(shè)備就顯的有點(diǎn)捉襟見肘,并且手機(jī)也不能很方便的從其他智能設(shè)備上獲取多媒體資源,使得用戶互動(dòng)可能性降低。手機(jī)投屏互動(dòng)技術(shù)就是在此種情況下誕生。手機(jī)投屏在專門的協(xié)議、同一局域網(wǎng)下,實(shí)現(xiàn)了不同智能終端之間進(jìn)行畫面顯示、音頻播放和遙控器控制的功能[1],用戶可以通過該技術(shù)實(shí)現(xiàn)手機(jī)等移動(dòng)設(shè)備獲取其他智能設(shè)備的多媒體資源,也能將手機(jī)本地多媒體資源、獲取到的其他智能設(shè)備中的多媒體資源推送到智能電視大屏幕上進(jìn)行觀看。自從Android操作系統(tǒng)在2007年發(fā)布,搭載著Android系統(tǒng)的智能設(shè)備發(fā)展飛速[2]。在最近幾年中,具有高性價(jià)比、硬件多選性、開源等優(yōu)勢的Android操作系統(tǒng)又快速進(jìn)軍了家電市場。在沒有Android操作系統(tǒng)的家電設(shè)備中,商家也為其生產(chǎn)的家電設(shè)備提供了可擴(kuò)展的接口,方便兼容Android操作系統(tǒng)。HDMI接口就是其中一個(gè)。從目前來看家電領(lǐng)域已經(jīng)被Android操作系統(tǒng)所覆蓋。正因?yàn)樵絹碓蕉嗟闹悄茉O(shè)備都搭載Android操作系統(tǒng),Android應(yīng)用程序開發(fā)也被帶動(dòng)起來了。為了實(shí)現(xiàn)生活更加便利、快捷、智能,許許多多的公司和個(gè)人在Android系統(tǒng)的基礎(chǔ)上進(jìn)行不斷的研發(fā),以便能研發(fā)出更加方便、智能的App。Android智能設(shè)備投屏功能就是本次開發(fā)的重點(diǎn)。1.2項(xiàng)目介紹在不同的多媒體終端上(如手機(jī)、PAD、TV等)利用相同的網(wǎng)絡(luò)上層協(xié)議(比如DLNA、Airplay、Miracast等)通過WIFI熱點(diǎn)網(wǎng)絡(luò)對(duì)圖片、音視頻進(jìn)行傳輸、解析、顯示和控制的技術(shù)叫多屏互動(dòng)技術(shù)。在不同設(shè)備上實(shí)現(xiàn)了資源共享。只要智能設(shè)備上安裝了相應(yīng)功能,手機(jī)、PAD或個(gè)人PC上的資源文件就可以隨時(shí)分享到電視上進(jìn)行觀看。而且,大小屏幕切換自如,滿足了人們?cè)谌粘I?、?huì)議、教學(xué)旅行、住宿類似需求。1.3投屏智能電視的幾種方法1.3.1DLNADLNA是由索尼、英特爾、微軟等發(fā)起成立的DIGITALLIVINGNETWORKALLIANCE(數(shù)字生活網(wǎng)絡(luò)聯(lián)盟)研發(fā)的,主要實(shí)現(xiàn)移動(dòng)設(shè)備、個(gè)人PC、家庭電視在內(nèi)的無線網(wǎng)絡(luò)和有限網(wǎng)絡(luò)的互通互聯(lián)[3]。1.3.2Miracast以Wi-Fi直連為基礎(chǔ)的無線顯示協(xié)議Miracast于2012年通過Wi-Fi聯(lián)盟所制定。智能設(shè)備使用此協(xié)議以無線方式實(shí)現(xiàn)視頻畫面的分享。通過Miracast協(xié)議,智能手機(jī)可在不受連接線纜長度影響的情況下將影片或照片播放在電視屏幕上。擁有類似于AirPlay的鏡像功能的Miracast是與DLNA不同的功能,該功能可實(shí)現(xiàn)在高清電視屏幕里投放智能手機(jī)屏幕中的內(nèi)容,這樣也就可以觀看電視屏幕來實(shí)現(xiàn)玩游戲的樂趣。該功能在Android4.2及以后的版本中成為了標(biāo)配(要找到此功能需要到智能手機(jī)設(shè)置或顯示菜單中去找,如:Wi-FiDisplay、Miracast、Mirroringscreen、無線顯示等)。通過無線顯示接收器可以將智能手機(jī)屏幕畫面無線傳輸?shù)娇蛷d電視或者會(huì)議室投影儀上。畫面?zhèn)鬏斞訒r(shí)150ms以下,幾乎同時(shí)。當(dāng)點(diǎn)擊此功能時(shí),智能設(shè)備沒有任何反應(yīng),因?yàn)榇隧?xiàng)功能需要配件支持。1.3.3AirPlay蘋果開發(fā)了一種通過WiFi將iPhone、iPad、iPodtouch等IOS設(shè)備上的包括但不限于圖片、音頻、視頻無線傳輸?shù)街С諥irPlay的智能設(shè)備上的技術(shù)叫AirPlay。AirPlay鏡像是AirPlay與DLNA不同指出,iPhone或iPad可以用AirPlay鏡像功能將畫面無線傳輸?shù)紸ppleTV電視上,當(dāng)iPhone或iPad顯示不同畫面的時(shí)候,AppleTV電視屏幕顯示和iPhone或iPad一樣的畫面。并且可以用iPad當(dāng)方向盤看著大屏玩游戲。另外實(shí)現(xiàn)雙屏游戲是AirPlay鏡像最強(qiáng)大的功能,讓用戶能在游戲中有更寬廣的視野,例如。當(dāng)電視里顯示游戲畫面的時(shí)候,另一個(gè)設(shè)備上顯示的是鼻塞的路線圖。1.3.4GoogleCast因?yàn)閲鴥?nèi)的手機(jī)基本都是閹割版本的。因?yàn)椴恍枰褂肎ooglePlay,所以國內(nèi)很多手機(jī)需要下載好谷歌的三件套才能使用,然后就是谷歌官方的硬件Chromecast,在國內(nèi)基本很難用,因?yàn)橐迷L問谷歌的服務(wù)器,所以需要外網(wǎng)才行[5]。1.3.5DLNA和Miracast區(qū)別DLNA和Miracast的區(qū)別是前者是基于文件的,后者是實(shí)時(shí)的。媒體文件通常由各種編碼格式,而播放器為了播放媒體文件是需要處理這些編碼格式的。為此,DLNA為了比較好的播放體驗(yàn),會(huì)顯緩存一小段時(shí)間[4]。Miracast通過實(shí)時(shí)傳輸源端的輸出將源端的操作傳輸?shù)浇邮斩?,如果源端是播放媒體文件,則源端需要先即將媒體文件進(jìn)行解碼,在編碼成H.264的格式通過Miracast將編碼后的數(shù)據(jù)無線傳輸給接收端,然后接收端在對(duì)H.264進(jìn)行解碼操作,并展示到接收端屏幕上。在WiFi通路方面,Miracast比DLNA的要求更高一些。因此本文以DLNA作為功能實(shí)現(xiàn)的架構(gòu)。2相關(guān)理論與技術(shù)DLNA是由索尼、英特爾、微軟等發(fā)起成立的DIGITALLIVINGNETWORKALLIANCE(數(shù)字生活網(wǎng)絡(luò)聯(lián)盟)研發(fā)的。主要實(shí)現(xiàn)移動(dòng)設(shè)備、個(gè)人PC、家庭電視在內(nèi)的無線網(wǎng)絡(luò)和有限網(wǎng)絡(luò)的互通互聯(lián)。在DLNA協(xié)議中,通過UPnP協(xié)議實(shí)現(xiàn)部分核心設(shè)備的發(fā)現(xiàn)和控制[6]。而Cling是一款封裝DLNA協(xié)議的設(shè)備搜索、設(shè)備連接和設(shè)備控制的開源框架庫。因此本章將會(huì)介紹DLNA協(xié)議標(biāo)準(zhǔn)和Cling開源庫實(shí)現(xiàn)投屏的技術(shù)。2.1DLNA協(xié)議標(biāo)準(zhǔn)2.1.1DLNA設(shè)備類型在不同應(yīng)用領(lǐng)域中,可以將DLNA所支持的設(shè)備分成三大類,分別是移動(dòng)網(wǎng)絡(luò)設(shè)備,家庭網(wǎng)絡(luò)設(shè)備和家庭互操作設(shè)備[7]。家庭網(wǎng)絡(luò)設(shè)備包括5個(gè)類型,分別是數(shù)字媒體服務(wù)器、數(shù)字媒體播放設(shè)備、數(shù)字媒體渲染設(shè)備、數(shù)字媒體控制器和數(shù)字媒體打印機(jī)[7]。移動(dòng)手持設(shè)備也包括5個(gè)類型。分別是移動(dòng)數(shù)字媒體服務(wù)器、移動(dòng)數(shù)字媒體上傳設(shè)備、移動(dòng)數(shù)字媒體播放器、移動(dòng)數(shù)字媒體下載設(shè)備以及移動(dòng)數(shù)字媒體控制器。家庭互操作設(shè)備包括兩種類型,分別是移動(dòng)網(wǎng)絡(luò)連接功能設(shè)備和移動(dòng)互操作單元。2.1.2DLNA分級(jí)結(jié)構(gòu)下圖是將DLNA各個(gè)層次標(biāo)明了標(biāo)準(zhǔn)和包括各項(xiàng)內(nèi)容進(jìn)行闡述的分級(jí)結(jié)構(gòu)圖,如圖2-1。圖2-1DLNA分級(jí)結(jié)構(gòu)圖網(wǎng)絡(luò)連接層網(wǎng)絡(luò)連接層包括無線網(wǎng)絡(luò)、有線網(wǎng)絡(luò)和藍(lán)牙等,它定義了所接入網(wǎng)絡(luò)的類型和協(xié)議,是整個(gè)結(jié)構(gòu)圖的最底層。DLNA支持網(wǎng)絡(luò)類型為802.3i/u的有線網(wǎng)絡(luò),網(wǎng)絡(luò)類型為802.11a/b/g的無線網(wǎng)絡(luò),以及藍(lán)牙技術(shù)。網(wǎng)絡(luò)協(xié)議DLNA是在IP技術(shù)的基礎(chǔ)上實(shí)現(xiàn)的,且當(dāng)前已被廣泛使用的網(wǎng)絡(luò)技術(shù)基礎(chǔ)協(xié)議是IPv4協(xié)議,因而DLNA必須支持IPv4。設(shè)備的發(fā)現(xiàn)、控制及媒體管理DLNA框架的核心模塊是發(fā)現(xiàn)設(shè)備、控制設(shè)備、媒體管理,而實(shí)現(xiàn)這一核心功能主要靠UPnPDA和UPnPAC這兩大框架。UPnPDA框架中包括簡單服務(wù)發(fā)現(xiàn)協(xié)議SSDP和簡單對(duì)象訪問協(xié)議SOAP。而SSDP是為局域網(wǎng)中感興趣的設(shè)備提供服務(wù),SOAP主要為設(shè)備發(fā)送控制消息。對(duì)音頻和視頻的管理控制主要靠UPnPAV框架,并明確了各個(gè)支持DLNA的設(shè)備在多媒體傳送過程中所承擔(dān)的任務(wù)。媒體傳輸HTTP協(xié)議是帶有DLNA功能設(shè)備必須支持使用的傳輸協(xié)議,而RTP協(xié)議是可以通過設(shè)備自己選擇是否支持。媒體格式確定了DLNA支持多媒體格式包括圖片、音頻、視頻和其他可選支持的格式。必須支持的格式是圖片、音頻和視頻格式。而支持圖片的格式包括JPEG,支持音頻的格式包括AC-3、AAC、MP3以及WMA等。支持視頻的格式包括MPRG-1、MPEG-4和H.264等格式。當(dāng)前網(wǎng)絡(luò)傳輸技術(shù)和多媒體壓縮技術(shù)發(fā)展越來越快,今后DLNA產(chǎn)品支持的多媒體格式會(huì)越來越多。2.2UPnP協(xié)議棧工作原理2.2.1UPnP網(wǎng)絡(luò)簡介UPnP協(xié)議主要實(shí)現(xiàn)設(shè)備與設(shè)備之間網(wǎng)絡(luò)互聯(lián)的功能,是由“通用即插即用論壇”(UPnPForum)推廣的一套網(wǎng)絡(luò)協(xié)議。由設(shè)備尋址、設(shè)備發(fā)現(xiàn)、設(shè)備描述、設(shè)備控制、事件通知以及基于Html描述這幾部分構(gòu)成的UPnP協(xié)議是設(shè)備與設(shè)備之間,設(shè)備與控制點(diǎn),控制點(diǎn)與控制點(diǎn)之間的通信的協(xié)議。2.2.2UPnP協(xié)議棧組成由多協(xié)議、多層次的設(shè)備模型構(gòu)成的協(xié)議棧UPnP協(xié)議為了實(shí)現(xiàn)對(duì)局域網(wǎng)中的設(shè)備發(fā)現(xiàn)和控制,特將框架分為尋址、發(fā)現(xiàn)、描述、控制、事件和展示這六個(gè)步驟,且這當(dāng)中每一步驟都定義屬于自己的通訊協(xié)議[9]。為了實(shí)現(xiàn)能在不同開發(fā)語言、不同的操作系統(tǒng)編寫和運(yùn)行UPnP協(xié)議棧支持的應(yīng)用程序,UPnP里的每個(gè)協(xié)議都是在成熟開放的標(biāo)準(zhǔn)協(xié)議(如IP、UDP以及TCP協(xié)議)之上建立的。下圖為UPnP協(xié)議棧簡略描述。圖2-2UPnP協(xié)議棧組成(1)IP主要用到網(wǎng)絡(luò)層數(shù)據(jù)的傳輸,IP層用于數(shù)據(jù)的發(fā)送和接收。兩個(gè)設(shè)備互聯(lián)其實(shí)就是網(wǎng)絡(luò)互聯(lián),所以需要網(wǎng)絡(luò)層協(xié)議。(2)TCP-UDP這里包含了UDP和TCP兩塊協(xié)議。如圖2-3所示:圖2-3UDP和TCP兩塊協(xié)議UDP協(xié)議與IP協(xié)議組合成:UDP/IP協(xié)議。而HHTPMU和HTPU這兩個(gè)協(xié)議是基于UDP/IP協(xié)議之上的。TCP協(xié)議與IP協(xié)議組合成:TCP/IP協(xié)議。.Http則是基于TCP/IP協(xié)議之上。使用UDP,可以通過多點(diǎn)傳送(Multicast)向LAN上所支持UPnP的設(shè)備發(fā)送新設(shè)備接入的通知,這里流媒體也會(huì)使用UDP來傳輸,因?yàn)樗俣瓤?。所有的UPnP消息都是由HTTP協(xié)議基礎(chǔ)上定義的HTTPMU協(xié)議和HTTPU協(xié)議來進(jìn)行封裝,并且用UDP來實(shí)現(xiàn)組播通訊。而UDP協(xié)議則是通過不斷發(fā)送信息而不需要等待回復(fù),因此很適用于直播類傳輸,但缺點(diǎn)是容易丟幀。因此使用UDP來通訊是為了能很好的播放高刷新率的媒體文件。(3)設(shè)備發(fā)現(xiàn)|設(shè)備控制|設(shè)備事件協(xié)議圖2-4設(shè)備發(fā)現(xiàn)|設(shè)備控制|設(shè)備事件協(xié)議1)SSDP協(xié)議:簡單服務(wù)發(fā)現(xiàn)協(xié)議在UPnP協(xié)議中,當(dāng)用戶連接到無線WIFI時(shí),控制端能通過SSDP協(xié)議搜索到局域網(wǎng)絡(luò)中感興趣并且支持UPnP協(xié)議的設(shè)備并能為支持UPnP協(xié)議的設(shè)備提供服務(wù)。SSDP協(xié)議的主要功能時(shí)宣告設(shè)備存在和搜索服務(wù)和支持DLNA協(xié)議的設(shè)備,通過UDP協(xié)議多播或單播來實(shí)現(xiàn)了控制設(shè)備自動(dòng)搜索感興趣的支持DLNA協(xié)議的設(shè)備或服務(wù)、支持DLNA協(xié)議的設(shè)備里廣播上下線消息、控制設(shè)備向支持DLNA協(xié)議的設(shè)備發(fā)送控制指令等功能。SOAP協(xié)議:簡單對(duì)象訪問協(xié)議(SimpleObjectAccessProtocol)。SOPA協(xié)議規(guī)定怎樣使用XML和HTTP協(xié)議來執(zhí)行包括控制設(shè)備發(fā)送命令消息給支持DLNA設(shè)備、支持DLNA設(shè)備收到消息后發(fā)送響應(yīng)消息給控制設(shè)備的遠(yuǎn)程服務(wù)請(qǐng)求。在局域網(wǎng)絡(luò)中,控制設(shè)備需要向支持DLNA設(shè)備發(fā)送包含需要調(diào)用的參數(shù)和函數(shù)的服務(wù)SOAP請(qǐng)求來獲取描述文檔。支持DLNA設(shè)備收到該服務(wù)SOAP請(qǐng)求后,支持DLNA設(shè)備會(huì)將包括設(shè)備的狀態(tài)、返回的值和執(zhí)行錯(cuò)誤的信息等一些結(jié)果或者執(zhí)行失敗信息封裝一個(gè)SOAP響應(yīng)中并傳輸給控制設(shè)備。3)設(shè)備事件GENA協(xié)議:該協(xié)議主要是為控制設(shè)備獲取監(jiān)聽設(shè)備在某個(gè)服務(wù)狀態(tài)變化時(shí)傳送訂閱信息或接收返回的信息做一些規(guī)定。4)HTTPU和HTTPMU協(xié)議由UDP傳輸協(xié)議實(shí)現(xiàn)用于多播通信的HTTPMU協(xié)議和以UDP傳輸協(xié)議實(shí)現(xiàn)的HTTPU協(xié)議都是HTTP協(xié)議的衍生通信傳輸協(xié)議,因此,該協(xié)議適合由不同語言不同操作系統(tǒng)使用的協(xié)議。方便各種設(shè)備適配支持DLNA協(xié)議的設(shè)備。2.2.3UPnP工作流程下圖是描述UPnPDA對(duì)設(shè)備的發(fā)現(xiàn)和控制大概流程,從下往上依次為尋址、發(fā)現(xiàn)、描述、控制、事件、展示。如下圖所示。圖2-5UPnP工作流程(1)設(shè)備尋址首先控制設(shè)備會(huì)其搜索DHCP服務(wù)器獲取自己的IP地址,如果沒有獲取到IP地址,則使用LLA協(xié)議來獲取IP地址。為了能更好的執(zhí)行后續(xù),尋址是必須的一步。當(dāng)前Android操作系統(tǒng)會(huì)自動(dòng)去獲取IP地址,而我們現(xiàn)在所基于的操作系統(tǒng)正式Android操作系統(tǒng),因此,此開發(fā)不需要考慮設(shè)備尋址。(2)設(shè)備發(fā)現(xiàn)當(dāng)控制設(shè)備獲取到自己的IP地址后,就可以在局域網(wǎng)種通過簡單服務(wù)發(fā)現(xiàn)協(xié)議SSDP來尋找感興趣并且支持了DLNA協(xié)議的設(shè)備及其上的服務(wù)。(3)設(shè)備描述控制設(shè)備發(fā)現(xiàn)支持DLNA設(shè)備后,能從種獲取到支持DLNA設(shè)備服務(wù)類型、支持DLNA設(shè)備唯一標(biāo)識(shí)和支持DLNA設(shè)備的描述文檔的URL,并從支持DLNA設(shè)備描述文檔的URL種獲取更多支持DLNA設(shè)備的詳細(xì)描述來實(shí)現(xiàn)控制支持DLNA設(shè)備之間交互。(4)設(shè)備控制基于SOAP協(xié)議實(shí)現(xiàn)控制設(shè)備通過網(wǎng)絡(luò)請(qǐng)求來調(diào)用支持UPnP的設(shè)備上所提供的服務(wù),獲取到該設(shè)備的描述文檔,解析支持UPnP設(shè)備上的描述文檔來獲取某個(gè)服務(wù)的控制URL、所需要函數(shù)名稱、參數(shù)名稱以及參數(shù)要求,然后控制設(shè)備向控制通過向URL傳入函數(shù)名稱、參數(shù)名稱以及對(duì)應(yīng)參數(shù)數(shù)據(jù)發(fā)出調(diào)用請(qǐng)求,支持UPnP設(shè)備收到調(diào)用請(qǐng)求后通過一系列操作后返回響應(yīng)的結(jié)果或者錯(cuò)誤信息,控制設(shè)備收到返回的響應(yīng)數(shù)據(jù)完成響應(yīng)操作來達(dá)到控制支持UPnP設(shè)備所提供能的功能。(5)設(shè)備事件設(shè)備事件就是控制設(shè)備通過訂閱支持UPnP設(shè)備的事件,該事件就是讓支持UPnP設(shè)備發(fā)送采用XML格式且遵守通用事件通知協(xié)議的規(guī)定的一個(gè)或多個(gè)狀態(tài)變化值的事件消息來達(dá)到更新運(yùn)行時(shí)狀態(tài)信息的值,在訂閱處能及時(shí)獲取到支持UPnP設(shè)備在運(yùn)行時(shí)的狀態(tài)信息值。(6)設(shè)備展現(xiàn)當(dāng)支持UPnP設(shè)備種帶有顯示URL的描述信息時(shí),控制設(shè)備可以通過該URL鏈接來實(shí)現(xiàn)控制設(shè)備媒體文件展示在大屏顯示器上[8]。2.3Cling框架Cling類庫是由Java實(shí)現(xiàn)的DLNA/UPnP協(xié)議棧?;贒LNA/UPnP可以開發(fā)出類似多屏互動(dòng)、資源共享、遠(yuǎn)程控制等功能的應(yīng)用,通過Android應(yīng)用管理一個(gè)或多個(gè)設(shè)備,將音頻、視頻、圖片推送到指定設(shè)備顯示。Cling作為UPnP協(xié)議棧,其主旨即是在設(shè)備的發(fā)現(xiàn),控制等過程中對(duì)不同的協(xié)議及內(nèi)容進(jìn)行處理。UPnP協(xié)議棧由多個(gè)層組成,Cling只關(guān)心底層的TCP/IP協(xié)議以及包含SSDP(設(shè)備發(fā)現(xiàn)),SOAP(設(shè)備控制),GENA(設(shè)備事件)協(xié)議的層。3軟件開發(fā)所需條件3.1開發(fā)環(huán)境及研究基礎(chǔ)本軟件是運(yùn)行在Android系統(tǒng)上,需要使用Android開發(fā)語言來實(shí)現(xiàn)功能。且在Windows操作系統(tǒng)上使用Androidstudio開發(fā)IDE。在開發(fā)本軟件之前,需要有以下研究基礎(chǔ)。(1)掌握Android開發(fā)語言、多媒體開發(fā)技術(shù)以及AndroidstudioIDE使用流程,熟悉Android系統(tǒng)。(2)了解HTTP協(xié)議、TCP/IP協(xié)議和UDP協(xié)議,DLNA協(xié)議標(biāo)準(zhǔn)和UPnP協(xié)議(3)了解Cling第三方庫。(4)熟練使用Android中各種第三方庫和AIDL的知識(shí),能熟練使用Service服務(wù)相關(guān)的功能以及Service與Activity相互通信的技術(shù)。3.2軟件和硬件基礎(chǔ)App運(yùn)行環(huán)境如表3-1所示。3.3編程前配置3.3.1網(wǎng)絡(luò)權(quán)限要實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求以及IP地址獲取,則需要使用到網(wǎng)絡(luò)相關(guān)權(quán)限、WIFI相關(guān)權(quán)限程序喚醒權(quán)限等相關(guān)權(quán)限。如下為當(dāng)前軟件開發(fā)需要的權(quán)限。因下列權(quán)限不是運(yùn)行時(shí)權(quán)限,不需要在使用時(shí)再去獲取,可以直接在AndroidManifest中聲明。無需其他操作。<uses-permissionandroid:name=”android.permission.ACCESS_WIFI_STATE”/><uses-permissionandroid:name=”android.permission.ACCESS_NETWORK_STATE”/><uses-permissionandroid:name=”android.permission.INTERNET”/><uses-permissionandroid:name=”android.permission.CHANGE_WIFI_MULTICAST_STATE”/><uses-permissionandroid:name=”android.permission.WAKE_LOCK”/>4搜索設(shè)備4.1設(shè)備搜索流程圖代碼實(shí)現(xiàn)設(shè)備搜索流程圖。該軟件是在Cling第三方庫的基礎(chǔ)上實(shí)現(xiàn)的,因此,我們只需要調(diào)用Cling開放出來的方法來實(shí)現(xiàn)相應(yīng)的操作。先創(chuàng)建ClingManager對(duì)象,通過ClingManager對(duì)象來開啟搜索設(shè)備功能SearchDevices。并實(shí)現(xiàn)BrowseRegisterListener監(jiān)聽器,重寫其結(jié)果返回方法。當(dāng)結(jié)果返回方法被調(diào)用,則能從其中獲取到搜索到設(shè)備的信息以及是否搜索到了設(shè)備。然后可以在界面上進(jìn)行展示。大概流程如下圖。4.2UML圖4.3功能實(shí)現(xiàn)本項(xiàng)目是在Cling庫的支持下完成功能實(shí)現(xiàn)的。因此,上圖中ClingUPnPService類繼承Cling庫下的AndroidUpnpServiceImpl類并實(shí)現(xiàn)里面的方法。ClingManager類中實(shí)現(xiàn)了搜索設(shè)備,獲取控制點(diǎn),設(shè)備顯示和刪除等功能。在MainActivity的中創(chuàng)建ServiceConnection對(duì)象,并實(shí)現(xiàn)ServiceConnection下的onServiceConnected和onServiceDisconnected兩個(gè)方法。onServiceConnected方法下實(shí)行ClingUPnPService的對(duì)象創(chuàng)建,BrowseRegistryListener監(jiān)聽器對(duì)象創(chuàng)建,ClingManager.getInstance()來創(chuàng)建ClingManager類的對(duì)象,通過ClingManager對(duì)象設(shè)置UpnPService服務(wù)、DeviceManager和綁定設(shè)備搜索監(jiān)聽器,最后開啟設(shè)備搜索功能。onServiceDisconnected當(dāng)服務(wù)斷開時(shí),需要重新設(shè)置UPnPService的服務(wù)。在MainActivity類中的onCreate方法里面,需要?jiǎng)?chuàng)建ClingUPnPService服務(wù)的意圖,并綁定當(dāng)前服務(wù)。綁定服務(wù)后,需要在onDestroy中取消綁定。通過BrowseRegistryListener的對(duì)象調(diào)用setOnDeviceListChangeListener實(shí)現(xiàn)DeviceListChangeListener接口下面的方法onDeviceAdded和onDeviceRemoved兩個(gè)方法。onDeviceAdded里面實(shí)現(xiàn)將設(shè)獲取到的設(shè)備添加到設(shè)備的列表中。onDeviceRemoved實(shí)現(xiàn)當(dāng)設(shè)備斷開服務(wù)后刪除列表中的設(shè)備。privateBrowseRegistryListenermBrowseRegistryListener=newBrowseRegistryListener();privateServiceConnectionmUpnpServiceConnection=newServiceConnection(){@OverridepublicvoidonServiceConnected(ComponentNameclassName,IBinderservice){ClingUpnpService.LocalBinderbinder=(ClingUpnpService.LocalBinder)service;ClingUpnpServicebeyondUpnpService=binder.getService();ClingManagerclingUpnpServiceManager=ClingManager.getInstance();clingUpnpServiceManager.setUpnpService(beyondUpnpService);clingUpnpServiceManager.setDeviceManager(newDeviceManager());clingUpnpServiceManager.getRegistry().addListener(mBrowseRegistryListener);clingUpnpServiceManager.searchDevices();}@OverridepublicvoidonServiceDisconnected(ComponentNameclassName){ClingManager.getInstance().setUpnpService(null);}};MainActivity類中onCreate方法里面綁定服務(wù)IntentupnpServiceIntent=newIntent(MainActivity.this,ClingUpnpService.class);bindService(upnpServiceIntent,mUpnpServiceConnection,Context.BIND_AUTO_CREATE);mBrowseRegistryListener綁定設(shè)備搜索監(jiān)聽回調(diào),及時(shí)添加設(shè)備到設(shè)備列表中。mBrowseRegistryListener.setOnDeviceListChangedListener(newDeviceListChangedListener(){@OverridepublicvoidonDeviceAdded(finalIDevicedevice){runOnUiThread(newRunnable(){publicvoidrun(){mDevicesAdapter.add((ClingDevice)device);}});}@OverridepublicvoidonDeviceRemoved(finalIDevicedevice){runOnUiThread(newRunnable(){publicvoidrun(){mDevicesAdapter.remove((ClingDevice)device);}});}});5設(shè)備控制5.1控制流程圖5.2設(shè)備控制UML圖5.3設(shè)備控制代碼實(shí)現(xiàn)5.3.1注冊(cè)TV狀態(tài)廣播接收創(chuàng)建一個(gè)TransportStateBroadcastReceiver類并繼承BroadcastReceiver,用來接受狀態(tài)改變信息。通過Handler來切換線程實(shí)現(xiàn)控制和消息提示功能。mTransportStateBroadcastReceiver=newTransportStateBroadcastReceiver();IntentFilterfilter=newIntentFilter();filter.addAction(Intents.ACTION_PLAYING);filter.addAction(Intents.ACTION_PAUSED_PLAYBACK);filter.addAction(Intents.ACTION_STOPPED);filter.addAction(Intents.ACTION_TRANSITIONING);registerReceiver(mTransportStateBroadcastReceiver,filter);privateclassTransportStateBroadcastReceiverextendsBroadcastReceiver{@OverridepublicvoidonReceive(Contextcontext,Intentintent){Stringaction=intent.getAction();if(Intents.ACTION_PLAYING.equals(action)){mHandler.sendEmptyMessage(PLAY_ACTION);}elseif(Intents.ACTION_PAUSED_PLAYBACK.equals(action)){mHandler.sendEmptyMessage(PAUSE_ACTION);}elseif(Intents.ACTION_STOPPED.equals(action)){mHandler.sendEmptyMessage(STOP_ACTION);}elseif(Intents.ACTION_TRANSITIONING.equals(action)){mHandler.sendEmptyMessage(TRANSITIONING_ACTION);}}}privatefinalclassInnerHandlerextendsHandler{@OverridepublicvoidhandleMessage(Messagemsg){super.handleMessage(msg);switch(msg.what){casePLAY_ACTION:Toast.makeText(mContext,"正在投放",Toast.LENGTH_SHORT).show();mClingPlayControl.setCurrentState(DLANPlayState.PLAY);break;casePAUSE_ACTION:mClingPlayControl.setCurrentState(DLANPlayState.PAUSE);break;caseSTOP_ACTION:mClingPlayControl.setCurrentState(DLANPlayState.STOP);break;caseTRANSITIONING_ACTION:Toast.makeText(mContext,"正在連接",Toast.LENGTH_SHORT).show();break;caseERROR_ACTION:Toast.makeText(mContext,"投放失敗",Toast.LENGTH_SHORT).show();break;}}}5.3.2獲取控制點(diǎn)控制點(diǎn)包含在UpnPService里面,Cling對(duì)android做了一層封裝AndroidUpnpServiceImpl,這個(gè)類里面就有UpnpService,我們可以通過獲取UpnpService之后獲取到控制點(diǎn)。我們的Activity可以綁定AndroidUpnpServiceImpl這個(gè)Service繼承類,當(dāng)onServiceConnected之后,我們就可以通過upnpService.getControlPoint()獲取到控制點(diǎn)。我們通過綁定Service,然后將Service綁定到ClingUpnpServiceManager中,ClingUpnpServiceManager是一個(gè)單例對(duì)象,因?yàn)镾ervice里面有獲取控制點(diǎn)等方法,綁定到ClingUpnpServiceManager之后,我們可以直接通過ClingUpnpServiceManager來獲取控制點(diǎn)等。同時(shí)我們?cè)贑lingPlayControl中封裝了控制設(shè)備的各種方法(例如:播放、暫停、音量控制等)。創(chuàng)建一個(gè)AVTransportSubscriptionCallback的類,它繼承SubscriptionCallback,SubscriptionCallback是Cling做的事件回調(diào)。用于接收tv端的通知信息。在eventReceived方法中獲取TV端的音量、當(dāng)前狀態(tài)。通過eventReceived方法里的參數(shù)GENASubscription的對(duì)象getGurrentValues()獲取Map對(duì)象,判斷Map對(duì)象的里面的鍵是否包含“LastChange”字段。如果包含,則獲取該鍵里面的value。5.3.3設(shè)備控制代碼將通過鍵(“LastChange”)獲取到的值,new的AVTransportLastChangeParser對(duì)象,傳入new一個(gè)LastChange生成一個(gè)LastChange對(duì)象lastChange。lastChange.getEventedValue獲取AVTransportVariable.TransportState對(duì)象transportState,transportState.getValue()獲取TransportState對(duì)象state。if(state==TransportState.PLAYING){Intentintent=newIntent(Intents.ACTION_PLAYING);mContext.sendBroadcast(intent);return;}elseif(state==TransportState.PAUSED_PLAYBACK){Intentintent=newIntent(Intents.ACTION_PAUSED_PLAYBACK);mContext.sendBroadcast(intent);return;}elseif(state==TransportState.STOPPED){Intentintent=newIntent(Intents.ACTION_STOPPED);mContext.sendBroadcast(intent);return;}elseif(state==TransportState.TRANSITIONING){Intentintent=newIntent(Intents.ACTION_TRANSITIONING);mContext.sendBroadcast(intent);return;}(1)播放視頻通過ClingUpnpService對(duì)象upnpService獲取到ControlPoint對(duì)象controlPointImpl。publicvoidplay(finalControlCallbackcallback){finalServiceavtService=ClingUtils.findServiceFromSelectedDevice(ClingManager.AV_TRANSPORT_SERVICE);if(Utils.isNull(avtService)){return;}finalControlPointcontrolPointImpl=ClingUtils.getControlPoint();if(Utils.isNull(controlPointImpl)){return;}controlPointImpl.execute(newPlay(avtService){@Overridepublicvoidsuccess(ActionInvocationinvocation){super.success(invocation);if(Utils.isNotNull(callback)){callback.success(newClingResponse(invocation));}}@Overridepublicvoidfailure(ActionInvocationinvocation,UpnpResponseoperation,StringdefaultMsg){if(Utils.isNotNull(callback)){callback.fail(newClingResponse(invocation,operation,defaultMsg));}}});}當(dāng)播放成功,調(diào)用success方法,播放失敗調(diào)用failure對(duì)象。在相應(yīng)方法里面做了處理。(2)暫停播放publicvoidpause(finalControlCallbackcallback){finalServiceavtService=ClingUtils.findServiceFromSelectedDevice(ClingManager.AV_TRANSPORT_SERVICE);if(Utils.isNull(avtService)){return;}finalControlPointcontrolPointImpl=ClingUtils.getControlPoint();if(Utils.isNull(controlPointImpl)){return;}controlPointImpl.execute(newPause(avtService){@Overridepublicvoidsuccess(ActionInvocationinvocation){super.success(invocation);if(Utils.isNotNull(callback)){callback.success(newClingResponse(invocation));}}@Overridepublicvoidfailure(ActionInvocationinvocation,UpnpResponseoperation,StringdefaultMsg){if(Utils.isNotNull(callback)){callback.fail(newClingResponse(invocation,operation,defaultMsg));}}});}(3)控制播放進(jìn)度publicvoidseek(intpos,finalControlCallbackcallback){finalServiceavtService=ClingUtils.findServiceFromSelectedDevice(ClingManager.AV_TRANSPORT_SERVICE);if(Utils.isNull(avtService)){return;}finalControlPointcontrolPointImpl=ClingUtils.getControlPoint();if(Utils.isNull(controlPointImpl)){return;}Stringtime=Utils.getStringTime(pos);controlPointImpl.execute(newSeek(avtService,time){@Overridepublicvoidsuccess(ActionInvocationinvocation){super.success(invocation);if(Utils.isNotNull(callback)){callback.success(newClingResponse(invocation));}}@Overridepublicvoidfailure(ActionInvocationinvocation,UpnpResponseoperation,StringdefaultMsg){if(Utils.isNotNull(callback)){callback.fail(newClingResponse(invocation,operation,defaultMsg));}}});}(4)控制音量大小publicvoidsetVolume(intpos,@NullablefinalControlCallbackcallback){finalServicercService=ClingUtils.findServiceFromSelectedDevice(ClingManager.RENDERING_CONTROL_SERVICE);if(Utils.isNull(rcService)){return;}finalControlPointcontrolPointImpl=ClingUtils.getControlPoint();if(Utils.isNull(controlPointImpl)){return;}longcurrentTimeMillis=System.currentTimeMillis();if(currentTimeMillis>mVolumeLastTime+RECEIVE_DELAY){controlPointImpl.execute(newSetVolume(rcService,pos){@Overridepublicvoidsuccess(ActionInvocationinvocation){if(Utils.isNotNull(callback)){callback.success(newClingResponse(invocation));}}@Overridepublicvoidfailure(ActionInvocationinvocation,UpnpResponseoperation,StringdefaultMsg){if(Utils.isNotNull(callback)){callback.fail(newClingResponse(invocation,operation,defaultMsg));}}});}mVolumeLastTime=currentTimeMillis;}(5)音量開關(guān)publicvoidsetMute(booleandesired
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024招標(biāo)項(xiàng)目廉政承諾書與投標(biāo)保證金監(jiān)管實(shí)施協(xié)議3篇
- 專業(yè)化焊接工程服務(wù)2024協(xié)議范本版B版
- 2024年配電網(wǎng)擴(kuò)建及優(yōu)化改造合同
- 16 表里的生物(說課稿)-2024-2025學(xué)年統(tǒng)編版語文六年級(jí)下冊(cè)
- 2024淘寶店鋪全息效果裝修模板定制與運(yùn)營合同3篇
- 無人機(jī)應(yīng)用技術(shù)培訓(xùn)協(xié)議
- 3 的倍數(shù)的特征(說課稿)-2024-2025學(xué)年五年級(jí)上冊(cè)數(shù)學(xué)北師大版
- 股份代持協(xié)議書完整范本
- 3《別了“不列顛尼亞”》、《縣委書記的榜樣-焦裕祿》聯(lián)讀說課稿 2024-2025學(xué)年統(tǒng)編版高中語文選擇性必修上冊(cè)
- 10 我們愛和平2023-2024學(xué)年六年級(jí)下冊(cè)道德與法治同步說課稿(統(tǒng)編版)
- 2024年醫(yī)師定期考核臨床類考試題庫及答案(共500題)
- 車間修繕合同模板
- 商會(huì)年會(huì)策劃方案范例(3篇)
- SQE年終總結(jié)報(bào)告
- 【高考語文】2024年全國高考新課標(biāo)I卷-語文試題評(píng)講
- 中心食堂(蔬菜類、豆制品、畜肉、禽肉類、水產(chǎn)類) 投標(biāo)方案(技術(shù)方案)
- 《化學(xué)實(shí)驗(yàn)室安全》課程教學(xué)大綱
- 2024年人教版初二地理上冊(cè)期末考試卷(附答案)
- 2024文旅景區(qū)秋季稻田豐收節(jié)稻花香里 說豐年主題活動(dòng)策劃方案
- 高低壓供配電設(shè)備檢查和檢修保養(yǎng)合同3篇
- 2023-2024學(xué)年福建省廈門市八年級(jí)(上)期末物理試卷
評(píng)論
0/150
提交評(píng)論