Opengl ES系列学习--创建动态壁纸
本节我们在上一节的基础上继续完成动态壁纸功能,我们要分析的目标就是《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的代码实现。虽然学完了,相信大家肯定会有这样的感觉,我们还只是懂了原理,完全自己写,估计目前难度还非常大,这也许就是易学难精的道理吧,新手、老手、高手的路还有很长,要成为真正的高手,我们还是必须要结合实践,不断的实现需求,修改逻辑,排查问题,只有这样反复的磨炼,才能不断的提高我们的内功!!
更多相关文章
- 初识Android的界面UI
- 资深程序员多年代码实践总结:《和Android源代码一起工作》 | Andr
- Android(安卓)Studio 中手把手教你设置switch/case代码块自动补
- Android(安卓)内存分析总结
- 如何优雅的实现Android(安卓)屏幕适配方案
- 动态化部署:Android热修复之代码修复(一)
- android 中用代码模拟发送按键
- Android(安卓)App 的设计架构:MVC、MVP、MVVM 的分析
- 本人初学android,希望大神帮忙指点学习路线,现在好迷茫