GLWallpaperService分析一

 WallpaperService是用来实现动态壁纸的服务,使用WallpaperService的典型方式是实现自定义的继承自WallpaperService的动态壁纸类。并实现它的WallpaperService.Engine。WallpaperService的onCreateEngine()方法会返回这个engine的实例。

 

常见的自定义的动态壁纸实现如下:

AndroidManifest.xml

<service
                            android:label="@string/app_name"
                            android:name=".LiveWallpaper"
                            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/livewallpaper" />
</service>


实现

public class LiveWallpaper extends WallpaperService
{
         @Override
         public Engine onCreateEngine()
         {
                   return new MyEngine();
         }
 
         class MyEngine extends Engine
         {
                   Handler mHandler = new Handler();
                   private final Runnable drawTarget = new Runnable()
                   {
                            public void run()
                            {
                                     drawFrame();
                            }
                   };
        @Override
                   public void onCreate(SurfaceHolder surfaceHolder)
                   {
                            super.onCreate(surfaceHolder);
                            setTouchEventsEnabled(true);
                   }
 
                   @Override
                   public void onDestroy()
                   {
                            super.onDestroy();
                            // 删除回调
                            mHandler.removeCallbacks(drawTarget);
                   }
 
                   @Override
                   public void onVisibilityChanged(boolean visible)
                   {
                            mVisible = visible;
                            // 当界面可见时候,执行drawFrame()方法。
                            if (visible)
                            {
                                     drawFrame();
                            }
                            else
                            {
                                     // 如果界面不可见,删除回调
                                     mHandler.removeCallbacks(drawTarget);
                            }
                   }
 
                   @Override
                   public void onOffsetsChanged(float xOffset, float yOffset, float xStep,
                            float yStep, int xPixels, int yPixels)
                   {
                            drawFrame();
                   }
 
                   @Override
                   public void onTouchEvent(MotionEvent event)
                   {
                 //自己实现一些触碰时的代码
                            super.onTouchEvent(event);
                   }
                   private void drawFrame()
                   {
                            final SurfaceHolder holder = getSurfaceHolder();
                            Canvas c = null;
                            try
                            {
                                     // 对画布加锁
                                     c = holder.lockCanvas();
                                     if (c != null)
                                     {
                 //调用Canvas的方法进行绘制


 

以上代码摘自疯狂Android讲义的示例代码,其本身是参考的Android示例源码的CubeLiveWallpaper动态壁纸(Android4.2\android\development\samples\CubeLiveWallpaper)

 

可以发现由于WallpaperService本身由于是一个Service,所以其无法直接在UI上进行绘图,而是会通过锁定surface上面的画面,并返回一个画布Canvas。然后在Canvas上绘制图片或者颜色,形状等,绘制完毕后再释放对画面的锁定,并将画布展示在屏幕上。

这种方法注定无法快速的处理我们想要展示的动画,比如绘制一个随着手指滑动的波纹,这种效果更多的是需要更加快速的展示,而不是Canvas绘制时如同幻灯片一般的卡顿。

这方面的例子还有比如大名鼎鼎的Jake Wharton(ActionBarSherlock,Android-ViewPagerIndicator,butterknife,NineOldAndroids作者)的早期作品BreakoutWallpaperSnakeWallpaperWakkaWallpaperTronWallpaper其实现效果都是一帧一帧的动画

 

而Android系统自带的动态壁纸如MagicSmoke等。其为什么能够实现流畅的动画效果的?

是因为其使用的是RenderScript脚本,使用render脚本来渲染基础的surface画面。

1,RenderScriptGL  mRs = newRenderScriptGL(RenderScriptWallpaper.this, sc); //使用WallpaperService的Context新建一个RenderScript类。
2,mRs.setSurface(holder,width, height);//将WallpaperService和Surface进行绑定。
3,mRenderer.init(mRs,getResources(), isPreview());//加载rs脚本文件
4,mRenderer.start(); //开始播放rs脚本


 

这样通过高效的渲染脚本来直接绘制画面,流畅的绘制动态壁纸。

 

对于不熟悉rs脚本的coder,是不是在自己实现动态壁纸的时候,也能够直接绘制surface而让动态壁纸真正流畅的运行起来?

答案是肯定的。Mark F Guerragithub上实现了一个GLWallpaperService——一个使用OpenGL Android动态壁纸库。通过使用该库,能够更快速的实现一个使用OpenGL 快速渲染的动态壁纸。在Android里如何使用OpenGL,可以参考下面这个教程:

http://www.jayway.com/tag/opengl-es/

甚至连著名的壁纸软件muzei 也使用了该库。有兴趣的可以参考一下。

 

后面会进行如下分析:

GLWallpaperService 的使用

GLWallpaperService 实现分析

 

 

 

你可能感兴趣的:(动画,android,canvas,OpenGL,Surface)