本节我们在上一节的基础上继续完成动态壁纸功能,我们要分析的目标就是《OpenGL ES应用开发实践指南 Android卷》书中第14章实现的最终的结果,代码下载请点击:Opengl ES Source Code,该Git库中的livewallpaper Module就是我们本节要分析的目标,先看下本节最终实现的结果。

     最终的效果,就是把我们上一节实现的结果作为壁纸显示了出来,桌面滑动时,壁纸也跟着滑动。如果了解壁纸的同学应该都知道,本节的内容其实和Opengl ES完全没有什么相关的了,就是实现一个壁纸,壁纸实现完全用的是我们上一节已经实现的结果。

     本节新增的代码,首先是在Manifest中注册了GLWallpaperService,它必须要实现framework定义的WallpaperService,才能实现自定义壁纸功能,而要实现WallpaperService,必须要重写onCreateEngine方法,并返回一个WallpaperService类的内部类Engine的实例对象,所以对壁纸的控制都是在Engine中完成的。《深入理解ANDROID 卷3》一书的第8章中对android系统的壁纸功能有非常详细的源码分析讲解,大家如果想了解详情的话,强烈推荐看一下该书,下载链接:深入理解ANDROID 卷3.pdf。

     GLWallpaperService完整源码如下:

public class GLWallpaperService extends WallpaperService {    @Override    public Engine onCreateEngine() {        return new GLEngine();    }    public class GLEngine extends Engine {        private static final String TAG = "GLEngine";        private WallpaperGLSurfaceView glSurfaceView;        private ParticlesRenderer particlesRenderer;        private boolean rendererSet;        @Override        public void onCreate(SurfaceHolder surfaceHolder) {            super.onCreate(surfaceHolder);            if (LoggerConfig.ON) {                Log.d(TAG, "onCreate(" + surfaceHolder + ")");            }            glSurfaceView = new WallpaperGLSurfaceView(GLWallpaperService.this);            // Check if the system supports OpenGL ES 2.0.            ActivityManager activityManager =                    (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);            ConfigurationInfo configurationInfo = activityManager                    .getDeviceConfigurationInfo();            // Even though the latest emulator supports OpenGL ES 2.0,            // it has a bug where it doesn't set the reqGlEsVersion so            // the above check doesn't work. The below will detect if the            // app is running on an emulator, and assume that it supports            // OpenGL ES 2.0.            final boolean supportsEs2 =                    configurationInfo.reqGlEsVersion >= 0x20000                            // Check for emulator.                            || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1                            && (Build.FINGERPRINT.startsWith("generic")                            || Build.FINGERPRINT.startsWith("unknown")                            || Build.MODEL.contains("google_sdk")                            || Build.MODEL.contains("Emulator")                            || Build.MODEL.contains("Android SDK built for x86")));            /*            final ParticlesRenderer particlesRenderer =                 new ParticlesRenderer(GLWallpaperService.this);            */            particlesRenderer = new ParticlesRenderer(GLWallpaperService.this);            if (supportsEs2) {                glSurfaceView.setEGLContextClientVersion(2);                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {                    glSurfaceView.setPreserveEGLContextOnPause(true);                }                glSurfaceView.setRenderer(particlesRenderer);                rendererSet = true;            } else {                /*                 * This is where you could create an OpenGL ES 1.x compatible                 * renderer if you wanted to support both ES 1 and ES 2. Since                 * we're not doing anything, the app will crash if the device                 * doesn't support OpenGL ES 2.0. If we publish on the market, we                 * should also add the following to AndroidManifest.xml:                 *                 *                  *                 * This hides our app from those devices which don't support OpenGL                 * ES 2.0.                 */                Toast.makeText(GLWallpaperService.this,                        "This device does not support OpenGL ES 2.0.",                        Toast.LENGTH_LONG).show();                return;            }        }        @Override        public void onVisibilityChanged(boolean visible) {            super.onVisibilityChanged(visible);            if (LoggerConfig.ON) {                Log.d(TAG, "onVisibilityChanged(" + visible + ")");            }            if (rendererSet) {                if (visible) {                    glSurfaceView.onResume();                } else {                    glSurfaceView.onPause();                }            }        }        @Override        public void onOffsetsChanged(final float xOffset, final float yOffset,                                     float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) {            glSurfaceView.queueEvent(new Runnable() {                @Override                public void run() {                    particlesRenderer.handleOffsetsChanged(xOffset, yOffset);                }            });        }        @Override        public void onDestroy() {            super.onDestroy();            if (LoggerConfig.ON) {                Log.d(TAG, "onDestroy()");            }            glSurfaceView.onWallpaperDestroy();        }        class WallpaperGLSurfaceView extends GLSurfaceView {            private static final String TAG = "WallpaperGLSurfaceView";            WallpaperGLSurfaceView(Context context) {                super(context);                if (LoggerConfig.ON) {                    Log.d(TAG, "WallpaperGLSurfaceView(" + context + ")");                }            }            @Override            public SurfaceHolder getHolder() {                if (LoggerConfig.ON) {                    Log.d(TAG, "getHolder(): returning " + getSurfaceHolder());                }                return getSurfaceHolder();            }            public void onWallpaperDestroy() {                if (LoggerConfig.ON) {                    Log.d(TAG, "onWallpaperDestroy()");                }                super.onDetachedFromWindow();            }        }    }}

     该类中就是自定义了WallpaperGLSurfaceView,它是继承GLSurfaceView,用它来显示我们自定义的壁纸,其他的代码我们就不展开分析了,大家有兴趣可以自己研究一下。

     到这里我们就把《OpenGL ES应用开发实践指南 Android卷》书中后面的章节的代码就分析完了,后续我们继续学习Opengl ES 3.0的代码实现。虽然学完了,相信大家肯定会有这样的感觉,我们还只是懂了原理,完全自己写,估计目前难度还非常大,这也许就是易学难精的道理吧,新手、老手、高手的路还有很长,要成为真正的高手,我们还是必须要结合实践,不断的实现需求,修改逻辑,排查问题,只有这样反复的磨炼,才能不断的提高我们的内功!!

更多相关文章

  1. 初识Android的界面UI
  2. 资深程序员多年代码实践总结:《和Android源代码一起工作》 | Andr
  3. Android(安卓)Studio 中手把手教你设置switch/case代码块自动补
  4. Android(安卓)内存分析总结
  5. 如何优雅的实现Android(安卓)屏幕适配方案
  6. 动态化部署:Android热修复之代码修复(一)
  7. android 中用代码模拟发送按键
  8. Android(安卓)App 的设计架构:MVC、MVP、MVVM 的分析
  9. 本人初学android,希望大神帮忙指点学习路线,现在好迷茫

随机推荐

  1. 加载一张高德地图
  2. 【Android】安卓布局文件中xmlns属性
  3. android 字节流缓冲区 字节缓冲流 读写SD
  4. android 自定义Toast增加点击事件、Toast
  5. Android基础知识梳理
  6. Android实现Service下载文件,Notification
  7. android中开启子线程
  8. Android(安卓)Service 两种启动方式的区
  9. Android仿微信雷达扫描效果的实现方法
  10. Android(安卓)Vibrator的使用