Opengl ES系列学习--创建动态壁纸

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

Opengl ES系列学习--创建动态壁纸_第1张图片

Opengl ES系列学习--创建动态壁纸_第2张图片

Opengl ES系列学习--创建动态壁纸_第3张图片

Opengl ES系列学习--创建动态壁纸_第4张图片

     最终的效果,就是把我们上一节实现的结果作为壁纸显示了出来,桌面滑动时,壁纸也跟着滑动。如果了解壁纸的同学应该都知道,本节的内容其实和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的代码实现。虽然学完了,相信大家肯定会有这样的感觉,我们还只是懂了原理,完全自己写,估计目前难度还非常大,这也许就是易学难精的道理吧,新手、老手、高手的路还有很长,要成为真正的高手,我们还是必须要结合实践,不断的实现需求,修改逻辑,排查问题,只有这样反复的磨炼,才能不断的提高我们的内功!!

你可能感兴趣的:(Opengl,ES,android,framework,数据结构和算法,Android源码解析,android,opengl,opengl,es)