Android OpenGL动态壁纸

首先申明下,本文为笔者学习《OpenGL ES应用开发实践指南》的笔记,并加入笔者自己的理解和归纳总结。

1、动态壁纸的Service组件

WallpaperService提供了基本的动态壁纸的实现。

public class GLWallpaperService extends WallpaperService {@Overridepublic Engine onCreateEngine() {return new GLEngine();}}

2、创建自定义GLSurfaceView

GLSurfaceView会调用getHolder()来添加界面,只需重载getHolder方法,返回动态壁纸的渲染表面。onWallpaperDestroy在销毁动态壁纸时被调用,使用GLSurfaceView的onDetachedFromWindow方法。

class WallpaperGLSurfaceView extends GLSurfaceView {public WallpaperGLSurfaceView(Context context) {super(context);}@Overridepublic SurfaceHolder getHolder() {return GLEngine.this.getSurfaceHolder();}public void onWallpaperDestroy() {super.onDetachedFromWindow();}
}

3、Engine类

GLEngine继承Engine类,当动态壁纸创建时,调用GLEngine的onCreate方法来初始化,销毁时调用onDestroy方法。当动态壁纸可见或者隐藏时,onVisibilityChanged方法会被调用。

public class GLEngine extends Engine {@Overridepublic void onCreate(SurfaceHolder surfaceHolder) {super.onCreate(surfaceHolder);}@Overridepublic void onVisibilityChanged(boolean visible) {super.onVisibilityChanged(visible);}@Overridepublic void onDestroy() {super.onDestroy();}}

完善动态壁纸的生命周期,在onCreate中创建GLSurfaceView,onDestroy中销毁。

private WallpaperGLSurfaceView mSurfaceView;@Override
public void onCreate(SurfaceHolder surfaceHolder) {super.onCreate(surfaceHolder);mSurfaceView = new WallpaperGLSurfaceView(GLWallpaperService.this);
}public void onVisibilityChanged(boolean visible) {super.onVisibilityChanged(visible);if (mRender) {if (visible) {mSurfaceView.onResume();} else {mSurfaceView.onPause();}}
}@Override
public void onDestroy() {super.onDestroy();mSurfaceView.onWallpaperDestroy();
}

4、添加配置

在AndroidManifest.xml中添加

<uses-feature android:name="android.software.live_wallpaper" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />

表明这个应用包含一个动态壁纸,并且还需要OpenGL ES 2.0或以上版本。
还需要添加动态壁纸Service的引用

<service android:name=".opengl.GLWallpaperService"android:label="@string/app_name"android:permission="android.permission.BIND_WALLPAPER" ><intent-filter><action android:name="android.service.wallpaper.WallpaperService" /></intent-filter><meta-dataandroid:name="android.service.wallpaper"android:resource="@xml/wallpaper" />
</service>

在资源目录res/xml下,添加wapaper.xml文件

<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"android:thumbnail="@drawable/ic_wallpaper" />

5、体验动态壁纸

(1) 切换到设备的主屏幕上,按住屏幕的空白部分,直至弹出一个菜单。
(2) 选择"动态壁纸",从弹出的列表中选择我们自己的动态壁纸。
(3) 选择"设置壁纸"

6、随主屏幕滚动背景

当你在主屏幕上的不同页面之间来回滑动时,动态壁纸没有移动,通过Engine的onOffsetsChanged方法,可以是实现动态壁纸的滚动效果。

public void onOffsetsChanged(final float xOffset, final float yOffset, float xOffsetStep,float yOffsetStep, int xPixelOffset, int yPixelOffset) {mSurfaceView.queueEvent(new Runnable() {@Overridepublic void run() {mShaderRender.handleOffsetsChanged(xOffset, yOffset);}});
}

7、GLWallpaperService类

public class GLWallpaperService extends WallpaperService {@Overridepublic Engine onCreateEngine() {return new GLEngine();}public class GLEngine extends Engine {private WallpaperGLSurfaceView mSurfaceView;private OpenGLParticleShaderRender mShaderRender;private boolean mRender;@Overridepublic void onCreate(SurfaceHolder surfaceHolder) {super.onCreate(surfaceHolder);mSurfaceView = new WallpaperGLSurfaceView(GLWallpaperService.this);ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);ConfigurationInfo configurationInfo = am.getDeviceConfigurationInfo();boolean supportEs2 = configurationInfo.reqGlEsVersion >= 0x20000;if (supportEs2) {// 选择OpenGL ES 2.0mSurfaceView.setEGLContextClientVersion(2);mShaderRender = new OpenGLParticleShaderRender();// 设置渲染mSurfaceView.setRenderer(mShaderRender);mRender = true;} else {Toast.makeText(GLWallpaperService.this ,"This device does not support OpenGL ES 2.0",Toast.LENGTH_LONG).show();}}@Overridepublic void onVisibilityChanged(boolean visible) {super.onVisibilityChanged(visible);if (mRender) {if (visible) {mSurfaceView.onResume();} else {mSurfaceView.onPause();}}}@Overridepublic void onDestroy() {super.onDestroy();mSurfaceView.onWallpaperDestroy();}@Overridepublic void onOffsetsChanged(final float xOffset, final float yOffset, float xOffsetStep,float yOffsetStep, int xPixelOffset, int yPixelOffset) {mSurfaceView.queueEvent(new Runnable() {@Overridepublic void run() {LogUtil.log("GLEngine", "xOffset = " + xOffset + ", yOffset = " + yOffset);mShaderRender.handleOffsetsChanged(xOffset, yOffset);}});}class WallpaperGLSurfaceView extends GLSurfaceView {public WallpaperGLSurfaceView(Context context) {super(context);}@Overridepublic SurfaceHolder getHolder() {return GLEngine.this.getSurfaceHolder();}public void onWallpaperDestroy() {super.onDetachedFromWindow();}}}private class OpenGLParticleShaderRender implements GLSurfaceView.Renderer {private Particle mParticle;private ParticleProgram mParticleProgram;private ParticleShooter mRedParticleShooter, mGreenParticleShooter, mBlueParticleShooter;private long mGlobalStartTime;private float[] projectionMatrix = new float[16];private float[] viewMatrix = new float[16];private float[] viewProjectionMatrix = new float[16];private float xOffset, yOffset;@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.1f);GLES20.glEnable(GLES20.GL_BLEND);GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);mParticleProgram = new ParticleProgram(GLWallpaperService.this);mParticle = new Particle(10000);mGlobalStartTime = System.nanoTime();final Geometry.Vector particleDirection = new Geometry.Vector(0f, 0.5f, 0f);mRedParticleShooter = new ParticleShooter(new Geometry.Point(-1, 0, 0),particleDirection, Color.rgb(250, 50, 5));mGreenParticleShooter = new ParticleShooter(new Geometry.Point(0, 0, 0),particleDirection, Color.rgb(25, 255, 25));mBlueParticleShooter = new ParticleShooter(new Geometry.Point(1, 0, 0),particleDirection, Color.rgb(5, 50, 255));final float angleVarianceInDegrees = 5f;final float speedVariance = 1f;mRedParticleShooter = new ParticleShooter(new Geometry.Point(-1, 0, 0),particleDirection, Color.rgb(250, 50, 5), angleVarianceInDegrees, speedVariance);mGreenParticleShooter = new ParticleShooter(new Geometry.Point(0, 0, 0),particleDirection, Color.rgb(25, 255, 25), angleVarianceInDegrees, speedVariance);mBlueParticleShooter = new ParticleShooter(new Geometry.Point(1, 0, 0),particleDirection, Color.rgb(5, 50, 255), angleVarianceInDegrees, speedVariance);}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {// 设置视图尺寸GLES20.glViewport(0, 0, width, height);// 创建透视投影Matrix.perspectiveM(projectionMatrix, 0, 45, (float)width / (float)height, 1f, 10f);updateViewMatrices();}@Overridepublic void onDrawFrame(GL10 gl) {// 清空屏幕GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT);float currentTime = (System.nanoTime() - mGlobalStartTime) / 1000000000f;mRedParticleShooter.addParticles(mParticle, currentTime, 5);mGreenParticleShooter.addParticles(mParticle, currentTime, 5);mBlueParticleShooter.addParticles(mParticle, currentTime, 5);mParticleProgram.setUniform(viewProjectionMatrix);mParticleProgram.setCurrentTime(currentTime);mParticle.bindData(mParticleProgram);mParticle.draw();}private void handleOffsetsChanged(float xOffset, float yOffset) {this.xOffset = (xOffset - 0.5f) * 2.5f;this.yOffset = (yOffset - 0.5f) * 2.5f;updateViewMatrices();}private void updateViewMatrices() {// 定义模型矩阵Matrix.setIdentityM(viewMatrix, 0);Matrix.translateM(viewMatrix, 0, 0f - xOffset, -1.5f - yOffset, -5f);Matrix.multiplyMM(viewProjectionMatrix, 0, projectionMatrix, 0, viewMatrix, 0);}}}

显示如下

Android OpenGL动态壁纸相关推荐

  1. Android OpenGL动态壁纸问题总结

    打开动态壁纸时一直显示动态壁纸正在加载 报错信息: 无!(这是最难受的 /(ㄒoㄒ)/~~ ). 问题原因: 粗心导致!把本应返回的MyEngine对象写成了Engine. 问题代码块: public ...

  2. android系统设置动态壁纸,安卓教程:设置GIF动图为手机壁纸

    不禁是一把泪,连设置GIF动态图为壁纸都可以做成教程了,小编你是有多缺文章素材啊?嗯,即便如此,在Android平台上,可是有很多同学为图动不动的问题而苦恼.所以,这篇教程就出来了. 前言:实现GIF ...

  3. Android自定义壁纸预览界面,Android自定义动态壁纸开发(时钟)

    看到有些手机酷炫的动态壁纸,有没有好奇过他们是如何实现的,其实我们自己也可以实现. 先看效果 上图是动态壁纸钟的一个时钟. 我们先来看看 Livewallpaper(即动态墙纸)的实现,Android ...

  4. win10动态壁纸怎么设置_教程:iPhone/Android设置动态壁纸

     提示:点击"软曼网"↑免费订阅本公众号 昨天分享了一篇文章<干啥?想偷看手机?滚!>,很多网友留言不知道如何下载和设置.今天就在分享一下下载和设置方法.用动态Gif图 ...

  5. Android 设置动态壁纸没有确认按钮处理方式

    使用反射设置壁纸, //        wallpaperManager.setWallpaperComponent(new ComponentName(context.getPackageName( ...

  6. android视频动态壁纸app,动态壁纸视频桌面

    动态壁纸视频桌面app,手机动态壁纸大全,为你带来多种类型壁纸资源,适用于学生.情侣.家人.闺蜜等人群,使用简单,内容丰富,轻松搞定你的手机桌面. 软件介绍 动态壁纸视频桌面:是集视频动态壁纸.3D壁 ...

  7. Android自定义动态壁纸开发

    看到有些手机酷炫的动态壁纸,有没有好奇过他们是如何实现的,其实我们自己也可以实现. 一.动态壁纸原理 如果你了解使用过SurfaceView的话,那么开发一款动态壁纸对你来说其实非常简单. 动态壁纸的 ...

  8. Android自定义动态壁纸,Android自定义动态壁纸开发详解

    看到有些手机酷炫的动态壁纸,有没有好奇过他们是如何实现的,其实我们自己也可以实现. 一.动态壁纸原理 如果你了解使用过SurfaceView的话,那么开发一款动态壁纸对你来说其实非常简单. 动态壁纸的 ...

  9. android视频动态壁纸app,短视频动态壁纸转换

    短视频动态壁纸转换app是一款能够将视频转换成动态壁纸的软件.短视频动态壁纸转换app虽然体积非常小巧但是短视频动态壁纸转换app的功能还是蛮强大的,而且操作很简单! 软件介绍 短视频动态壁纸转换ap ...

最新文章

  1. 关于HttpClient上传中文乱码的解决办法
  2. 漫画谈一下Maven依赖,百分之90的同学不知道!
  3. 【BZOJ】3527: [Zjoi2014]力(fft+卷积)
  4. 验证mongodb副本集并实现自动切换primary~记录过程
  5. 使用 kolla-ansible 来 reconfigure OpenStack 集群
  6. 加来道雄 基因编辑 纳米机器人_基因编辑,人工制造超人?科学正在成为新迷信...
  7. oracle11gR2静默安装
  8. php的验证码要gd库,PHP利用GD库实现一个简单的验证码
  9. Python 框架之Flask初步了解
  10. 公司里从员工到经理,不同层级应该关注的事情
  11. python基础知识5——赋值与深浅拷贝——整数和字符串,列表元组字典
  12. Android Studio 无法启动模拟器的一种可能是你装的是Ghost版的系统
  13. 【k8s】记踩坑无数后的kubernetes二进制安装详细步骤
  14. java判断一个数是不是素数_Java-判断一个数是不是素数
  15. 苹果留给 iOS 开发者的时间不多了:30 天内必须更新旧版本!
  16. qlv,qsv,kux格式转换成MP4格式软件
  17. Java中的String长度限制
  18. 在 CSDN 博客 100 天技术日更的 Flag,我做到了!
  19. 如何用c语言实现ax+by+cz=G所有的正整数的解的输出丫?
  20. 老周语录-做出好产品的关键

热门文章

  1. 又一个大雷引发市场巨震?Silvergate或将跌落:成也加密败也加密?
  2. 美少女的小裙子怎么画?怎样才能画好美少女的小裙子?
  3. 解决图片渲染报错[渲染层网络层错误] Failed to load local image resourcethe server responded with a status of 500 (HTT
  4. Excel表格怎么变成 latex 格式?
  5. Python_Runoob
  6. 新年好礼! 华为HG527-C免拆机完全破解
  7. Redis深度历险-Redis Stream
  8. Mac Android开发提升效率的工具、插件、心得集锦(gif动画演示)
  9. java怎么写文件?
  10. Android布局之线性布局LinearLayout(二) ----简单模仿ios端小米计算器主界面UI