Android原理之动态墙纸

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/

那么,动态墙纸的本质是什么呢?前文已述,是APK,不过是比较特殊的APK。我们不妨打开MagicSomke的AndroidManifest.xml文件:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!--  
  3. /*  
  4. **  
  5. ** Copyright 2008, The Android Open Source Project  
  6. **  
  7. ** Licensed under the Apache License, Version 2.0 (the "License");  
  8. ** you may not use this file except in compliance with the License.  
  9. ** You may obtain a copy of the License at  
  10. **  
  11. **     http://www.apache.org/licenses/LICENSE-2.0  
  12. **  
  13. ** Unless required by applicable law or agreed to in writing, software  
  14. ** distributed under the License is distributed on an "AS IS" BASIS,  
  15. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  16. ** See the License for the specific language governing permissions and  
  17. ** limitations under the License.  
  18. */  
  19. -->  
  20. <manifest  
  21.     xmlns:android="http://schemas.android.com/apk/res/android"  
  22.     package="com.android.magicsmoke">  
  23.   
  24.     <original-package android:name="com.android.magicsmoke" />  
  25.   
  26.     <uses-feature android:name="android.software.live_wallpaper" />  
  27.   
  28.     <uses-permission android:name="android.permission.SET_WALLPAPER_COMPONENT" />  
  29.     <uses-permission android:name="android.permission.BIND_WALLPAPER" />  
  30.   
  31.     <application  
  32.         android:label="@string/wallpapers"  
  33.         android:icon="@drawable/ic_launcher_wallpaper">  
  34.   
  35.         <service  
  36.             android:label="@string/wallpaper_magicsmoke"  
  37.             android:name="MagicSmoke"  
  38.             android:permission="android.permission.BIND_WALLPAPER">  
  39.             <intent-filter>  
  40.                 <action android:name="android.service.wallpaper.WallpaperService" />  
  41.             </intent-filter>  
  42.             <meta-data android:name="android.service.wallpaper" android:resource="@xml/magicsmoke" />  
  43.         </service>  
  44.   
  45.         <activity  
  46.             android:name="com.android.magicsmoke.MagicSmokeSelector"  
  47.             android:theme="@style/Preview"  
  48.             android:exported="true">  
  49.         </activity>  
  50.   
  51.     </application>  
  52.   
  53. </manifest>  

我想细心的朋友已经猜出来了,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的背景设置为非透明的,比如以不透明的图片或者颜色作为背景,那么,你将看不到任何动态墙纸效果,当然,这样的话,静态墙纸你也不会看到了。

相关推荐