通常手机屏幕的壁纸就是一张静态的图片,看上去已经挺不错的了,但它不会有变化。

 

让我们揭开它神秘的面纱。看看这些神奇的应用是如何做到的。

  

Android 壁纸WallpaperService android live wallpapers_Blend

                                                                              图一

                    创建我们的CS——LiveWallpaper项目

  在这个例子中,我们将创造一个活生生的墙纸,使用OpenGL显示一个旋转的立方体。最后的程序运行结果就如图一所示。首先创建一个新的android项目,在其的向导wizard中使用这些值:

Project  name:  CS_Livewallpaper
Build  Target:  Android  2.2
Application  name:  Wallpaper
Package  name:  classroom.studio
Min  SDK  Version:  8

    Activity的名字可以先空着。关闭Activity项左边的复选框。如下图二所示。

Android 壁纸WallpaperService android live wallpapers_Blend_02

                                                                                  图二

为新项目中的androidmanifest.xml文件中添加新的属性。它看起来就像下面这样。

 



1 
  < 
  manifest  
  xmlns:android 
  ="http://schemas.android.com/apk/res/android" 
    
   2 
   package 
  ="classroom.studio" 
    
   3 
   android:versionCode 
  ="1" 
    
   4 
   android:versionName 
  ="1.0" 
  > 
    
   5 
    
  < 
  application  
  android:label 
  ="@string/app_name" 
  > 
    
   6 
    
  < 
  service  
  android:name 
  =".Wallpaper" 
    
   7 
   android:label 
  ="@string/service_name" 
    
   8 
   android:permission 
  ="android.permission.BIND_WALLPAPER" 
  > 
    
   9 
    
  < 
  intent-filter 
  > 
    
  10 
    
  < 
  action  
  android:name 
  =  
  11 
   "android.service.wallpaper.WallpaperService" 
    
  /> 
    
  12 
    
  </ 
  intent-filter 
  > 
    
  13 
    
  < 
  meta-data  
  android:name 
  ="android.service.wallpaper" 
    
  14 
   android:resource 
  ="@xml/wallpaper" 
    
  /> 
    
  15 
    
  </ 
  service 
  > 
    
  16 
    
  </ 
  application 
  > 
    
  17 
    
  < 
  uses-sdk  
  android:minSdkVersion 
  ="8" 
   android:targetSdkVersion 
  ="8" 
    
  /> 
    
  18 
  </ 
  manifest 
  > 
    
  19


 

背景上并且对事件有响应的Android服务。 android:permission= attribute的意思是任何程序调用我们的服务都需要有一个指定的权限。 Android的Home程序已经具备了该权限,所以它会工作得很好。

 

      < intent-filter >这个标签告诉Android它是个什么样的服务,并且< meta-data >标签让它知道在哪能找到关于wallpaper的额外信息。 android:resource被设为"@xml/wallpaper"这个值最好改成res/xml/wallpaper.xml 文件。以下便是该xml文件的内容。

 

 




1 
  <? 
  xml version="1.0" encoding="utf-8" 
  ?> 
    
  2 
  < 
  wallpaper  
  xmlns:android 
  ="http://schemas.android.com/apk/res/android" 
    
  3 
  android:author 
  ="@+string/author" 
    
  4 
  android:description 
  ="@string/description" 
    
  5 
  android:thumbnail 
  ="@drawable/thumbnail" 
    
  6 
  />


 

   这个 wallpaper的metadata(元数据)指定了这个程序的作者的名字、该程序的介绍以及一个缩略图。所有这些分别存储在string.xml以及drawable文件中。他们将在使用者选择该使用哪个动态壁纸应用的时候以列表的形式显示出来。因此我们还需要创建一个string.xml文件。如下所示。

 




Android 壁纸WallpaperService android live wallpapers_三星_03

string.xml

   我们可以AVD中看到这个文件实际所起的作用。如下图三所示

                                     

Android 壁纸WallpaperService android live wallpapers_三星_04

                                                                  图三

 

  同时我们也需要删除掉一个Layout中的文件 res/layout/main.xml。因为我们不会在这个程序中使用它。在我们具体了解了Android的一些服务之后我们将填写Wallpaper类。 

 

 

   书接前文,我们先要介绍Android的services。Android的一个与众不同的特征就是具有可在背景中运行程序的能力。为了将他们与前景的activities分开,Android把这些程序叫做services。

 

   Service类由一个service的main java类继承.Services像 activities一样 也有个生命周期,但较之要简单得多。 在这个周期中,当我们第一次创建service类时, 需要调用onCreate()的方法。而当我们消除该service时,则调用了onDestroy()方法。

 

方法,以及下表一所示。 

                                                                                        表一


公开的部分的方法

void          

onRebind(Intent intent)

如果之前通过onUnbind(Intent)方法已经通告解除所有联系后,


当新的clients再与service取得联系时,该方法被调用。

Boolean

onUnbind(Intent intent)

当所用Clients都已与一个service发出的特点界面断开联系时,调用该方法。

final void

stopSelf()

如果之前它开始过,则自己停止该service。

final void           

startForeground(int id, Notification notification)

该方法使该service能够运行在前台(前景上),


并在这个状态下支持将ongoing的通知显示给用户。

final void

stopForeground(boolean removeNotification)

从前景中去除该service,并允许在内存低时杀死service。


 


想了解更多方法请参考: http://d.android.com/reference/android/app/Service.html


   当然在我们这个例子中,不需要关心这些方法,因为他们都将由Service的子类WallpaperService 来处理。

   我们的main类需要扩展成Wallpaper,就像下面这样。


1   package 
   classroom。studio;  
   2 
    
  import 
   android.service.wallpaper.WallpaperService;  
   3 
    
  public 
    
  class 
   Wallpaper  
  extends 
   WallpaperService {  
   4 
    
  private 
    
  class 
   MyEngine  
  extends 
   Engine {  
   5 
    
  // 
   从这里实现引擎。。。 
    
   6 
    
  }  
   7 
  @Override  
   8 
    
  public 
   Engine onCreateEngine() {  
   9 
    
  return 
    
  new 
   MyEngine();  
  10 
  }  
  11 
  }  
  12

 

   我们现在要做的就是实现只有一行代码的onCreateEngine()方法。它的唯一目的就是要创建并返回另一个叫做MyEngine的类。

 

            构建一个绘图引擎

     因为这个MyEngine一定要是Wallpaper里的一个类,所以在类的封闭的大括号中声明了它。MyEngine 扩展了由Android提供的Engine类。以下的代码是带有所有要用到的方法的MyEngine 纲要。

 



Android 壁纸WallpaperService android live wallpapers_游戏_05

wallpaper.java     
 1    private      
   class 
    MyEngine  
   extends 
    Engine {  
    2 
   @Override  
    3 
     
   public 
     
   void 
    onCreate( 
   final 
    SurfaceHolder holder) {  
    4 
     
   super 
   .onCreate(holder);  
    5 
   }  
    6 
   @Override  
    7 
     
   public 
     
   void 
    onDestroy() {  
    8 
     
   super 
   .onDestroy();  
    9 
   };  
   10 
   @Override  
   11 
     
   public 
     
   void 
    onSurfaceCreated( 
   final 
    SurfaceHolder holder) {  
   12 
     
   super 
   .onSurfaceCreated(holder);  
   13 
   }  
   14 
   @Override  
   15 
     
   public 
     
   void 
    onSurfaceDestroyed( 
   final 
    SurfaceHolder holder) {  
   16 
     
   super 
   .onSurfaceDestroyed(holder);  
   17 
   }@Override  
   18 
     
   public 
     
   void 
    onSurfaceChanged( 
   final 
    SurfaceHolder holder,  
   19 
   final 
     
   int 
    format,  
   final 
     
   int 
    width,  
   final 
     
   int 
    height) {  
   20 
   super 
   .onSurfaceChanged(holder, format, width, height);  
   21 
   }  
   22 
   @Override  
   23 
   public 
     
   void 
    onVisibilityChanged( 
   final 
     
   boolean 
    visible) {  
   24 
   super 
   .onVisibilityChanged(visible);  
   25 
   }  
   26 
   @Override  
   27 
   public 
     
   void 
    onOffsetsChanged( 
   final 
     
   float 
    xOffset,  
   28 
   final 
     
   float 
    yOffset,  
   final 
     
   float 
    xOffsetStep,  
   29 
   final 
     
   float 
    yOffsetStep,  
   final 
     
   int 
    xPixelOffset,  
   30 
   final 
     
   int 
    yPixelOffset) {  
   31 
   super 
   .onOffsetsChanged(xOffset, yOffset, xOffsetStep,  
   32 
   yOffsetStep, xPixelOffset, yPixelOffset);  
   33 
   }  
   34 
   }


 

   需要注意的是每个方法应该总是调用其基类方法。

   在Engine的整个生命周期中,Android会在特定的命令下调用这些方法。下面就是整个句子。

onCreate
     onSurfaceCreated
                  onSurfaceChanged (1+ calls in any order)
                  onOffsetsChanged (0+ calls in any order)
                  onVisibilityChanged (0+ calls in any order)
     onSurfaceDestroyed
onDestroy


  接下来,我们将填写这些方法。不过我们还需要几个声明来防止编译出错,当我们编写代码时我们可以让Eclipse帮我们来创建这些语句(使用 Content Assist(Ctrl+空格)或是 Quick Fix(Ctrl+1) 亦或是通过Source > Organize Imports command ( Ctrl+Shift+O )实现批处理。但如果您愿意的话,也可以自己敲,下面是完整的列表。

 



1   import    java.util.concurrent.ExecutorService;  
   2 
  import 
   java.util.concurrent.Executors;  
   3 
  import 
   javax.microedition.khronos.egl.EGL10;  
   4 
  import 
   javax.microedition.khronos.egl.EGL11;  
   5 
  import 
   javax.microedition.khronos.egl.EGLConfig;  
   6 
  import 
   javax.microedition.khronos.egl.EGLContext;  
   7 
  import 
   javax.microedition.khronos.egl.EGLDisplay;  
   8 
  import 
   javax.microedition.khronos.egl.EGLSurface;  
   9 
  import 
   javax.microedition.khronos.opengles.GL10;  
  10 
  import 
   android.service.wallpaper.WallpaperService;  
  11 
  import 
   android.view.SurfaceHolder;

 

 下面让我们开始画我们的立方体吧。初始效果如图四所示。OpenGL ES

 

Android 壁纸WallpaperService android live wallpapers_XML_06

 

                                                图四

 

 

 

先要了解一下何为OpenGL 以及OpenGL ES。

 

   OpenGL的前世今生


    1992年Silicon Graphics 开发出了OpenGL。它从此开始为程序员提供一个统一的平台让他们能够驾驭来自不同生产商的硬件。它的核心,OpenGL迎合了三维图形开发的一些经典概念如viewpoints和lighting并试图让开发者可以基本不去考虑错综复杂的硬件层就能实现3D的效果。您可以浏览http://www.opengl.org了解OpenGL的更多内容。

    不过正是因为当初它是为工作站设计的,所以OpenGL对于一部手机来说实在是太大了。所以Google Android采用了OpenGL的一个子集——(OpenGL for Embedded Systems 针对嵌入式系统的OpenGL 简称OpenGL ES)。这个标准是由Intel、AMD、Nividia、Nokia、SONY、三星等行业巨头共同支持的 Khronos Group行业协会提出来的,包括Android、塞班和Iphone在内的主要手机平台都采用了这个库。虽然他们彼此之间还是有着细微的差别。您可以浏览http://www.khronos.org/opengles了解OpenGL ES的更多内容。

    几乎每种计算机语言都有他自己与OpenGL ES相绑定的部分。当然JAVA也不例外。在JAVA Specification Request(JSR)239中定义了这部分绑定。

 

    Android的OpenGL ES


    OpenGL ES 1.0 基于完整的OpenGL 1.3,而 ES 1.1 基于 OpenGL 1.5。JSR 239 有两个版本:一个原有的1.0 和正式的1.0.1。而我们这次使用的便是OpenGL ES1.1

    不过从Android2.2开始,OpenGL ES 2.0开始通过android.opengl 包得到支持。您也可以通过NDK来调用它。OpenGL ES 2.0  。不过还没有对应于OpenGL ES 2.0的JSR标准。如下图五所示

  

Android 壁纸WallpaperService android live wallpapers_游戏_07

                                                     图五

 

    现在让我们用OpenGL ES来建立我们自己的立方体模型吧。