來源:Linux社區 作者:droidpioneer
Livewallpaper,即動態牆紙,是Android的一大3D特色功能,使用者可以在案頭選擇載入動態牆紙,讓自己的手機案頭背景旋動起來。
相對於靜態案頭壁紙,動態牆紙可以展示各種動態變化的背景,而與傳統手機系統採用GIF作為動態背景不同的是,Android的動態牆紙並不是GIF圖片,而是一個標準的Android應用程式,也就是APK。既然是應用程式,當然意味著天生具有GIF圖片不具備的功能——能與使用者發生互動,而且動態背景變化絕不僅僅局限於GIF圖片那般只能是固定的幾張圖片的迴圈播放。
需要指出的是,標準的Android系統可以支援將動態GIF圖片設定為牆紙,但並不能將GIF圖片動態運行起來。也就是說,如果你將GIF圖片作為牆紙,你只能看到一幀靜態圖片,不能像很多其他系統的山寨機那樣能夠在案頭看到GIF圖片動態效果。這種局限是Android的一大缺陷,這個缺陷是Android牆紙架構設計缺陷有關。當然了,既然你可以載入豐富類型的旋動的具有互動效果的Android動態牆紙,那麼GIF圖片的少許遺憾完全可以接受。
Android內建的動態牆紙都是基於RenderScript實現的,RenderScript是Google用於Android的一種類C語言,其與C語言語言結構很類似,其對OpenGL的標準API進行了簡單的封裝,可以在運行時再載入RenderScript檔案運行。也就是說,如果你想基於RenderScript開發新的動態牆紙,你應該對OpenGL的常用API有一定的瞭解。此外,Google目前對RenderScript的開發資料還不是很完善,在公開發布的SDK裡也暫時沒有把RenderScript繼承進ADT,換言之,如果你想用RenderScript開發新動態牆紙,你不能基於ADT和SDK在Eclipse下進行開發,而應該下載完整原始碼並編譯整個架構,然後在自己的Linux編譯環境裡去寫新應用。因為RenderScript是要調用OpenGL介面的,你開發的應用要能在真機上運行起來,你的機子必須支援3D,也就是OpenGL。如果你發現有的廠商的手機案頭並沒有載入動態牆紙的入口,那麼不用多說,那一定是該手機根本不支援3D,這一點對於想購買真機來學習Andoid開發的朋友來說就一定要當心了。
Google在發布的各個Android版本裡都內建了一定數量的動態牆紙,各個版本的動態牆紙代碼有少許差別,但是動態牆紙的名稱、視效、個數基本都是一樣的。下面我們看下這些動態牆紙的代碼在什麼位置。我們開啟Google的Android原始碼地址:http://android.git.kernel.org/
可以看到,Android內建的動態牆紙都在packages/wallpapers/這個目錄裡,通過git clone方法(參見“Android源碼下載——用git clone實現單個目錄下載”,http://www.linuxidc.com/Linux/2011-07/38953.htm)快速的下載各個子目錄各個Android版本的Android內建動態牆紙代碼。其中,Basic、MusicVisualization兩個目錄裡都包括了多個相同代碼架構的多個動態牆紙,MagicSmoke目錄只包含魔幻煙霧一個動態牆紙,LivePicker目錄裡包含的是動態牆紙的挑選清單的代碼,也就是你在案頭選擇添加動態牆紙時出現的系統裡所有動態牆紙的那個列表的實現代碼。
那麼,動態牆紙的本質是什麼呢?前文已述,是APK,不過是比較特殊的APK。我們不妨開啟MagicSomke的AndroidManifest.xml檔案:
<span style="font-size:16px;"><manifest xmlns:Android="http://schemas.android.com/apk/res/android" package="com.Android.magicsmoke"> <original-package Android:name="com.android.magicsmoke" /> <uses-feature Android:name="android.software.live_wallpaper" /> <uses-permission Android:name="android.permission.SET_WALLPAPER_COMPONENT" /> <uses-permission Android:name="android.permission.BIND_WALLPAPER" /> <application Android:label="@string/wallpapers" Android:icon="@drawable/ic_launcher_wallpaper"> <service Android:label="@string/wallpaper_magicsmoke" Android:name="MagicSmoke" Android:permission="android.permission.BIND_WALLPAPER"> <intent-filter> <action Android:name="android.service.wallpaper.WallpaperService" /> </intent-filter> <meta-data Android:name= "android.service.wallpaper" android:resource="@xml/magicsmoke" /> </service> <activity Android:name="com.android.magicsmoke.MagicSmokeSelector" Android:theme="@style/Preview" Android:exported="true"> </activity> </application> </manifest> </span>
我想細心的朋友已經猜出來了,Android動態牆紙的本質是一個“Service”,這個Service能夠被主介面Launcher載入。那麼Launcher是如何能識別這個包含動態牆紙Service的APK的呢?上面這個AndroidManifest.xml檔案的intent-filter的action泄露了天機:
<action Android:name="android.service.wallpaper.WallpaperService" />
不錯,系統正式通過APK的這個action把其當做一個動態牆紙載入進LivePicker列表,使用者在LivePicker列表裡選擇自己喜歡的動態牆紙,進而將動態牆紙顯示進Launcher的背後。
需要指出的是,Android的動態牆紙雖然似乎是顯示在Launcher的背景裡,但其實這隻是假象,動態牆紙和Launcher是完全不同的兩個進程,只不過Launcher和動態牆紙的進程可以通過架構裡的WallpaperManager進行處理序間通訊罷了,使用者在Launcher案頭滑動、點擊螢幕時有的動態牆紙能產生互動效果,實際上就是這個進程通訊完成的。如果你通過代碼將Launcher的背景設定為非透明的,比如以不透明的圖片或者顏色作為背景,那麼,你將看不到任何動態牆紙效果,當然,這樣的話,靜態牆紙你也不會看到了。