張宏寬,舒信陽(yáng),胡權(quán),樓勇亮,周伯濤
(數(shù)源科技股份有限公司,浙江 杭州 310012)
隨著公交智能化的發(fā)展,信息屏在公共出行中得到廣泛應(yīng)用,它可以實(shí)現(xiàn)車(chē)輛行駛路線顯示與站點(diǎn)動(dòng)態(tài)提示、公共文明建設(shè)信息的精準(zhǔn)投放以及突發(fā)事件的提示警告,為乘客提供出行引導(dǎo),也提升了城市精神文明的建設(shè)。
目前行業(yè)中常見(jiàn)的公交信息屏,顯示風(fēng)格比較單一,對(duì)客戶(hù)容易造成視覺(jué)審美疲勞,有時(shí)候也會(huì)出現(xiàn)界面內(nèi)容與顯示風(fēng)格不搭配的情況,因此客戶(hù)會(huì)經(jīng)常要求設(shè)備廠家對(duì)顯示風(fēng)格進(jìn)行更換,特別是產(chǎn)品在裝車(chē)后,售后升級(jí)維護(hù)的工作量很大,造成很多人力和財(cái)力的浪費(fèi)。也有廠商為客戶(hù)提供了應(yīng)用的多種主題供自主選擇,但是都沒(méi)有真正從底層去做這樣一整套的整體風(fēng)格自動(dòng)切換,因而整體風(fēng)格上的協(xié)調(diào)性和審美感也會(huì)大打折扣。本文給出了一種基于Android的系統(tǒng)風(fēng)格深度定制方法,可以根據(jù)時(shí)令或其他觸發(fā)條件自動(dòng)去更新系統(tǒng)的整體風(fēng)格,也可以由客戶(hù)根據(jù)需求自主選擇風(fēng)格,對(duì)整個(gè)啟動(dòng)過(guò)程做風(fēng)格切換。
風(fēng)格定制的系統(tǒng)框架如圖1所示,在系統(tǒng)應(yīng)用中設(shè)置定制化的自動(dòng)觸發(fā)條件,如監(jiān)聽(tīng)到今天是春節(jié),系統(tǒng)可以自動(dòng)選取春節(jié)的喜慶風(fēng)格,應(yīng)用Apk的喜慶風(fēng)格隨即變化[1-2]。開(kāi)機(jī)過(guò)程中三個(gè)階段的顯示動(dòng)畫(huà)會(huì)依次更新。這些自動(dòng)觸發(fā)條件可以是季節(jié)、節(jié)日,不同的觸發(fā)條件對(duì)應(yīng)不同的整體風(fēng)格。也支持手動(dòng)定制風(fēng)格,比如要播報(bào)突發(fā)事件或是極端天氣預(yù)警,在應(yīng)用Apk的設(shè)置菜單中,選定相應(yīng)風(fēng)格,開(kāi)機(jī)過(guò)程會(huì)自動(dòng)更新[3-4]。
圖1 風(fēng)格定制示意圖
自動(dòng)定制和手動(dòng)定制都是定制過(guò)程,自動(dòng)定制是根據(jù)提前預(yù)設(shè)的觸發(fā)條件自動(dòng)選擇風(fēng)格,手動(dòng)定制是根據(jù)喜好或特定信息選擇風(fēng)格,定制過(guò)程是一致的[5-6]。Android系統(tǒng)開(kāi)始過(guò)程中包含三個(gè)階段的顯示動(dòng)畫(huà),即Uboot Logo,Kernel Logo,Bootanimation,從底層開(kāi)始的定制過(guò)程,主要是開(kāi)機(jī)三個(gè)階段的開(kāi)機(jī)畫(huà)面及動(dòng)畫(huà)風(fēng)格的自動(dòng)切換,具體包括Uboot層狀態(tài)數(shù)據(jù)的存??;Kernel內(nèi)核層、HAL&Framework系統(tǒng)層文件系統(tǒng)的讀寫(xiě);系統(tǒng)及應(yīng)用接口的風(fēng)格切換的配置;消息從底層到上層和由上層到底層的傳遞;基于腳本自動(dòng)制作的圖片和動(dòng)畫(huà)風(fēng)格資源等。
不管是自動(dòng)定制還是手動(dòng)定制,首先是風(fēng)格的選取,系統(tǒng)獲取風(fēng)格設(shè)置消息,通知底層要切換到哪種風(fēng)格;當(dāng)?shù)讓又懒司唧w風(fēng)格后,系統(tǒng)會(huì)把這個(gè)消息傳遞給上一層,完成相應(yīng)風(fēng)格的切換。Android系統(tǒng)風(fēng)格切換過(guò)程如圖2所示,分為兩條主線,一是虛線所示[自上而下]的傳輸,二是粗線所示[自下而上]的更新[7]。
圖2 風(fēng)格定制軟件流程圖
切換狀態(tài)的傳輸路徑:系統(tǒng)與應(yīng)用層>HAL&Framework層>Kernel層>Uboot層
如圖2虛線部分所示,假定從當(dāng)前[風(fēng)格2]要切換到[風(fēng)格1],需要把[風(fēng)格1]的狀態(tài)信息傳到底層的Uboot層,因?yàn)橄到y(tǒng)開(kāi)機(jī)的圖片及動(dòng)畫(huà)是在開(kāi)機(jī)過(guò)程中完成的,在Uboot層會(huì)更新第一張開(kāi)機(jī)Logo;在HAL&Framework 層向下連接驅(qū)動(dòng)層(kernel driver),向上給JNI或HAL提供接口(Android Native),通過(guò)文件系統(tǒng)傳遞消息;在Kernel層>Uboot層,Kernel層通過(guò)IOCtrl驅(qū)動(dòng)接口獲取上一層切換[風(fēng)格1]消息值,用RTC寄存器賦值,把切換的消息保存起來(lái),傳遞給Uboot層。
風(fēng)格更新的路徑:Uboot層>Kernel層>HAL&Framework層>系統(tǒng)與應(yīng)用層。
如圖2粗黑線所示,把需要切換相應(yīng)風(fēng)格的消息逐層上傳,把對(duì)應(yīng)風(fēng)格相應(yīng)層級(jí)的圖片和動(dòng)畫(huà)風(fēng)格展現(xiàn)出來(lái),隨后標(biāo)記當(dāng)前風(fēng)格的圖片和動(dòng)畫(huà)狀態(tài),提供給下一層級(jí)使用。點(diǎn)擊“切換風(fēng)格”,系統(tǒng)在完成[由上往下]的消息傳遞及配置后,自動(dòng)重啟,在重新啟動(dòng)的過(guò)程中,完成系統(tǒng)開(kāi)機(jī)過(guò)程三個(gè)階段的圖片及動(dòng)畫(huà),也包括系統(tǒng)風(fēng)格的更新,步驟如下:
步驟1:在Uboot層獲取RTC寄存器,得到需要切換的風(fēng)格信息,通過(guò)Memory記錄讀取狀態(tài)值,完成顯示Uboot Logo;
步驟2:在Kernel層讀取Memory特定位置記錄的標(biāo)記,得知上一層切換的是何種風(fēng)格,完成顯示Kernel Logo;
步驟3:在HAL&Framework層由文件系統(tǒng)的狀態(tài),得知上一層切換的圖片或動(dòng)畫(huà)是何種風(fēng)格,完成播放Bootanimation動(dòng)畫(huà);
步驟4:在系統(tǒng)層由文件系統(tǒng)的狀態(tài),得知要更新的是何種風(fēng)格,[標(biāo)記](méi)當(dāng)前是何種風(fēng)格的圖畫(huà)和動(dòng)畫(huà) ,完成系統(tǒng)風(fēng)格的更新。
3.1.1 系統(tǒng)與應(yīng)用Apk設(shè)置
進(jìn)入“設(shè)置”菜單中,系統(tǒng)通過(guò)[文件系統(tǒng)]獲取當(dāng)前是何種風(fēng)格的圖畫(huà)和動(dòng)畫(huà)(假如當(dāng)前風(fēng)格為[風(fēng)格2]),[標(biāo)記](méi)當(dāng)前風(fēng)格的狀態(tài),如要更新新的風(fēng)格,如選中[風(fēng)格1],點(diǎn)擊“切換風(fēng)格”,系統(tǒng)會(huì)自動(dòng)更新相應(yīng)[風(fēng)格1]的圖片和動(dòng)畫(huà),以及系統(tǒng)風(fēng)格;如果不更新則退出菜單,保持原來(lái)風(fēng)格。
3.1.2 Hal&JNI狀態(tài)
Hal層承上啟下,通過(guò)Native和系統(tǒng)及應(yīng)用相通,通過(guò)文件系統(tǒng)和kernel相通。
3.1.3 Kernel層設(shè)置
Kernel層和Hal或JNI是通過(guò)IOCtrl機(jī)制進(jìn)行傳遞的,實(shí)質(zhì)還是文件系統(tǒng)。Kernel接受到不同的信息后,會(huì)做不同的處理,此處就是寫(xiě)RTC的不同狀態(tài),告知下一層要切換狀態(tài)的風(fēng)格,通過(guò)RTC寄存器把狀態(tài)保存起來(lái)供不同層級(jí)使用。
3.1.4 Uboot層狀態(tài)的接受
在Kernel層中,我們要把傳遞的狀態(tài)信息存在RTC寄存器中,利用RTC空余Bit位保存切換風(fēng)格的狀態(tài)。風(fēng)格的狀態(tài)信息從上層傳遞下來(lái)后,在Kernel層的時(shí)候給RTC寄存器賦值,把狀態(tài)保存下來(lái),寄存器和閃存的原理一樣,只要不掉電或不被重寫(xiě),寄存器的值是不變的,系統(tǒng)重啟時(shí)RTC寄存器不會(huì)被復(fù)位,系統(tǒng)重啟進(jìn)入U(xiǎn)boot層時(shí),去讀這個(gè)RTC寄存器,從而獲取到Kernel層想要傳下來(lái)的是風(fēng)格信息。
結(jié)合圖2所示,系統(tǒng)重新啟動(dòng)后,在開(kāi)機(jī)的過(guò)程中,系統(tǒng)需要完成三個(gè)階段圖片和動(dòng)畫(huà)的更新以及系統(tǒng)風(fēng)格的更新。
3.2.1 Uboot Logo更新
系統(tǒng)在開(kāi)機(jī)后完成基本配置就要顯示Uboot Logo,顯示風(fēng)格的狀態(tài)由RTC寄存器值傳遞過(guò)來(lái),顯示Logo的整個(gè)過(guò)程步驟如下:
A.通過(guò)讀取RTC寄存器值,獲取到將要更新的是何種風(fēng)格的狀態(tài)(Kernel層>Uboot層);
B.讀取Memory固定區(qū)域中記錄風(fēng)格狀態(tài)的數(shù)據(jù),獲取當(dāng)前是何種風(fēng)格狀態(tài);
C.對(duì)顯示接口(show_logo(style1))進(jìn)行統(tǒng)一,實(shí)現(xiàn)不同風(fēng)格的裝載;
D.如果與當(dāng)前風(fēng)格狀態(tài)不一致,則把[風(fēng)格1]的Uboot Logo裝入顯示接口(show_logo(style_1),并在Memory中記錄更新后的狀態(tài),此時(shí),我們把這種風(fēng)格1的狀態(tài)寫(xiě)Memory中保存起來(lái)。這些數(shù)據(jù)寫(xiě)在特定的Memory分區(qū)內(nèi),不受掉電、關(guān)機(jī)、恢復(fù)出廠設(shè)置的影響,所以能夠保留確定的風(fēng)格狀態(tài);
E.如果與當(dāng)前風(fēng)格狀態(tài)一致,則把原有風(fēng)格的Uboot Logo裝入顯示接口,進(jìn)行狀態(tài)值回填[9]。
3.2.2 Kernel Logo 更新
系統(tǒng)進(jìn)入Kernel層,完成相應(yīng)驅(qū)動(dòng)加載后,會(huì)顯示Kernel Logo,具體步驟如下:
A.通過(guò)讀取Nandflash的特定數(shù)據(jù),獲取上一層Uboot的風(fēng)格狀態(tài);
B.建立系統(tǒng)文件,更新文件系統(tǒng)狀態(tài),供HAL&Framework層、系統(tǒng)和應(yīng)用層使用;
C.如果與當(dāng)前風(fēng)格狀態(tài)不一致,則更新?tīng)顟B(tài),把需要切換的[風(fēng)格1]圖片裝入相應(yīng)的文件接口;如果與當(dāng)前風(fēng)格一致,則狀態(tài)不更新,把原來(lái)風(fēng)格的圖片裝入到文件接口;
D.回填狀態(tài),通過(guò)顯示接口進(jìn)行l(wèi)ogo顯示;
3.2.3 Bootanimation動(dòng)畫(huà)更新
在Framework層,完成第三個(gè)階段動(dòng)畫(huà)的播放,步驟如下:
步驟1 通過(guò)讀取文件系統(tǒng),F(xiàn)ramwork層獲取Kernel層需要更新的[風(fēng)格1]狀態(tài)后,判斷是否與當(dāng)前風(fēng)格動(dòng)畫(huà)狀態(tài)一致。
步驟2 如果不一致,先更新?tīng)顟B(tài),把需要切換的[風(fēng)格1]動(dòng)畫(huà)裝入到播放接口;如果一致,則狀態(tài)不更新,把原有風(fēng)格的動(dòng)畫(huà)裝入文件接口。
步驟3 回填狀態(tài),更新文件系統(tǒng),通過(guò)播放接口播放動(dòng)畫(huà)。
風(fēng)格定制化后的正常開(kāi)機(jī),系統(tǒng)會(huì)顯示當(dāng)前標(biāo)記的圖片和動(dòng)畫(huà),如圖3粗黑線所標(biāo)示。
圖3 正常開(kāi)機(jī)軟件流程圖
為了保證風(fēng)格信息狀態(tài)的確定性,在Memory(Nand Flash)空余區(qū)域 劃分出專(zhuān)屬區(qū)域記錄切換的狀態(tài);在系統(tǒng)Uboot階段去讀取Memory中記錄的當(dāng)前風(fēng)格狀態(tài),再去讀RTC的狀態(tài),如果不做切換,會(huì)保持當(dāng)前風(fēng)格狀態(tài);在Kernel或Hal&Framework 風(fēng)格更新之前,都會(huì)獲取到原有的風(fēng)格狀態(tài),根據(jù)獲取的狀態(tài),做原有風(fēng)格的更新。
系統(tǒng)預(yù)置多套風(fēng)格供自由切換,因此需要準(zhǔn)備多套風(fēng)格的圖片和動(dòng)畫(huà)等資源。同一風(fēng)格的圖片和動(dòng)畫(huà)分為Uboot Logo,Kernel Logo,Bootanimation動(dòng)畫(huà),這些資源預(yù)置到內(nèi)存后,需要按不同風(fēng)格命名,如圖4所示,對(duì)于開(kāi)機(jī)過(guò)程三個(gè)階段的圖片或動(dòng)畫(huà)資源,切換成加載的目標(biāo)格式等,可以借助Shell腳本自動(dòng)完成。
圖4 風(fēng)格資源示意圖
本文針對(duì)公交信息屏的風(fēng)格定制需求給出了一種基于Android的系統(tǒng)風(fēng)格深度定制方法,并在多個(gè)公交信息屏項(xiàng)目上進(jìn)行了應(yīng)用,收到了良好的反饋。此方法適用于所有Android系統(tǒng)的信息顯示設(shè)備,有非常友好的系統(tǒng)適配性。