- 浏览: 538163 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
landerson:
明显就有要求的嘛
ANDROID轻量级JSON序列化和反序列化[转] -
jimode2013:
很不错,就是需要这个方法
多个UIViewController使用addSubView,第二个 UIViewController 不响应旋转[转] -
w11h22j33:
...
[转]NSMutableArray中的自动释放对象让我郁闷了一整天 -
w11h22j33:
UILabel* label = [[UILabel a ...
Iphone开发 -
w11h22j33:
http://mobile.51cto.com/iphone- ...
获得通讯录中联系人的所有属性[转]
通常手机屏幕的壁纸就是一张静态的图片,看上去已经挺不错的了,但它不会有变化。
LiveWallPaper 动态壁纸是从Android2.1就开始带有的一个新的特性。它让我们能够将本来毫无生气的静态的手机屏幕背景替换成 从 随着音乐的活力和脉动而跳跃的声线 到 手指抚过能激起阵阵涟漪的静默的池塘。显示当前天气情况、展示幻灯片甚至是表现烟火特效也只是android百变动态壁纸的冰山一角。现在让我们揭开它神秘的面纱。看看这些神奇的应用是如何做到的。
图一
创建我们的CS——LiveWallpaper项目
在这个例子中,我们将创造一个活生生的墙纸,使用OpenGL显示一个旋转的立方体。最后的程序运行结果就如图一所示。首先创建一个新的android项目,在其的向导wizard中使用这些值:
Project name: CS_Livewallpaper
Build Target: Android 2.2
Application name: Wallpaper
Package name: classroom.studio
Min SDK Version: 8
Activity的名字可以先空着。关闭Activity项左边的复选框。如下图二所示。
图二
创建项目后,我们需要为新项目中的androidmanifest.xml文件中添加新的属性。它看起来就像下面这样。
1 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 2 package="classroom.studio" 3 android:versionCode="1" 4 android:versionName="1.0"> 5 <application android:label="@string/app_name"> 6 <service android:name=".Wallpaper" 7 android:label="@string/service_name" 8 android:permission="android.permission.BIND_WALLPAPER"> 9 <intent-filter> 10 <action android:name= 11 "android.service.wallpaper.WallpaperService" /> 12 </intent-filter> 13 <meta-data android:name="android.service.wallpaper" 14 android:resource="@xml/wallpaper" /> 15 </service> 16 </application> 17 <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" /> 18 </manifest> 19
<service>这个标签是新的。它定义了一个,将运行在背景上并且对事件有响应的Android服务。 android:permission= attribute的意思是任何程序调用我们的服务都需要有一个指定的权限。 Android的Home程序已经具备了该权限,所以它会工作得很好。
< intent-filter >这个标签告诉Android它是个什么样的服务,并且< meta-data >标签让它知道在哪能找到关于wallpaper的额外信息。 android:resource被设为"@xml/wallpaper"这个值最好改成res/xml/wallpaper.xml 文件。以下便是该xml文件的内容。
1 <?xml version="1.0" encoding="utf-8"?> 2 <wallpaper xmlns:android="http://schemas.android.com/apk/res/android" 3 android:author="@+string/author" 4 android:description="@string/description" 5 android:thumbnail="@drawable/thumbnail" 6 />
这个 wallpaper的metadata(元数据)指定了这个程序的作者的名字、该程序的介绍以及一个缩略图。所有这些分别存储在string.xml以及drawable文件中。他们将在使用者选择该使用哪个动态壁纸应用的时候以列表的形式显示出来。因此我们还需要创建一个string.xml文件。如下所示。
我们可以AVD中看到这个文件实际所起的作用。如下图三所示
图三
同时我们也需要删除掉一个Layout中的文件 res/layout/main.xml。因为我们不会在这个程序中使用它。在我们具体了解了Android的一些服务之后我们将填写Wallpaper类。
书接前文,我们先要介绍Android的services。Android的一个与众不同的特征就是具有可在背景中运行程序的能力。为了将他们与前景的activities分开,Android把这些程序叫做services。
Service类由一个service的main java类继承.Services像 activities一样 也有个生命周期,但较之要简单得多。 在这个周期中,当我们第一次创建service类时, 需要调用onCreate()的方法。而当我们消除该service时,则调用了onDestroy()方法。
而在这两者之间,当客户发出开始service的请求时,Android将调用 onStartCommand()方法 。当然Android也为我们提供一些其他的方法以备不时需,例如在内存低情况下使用的onLowMemory()方法,以及下表一所示。
表一
void | onRebind(Intent intent)
如果之前通过onUnbind(Intent)方法已经通告解除所有联系后,
当新的clients再与service取得联系时,该方法被调用。
|
Boolean | onUnbind(Intent intent)
当所用Clients都已与一个service发出的特点界面断开联系时,调用该方法。
|
final void | stopSelf()
如果之前它开始过,则自己停止该service。
|
final void | startForeground(int id, Notification notification)
该方法使该service能够运行在前台(前景上),
并在这个状态下支持将ongoing的通知显示给用户。
|
final void | stopForeground(boolean removeNotification)
从前景中去除该service,并允许在内存低时杀死service。
|
当然在我们这个例子中,不需要关心这些方法,因为他们都将由Service的子类WallpaperService 来处理。
我们的main类需要扩展成Wallpaper,就像下面这样。
1 package classroom。studio; 2 import android.service.wallpaper.WallpaperService; 3 public class Wallpaper extends WallpaperService { 4 private class MyEngine extends Engine { 5 // 从这里实现引擎。。。 6 } 7 @Override 8 public Engine onCreateEngine() { 9 return new MyEngine(); 10 } 11 } 12
我们现在要做的就是实现只有一行代码的onCreateEngine()方法。它的唯一目的就是要创建并返回另一个叫做MyEngine的类。
构建一个绘图引擎
因为这个MyEngine一定要是Wallpaper里的一个类,所以在类的封闭的大括号中声明了它。MyEngine 扩展了由Android提供的Engine类。以下的代码是带有所有要用到的方法的MyEngine 纲要。
1 private class MyEngine extends Engine { 2 @Override 3 public void onCreate(final SurfaceHolder holder) { 4 super.onCreate(holder); 5 } 6 @Override 7 public void onDestroy() { 8 super.onDestroy(); 9 }; 10 @Override 11 public void onSurfaceCreated(final SurfaceHolder holder) { 12 super.onSurfaceCreated(holder); 13 } 14 @Override 15 public void onSurfaceDestroyed(final SurfaceHolder holder) { 16 super.onSurfaceDestroyed(holder); 17 }@Override 18 public void onSurfaceChanged(final SurfaceHolder holder, 19 final int format, final int width, final int height) { 20 super.onSurfaceChanged(holder, format, width, height); 21 } 22 @Override 23 public void onVisibilityChanged(final boolean visible) { 24 super.onVisibilityChanged(visible); 25 } 26 @Override 27 public void onOffsetsChanged(final float xOffset, 28 final float yOffset, final float xOffsetStep, 29 final float yOffsetStep, final int xPixelOffset, 30 final int yPixelOffset) { 31 super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, 32 yOffsetStep, xPixelOffset, yPixelOffset); 33 } 34 }
需要注意的是每个方法应该总是调用其基类方法。
在Engine的整个生命周期中,Android会在特定的命令下调用这些方法。下面就是整个句子。
onCreate
onSurfaceCreated
onSurfaceChanged (1+ calls in any order)
onOffsetsChanged (0+ calls in any order)
onVisibilityChanged (0+ calls in any order)
onSurfaceDestroyed
onDestroy
接下来,我们将填写这些方法。不过我们还需要几个声明来防止编译出错,当我们编写代码时我们可以让Eclipse帮我们来创建这些语句(使用 Content Assist(Ctrl+空格)或是 Quick Fix(Ctrl+1) 亦或是通过Source > Organize Imports command ( Ctrl+Shift+O )实现批处理。但如果您愿意的话,也可以自己敲,下面是完整的列表。
1 import java.util.concurrent.ExecutorService; 2 import java.util.concurrent.Executors; 3 import javax.microedition.khronos.egl.EGL10; 4 import javax.microedition.khronos.egl.EGL11; 5 import javax.microedition.khronos.egl.EGLConfig; 6 import javax.microedition.khronos.egl.EGLContext; 7 import javax.microedition.khronos.egl.EGLDisplay; 8 import javax.microedition.khronos.egl.EGLSurface; 9 import javax.microedition.khronos.opengles.GL10; 10 import android.service.wallpaper.WallpaperService; 11 import android.view.SurfaceHolder;
下面让我们开始画我们的立方体吧。初始效果如图四所示。OpenGL ES
图四
先要了解一下何为OpenGL 以及OpenGL ES。
OpenGL的前世今生
1992年Silicon Graphics 开发出了OpenGL。它从此开始为程序员提供一个统一的平台让他们能够驾驭来自不同生产商的硬件。它的核心,OpenGL迎合了三维图形开发的一些经典概念如viewpoints和lighting并试图让开发者可以基本不去考虑错综复杂的硬件层就能实现3D的效果。您可以浏览http://www.opengl.org了解OpenGL的更多内容。
不过正是因为当初它是为工作站设计的,所以OpenGL对于一部手机来说实在是太大了。所以Google Android采用了OpenGL的一个子集——(OpenGL for Embedded Systems 针对嵌入式系统的OpenGL 简称OpenGL ES)。这个标准是由Intel、AMD、Nividia、Nokia、SONY、三星等行业巨头共同支持的 Khronos Group行业协会提出来的,包括Android、塞班和Iphone在内的主要手机平台都采用了这个库。虽然他们彼此之间还是有着细微的差别。您可以浏览http://www.khronos.org/opengles了解OpenGL ES的更多内容。
几乎每种计算机语言都有他自己与OpenGL ES相绑定的部分。当然JAVA也不例外。在JAVA Specification Request(JSR)239中定义了这部分绑定。
Android的OpenGL ES
OpenGL ES 1.0 基于完整的OpenGL 1.3,而 ES 1.1 基于 OpenGL 1.5。JSR 239 有两个版本:一个原有的1.0 和正式的1.0.1。而我们这次使用的便是OpenGL ES1.1
不过从Android2.2开始,OpenGL ES 2.0开始通过android.opengl 包得到支持。您也可以通过NDK来调用它。OpenGL ES 2.0 。不过还没有对应于OpenGL ES 2.0的JSR标准。如下图五所示
图五
现在让我们用OpenGL ES来建立我们自己的立方体模型吧。
评论
1 package org.example.opengl;
2 -
3 - import java.nio.ByteBuffer;
4 - import java.nio.ByteOrder;
5 5 import java.nio.IntBuffer;
6 -
7 - import javax.microedition.khronos.opengles.GL10;
8 -
9 - import android.content.Context;
10 10 import android.graphics.Bitmap;
11 - import android.graphics.BitmapFactory;
12 - import android.opengl.GLUtils;
13 -
14 - class GLCube {
15 private final IntBuffer mVertexBuffer;
16 - public GLCube() {
17 - int one = 65536;
18 - int half = one / 2;
19 - int vertices[] = {
20 // 前
21 - -half, -half, half, half, -half, half,
22 - -half, half, half, half, half, half,
23 - // 后
24 - -half, -half, -half, -half, half, -half,
25 half, -half, -half, half, half, -half,
26 - // 左
27 - -half, -half, half, -half, half, half,
28 - -half, -half, -half, -half, half, -half,
29 - // 右
30 half, -half, -half, half, half, -half,
31 - half, -half, half, half, half, half,
32 - // 顶
33 - -half, half, half, half, half, half,
34 - -half, half, -half, half, half, -half,
35 // 底
36 - -half, -half, half, -half, -half, -half,
37 - half, -half, half, half, -half, -half, };
38 -
45 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
46 - vbb.order(ByteOrder.nativeOrder());
47 - mVertexBuffer = vbb.asIntBuffer();
48 - mVertexBuffer.put(vertices);
49 - mVertexBuffer.position(0);
50 5 }- public void draw(GL10 gl) {
51 - gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
52 -
53 gl.glColor4f(1, 1, 1, 1);
54 - gl.glNormal3f(0, 0, 1);
55 - gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
56 - gl.glNormal3f(0, 0, -1);
57 - gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);
58
59 - gl.glColor4f(1, 1, 1, 1);
60 - gl.glNormal3f(-1, 0, 0);
61 - gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);
62 - gl.glNormal3f(1, 0, 0);
63 gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);
64 -
65 - gl.glColor4f(1, 1, 1, 1);
66 - gl.glNormal3f(0, 1, 0);
67 - gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);
68 gl.glNormal3f(0, -1, 0);
69 - gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);
70 - }
71 - }
在上述代码的第19行的矩阵通过点坐标确定了立方体的各个顶点。我们都知道立方体的每一个面都是个正方形。而这个正方形又是由两个等腰直角三角形组成的。 我们可以使用OpenGL中一个常用的绘图模型——GL_TRIANGLE_STRIP来画这个正方形。在这个模型中,我们指定两个起始点,随后标出的每一个点都将与起始点确定一个三角形。这是在图形加速硬件上绘出大量几何图形的一种十分快捷的方法。需要注意的是每个点都有x、y、z三个坐标。x轴指向屏幕右端、y轴指向屏幕上端而z轴则指向屏幕外朝向用户的视角。在代码第45行绘图方法中,我们使用构造的VertexBuffer并且为立方体的六条边画出六个不同向的等腰直角三角形。在项目实战中,您可能会把几个调用组合在一或两个strips中,因为您代码中的OpenGL命令调用越少,您的程序运行起来越快。
光、动作与质地
在真实的的生活中,我们周围有很多光源如太阳、灯光、火炬或是萤火虫的生物光。为了打造虚拟的3D世界,OpenGL让我们可以在场景中给出8种光源。并且如果我们想要它成为一个动态的背景,那么就一定要加入动作。当然这还不够,如果不给它加入质地(材质)的话,没人会相信它是个真东西。那在接下来的代码中我们将一一实现这些功能。
GlRenderer.java
1 package org.example.opengl;
2
3 import javax.microedition.khronos.egl.EGLConfig;
4 import javax.microedition.khronos.opengles.GL10;
5
6 import android.content.Context;
7 import android.opengl.GLSurfaceView;
8 import android.opengl.GLU;
9 import android.util.Log;
10
11 class GLRenderer implements GLSurfaceView.Renderer {
12 private static final String TAG = "GLRenderer";
13 private final Context context;
14
15
16 private final GLCube cube = new GLCube();
17
18
19 private long startTime;
20 private long fpsStartTime;
21 private long numFrames;
22
23
24
25 GLRenderer(Context context) {
26 this.context = context;
27 }
28
29
30
31 public void onSurfaceCreated(GL10 gl, EGLConfig config) {
32
37 boolean SEE_THRU = false;
38 // 定义了一个布尔变量用于设置是否使程序执行第79行使立方体变得透明的语句
39
40 startTime = System.currentTimeMillis();
41 fpsStartTime = startTime;
42 numFrames = 0;
43
44
45 // 定义光源
46
47 float lightAmbient[] = new float[] { 0.2f, 0.2f, 0.2f, 1 };
48 float lightDiffuse[] = new float[] { 1, 1, 1, 1 };
49 float[] lightPos = new float[] { 1, 1, 1, 1 };
50 gl.glEnable(GL10.GL_LIGHTING);
51 gl.glEnable(GL10.GL_LIGHT0);
52 gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0);
53 gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0);
54 gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPos, 0);
55
56
57 // 立方体的材质,这可以决定光照在它上面的效果 漫反射还是镜面反射。
58
59 float matAmbient[] = new float[] { 1, 1, 1, 1 };
60 float matDiffuse[] = new float[] { 1, 1, 1, 1 };
61 gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT,
62 matAmbient, 0);
63 gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE,
64 matDiffuse, 0);
65
66
67
68 // 设置我们需要的各种参数
69 gl.glEnable(GL10.GL_DEPTH_TEST);
70 gl.glDepthFunc(GL10.GL_LEQUAL);
71 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
72
73 // 选项:禁用抖动特效,以提高性能。
74 // gl.glDisable(GL10.GL_DITHER);
75
76
77
78 // 如上面提到的使透明的语句
79 if (SEE_THRU) {
80 gl.glDisable(GL10.GL_DEPTH_TEST);
81 gl.glEnable(GL10.GL_BLEND);
82 gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
83 }
84
85
86 // 启用纹理特效
87 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
88 gl.glEnable(GL10.GL_TEXTURE_2D);
89
90 // 将一张点阵图加载为立方体的纹理。
91 GLCube.loadTexture(gl, context, R.drawable.android);
92
93
94
95
96 }
97
98
99
100
101 public void onSurfaceChanged(GL10 gl, int width, int height) {
102
103 // ...
104
105
106 // 定义视角
107 gl.glViewport(0, 0, width, height);
108 gl.glMatrixMode(GL10.GL_PROJECTION);
109 gl.glLoadIdentity();
110 float ratio = (float) width / height;
111 GLU.gluPerspective(gl, 45.0f, ratio, 1, 100f);
112
113 }
114
115
116
117
118
119 public void onDrawFrame(GL10 gl) {
120
121 // ...
122
123
124
125
126 // 清到黑屏
127 gl.glClear(GL10.GL_COLOR_BUFFER_BIT
128 | GL10.GL_DEPTH_BUFFER_BIT);
129
130 // ...
131 gl.glMatrixMode(GL10.GL_MODELVIEW);
132 gl.glLoadIdentity();
133 gl.glTranslatef(0, 0, -3.0f);
134
135 // 您的其它的绘图命令可以写在这里。
136
137
138 // 根据时间设置每次旋转的角度
139 long elapsed = System.currentTimeMillis() - startTime;
140 gl.glRotatef(elapsed * (25f / 1000f), 0, 1, 0); //每秒钟它都会沿Y轴转25度
141 gl.glRotatef(elapsed * (10f / 1000f), 1, 0, 0); //每秒钟它沿x轴转10度
142
143
144 // 画出模型
145 cube.draw(gl);
146
147
148 // 随时跟踪得出的帧数
149
150 numFrames++;
151 long fpsElapsed = System.currentTimeMillis() - fpsStartTime;
152 if (fpsElapsed > 3 * 1000) { // 每3秒一次
153 float fps = (numFrames * 1000.0F) / fpsElapsed;
154 Log.d(TAG, "Frames per second: " + fps + " (" + numFrames
155 + " frames in " + fpsElapsed + " ms)");
156 fpsStartTime = System.currentTimeMillis();
157 numFrames = 0;
158 }
159
160
161
162
163
164 }
165
166
167
168 }
169
在代码的第69行,我们设置了一组OpenGL 参数。当然OpenGL那几十个参数都是通过glEnable( ) 来启用,通过 glDisable( )来禁用。在下面列出的是最常用到的参数选项。
选项说明:
GL_BLEND 允许将新进来的颜色值与已经在缓冲区中的颜色值融合。
GL_CULL_FACE
Ignore polygons(多边形) based on their
winding (clockwise or counterclockwise
(顺时针还是逆时针)) in window coordinates.
This is a cheap way to eliminate back faces.
(正在琢磨如何解释)
GL_DEPTH_TEST
进行更深入的比较,并且更新缓冲区的深度。
忽略掉像素数已经远高于之前绘制好的。
GL_LIGHTi Include light number i when figuring out an object’s
brightness and color.(正在琢磨如何解释)
GL_LIGHTING 开启照明和材质计算。
GL_LINE_SMOOTH 绘制抗锯齿线(无锯齿线)。
GL_MULTISAMPLE 启动多重采样抗锯齿和其他效果。
GL_POINT_SMOOTH 绘制抗锯齿点。
GL_TEXTURE_2D 使用纹理绘制表面。
除了GL_DITHER和GL_MULTISAMPLE以外其他选项都是默认关闭的。请注意,我们启动的任何一项特性都会带有一定的性能开销。
请注意一下第150行开始的代码,请问我们为什么要检测每秒钟的帧数呢?
为的是检测画面的流畅程度
我们如何界定流畅程度。对一个游戏或对图形加速能力要求较高的程序,可以通过它刷洗屏幕的速度来看出它的流畅度。我们经常使用FPS即每秒帧数来衡量。不同的人对于流畅与否的尺度是不同的。一般来讲 15–30FPS对于普通玩家来说就可以接受了。但较骨灰级的玩家来说可能要60FPS或是更高才能让他们满意。作为专业的程序员,我们应该向着60FPS的目标而努力。但这可能不太现实,毕竟一些服务于低端的Android手机,他们的3D硬件加速相对于他们的分辨率要弱一些。当然对于越快的设备,达到这个标准越是没有问题。高帧频是具有挑战性的,因为我们要在60fps下 即1/60th秒(16.67毫秒之间)调用onDrawFrame()做一切需要做的事情,包括任何动画、物理计算、游戏计算,再加上花费在实际绘制图形上的时间。而唯一能够检验程序的FPS是否达到了我们设计的预期的方法,就是就是通过程序自己来测量它。
如上面的代码所示。每三秒它就会将您的平均FPS值发到Android系统的Log Messages上。如果这个数字低于您的预期,您就可以调整您的算法并重试。当然AVD毕竟是模拟。我们最终还是要看实际真机测试。
发表评论
-
Android Launcher 分析【转】
2011-04-03 16:35 1960http://blog.csdn.net/fengke ... -
Android 中Goolgle 相关服务的移植[转]
2011-04-03 16:28 17031. 为什么需要移植? 首先,我编译了Android ... -
编译 android 2.1 (eclair) 源码 For HTC G1[转]
2011-03-27 15:51 20111. 说明 1) 下载编译最基本的android源码,无 ... -
从源代码编译Android(CyanogenMod For Hero GSM)【转】
2011-03-26 13:29 2728http://www.cnrgb.com/compile-cy ... -
Ubuntu10.0.4下CyanogenMod编译环境的搭建和可刷机文件的编译及打包(For HTC Dream)【转】
2011-03-26 13:27 4512http://www.linuxidc.com/Linux/2 ... -
在Android中使用OpenCv
2011-03-02 22:46 1287http://www.eoeandroid.com/threa ... -
android2.3源码下载编译全过程(附图及文档)修改版【转】
2011-03-02 22:43 2255原文http://www.eoeandroid.com ... -
Ubuntu 10.04(64位)下载并编译 Android 2.2 源码[只有11条命令]【转】
2011-02-13 23:44 2539为了方便,我把所有操作写成了命令,按顺序(软件安装--源码下载 ... -
动态壁纸探究[转]
2011-01-26 23:39 2052转自http://www.ophonesdn.com/ar ... -
定制你自己的桌面--- launcher小觑[转]
2011-01-26 10:22 1347定制你自己的桌面--- lau ... -
[转]下载并编译Android 2.3源码
2011-01-22 13:29 5545原文http://www.blogjava.net/TiGER ... -
Launcher研究之AndroidManifest.xml[转]
2010-12-14 09:22 2637分析Launcher的AndroidManifest.xml文 ... -
让你自己写的Android的Launcher成为系统中第一个启动的,也是唯一的Launcher(转载)
2010-12-13 22:19 1091如果你要定制一个Android系统,你想用你自己的Launch ... -
为Android加入busybox工具
2010-12-13 17:32 1731我们可以通过两种方式进入Android的console: 1 ... -
Android源码编译后
2010-12-13 00:08 3255在out/target/product/generic下生成的 ...
相关推荐
《X Live Wallpaper X动态壁纸v3.7 高级版》是一个专为手机或平板设备设计的高级动态壁纸应用。该应用提供了丰富的个性化选项,让用户能够定制自己的桌面背景,为移动设备增添生动有趣的视觉效果。v3.7版本可能是该...
Android动态壁纸,或者说“Live Wallpaper”,是Android操作系统中一种特殊的应用类型,允许用户将动态、交互式的背景设置为手机或平板电脑的主屏幕壁纸。这种壁纸不仅提供了静态图像的视觉体验,还可以根据用户的...
动态壁纸的实现主要依赖于Android系统的`LiveWallpaper`服务。首先,我们需要创建一个继承自`WallpaperService`的类,并在其中重写`engine`方法。在这个`engine`中,我们将定义壁纸的绘制逻辑,通常会用到`...
在Android平台上,动态壁纸(Live Wallpaper)是一种可以让用户自定义主屏幕背景的特殊类型的应用程序。它们不仅可以显示静态图像,还可以展示动态效果、交互式动画或者其他复杂视觉元素。本篇文章将深入探讨如何...
在Android平台上,动态壁纸(Live Wallpaper)是一种可以让用户自定义主屏幕背景的高级功能,它不仅限于静态图片,还能展示动画或者响应用户的交互。"Android动态壁纸模板"是一个非常有价值的资源,尤其对于那些想要...
首先,理解Android动态壁纸(Live Wallpaper)的概念是至关重要的。Android动态壁纸是一种特殊类型的壁纸应用,它不仅展示静态图像,还能展示动画或交互式内容。它们运行在Android系统的壁纸服务中,允许用户自定义...
开发者可能使用C#的WinForms或WPF(Windows Presentation Foundation)框架来创建这个动态壁纸程序。WinForms是.NET Framework的早期UI库,而WPF则提供了更强大的图形渲染能力和更丰富的用户体验设计选项。 在创建...
《TZM-Android-LiveWallpaper:开源精神在动态壁纸中的展现》 “TZM-Android-LiveWallpaper”是一个专为Android系统设计的开源动态壁纸应用,其核心理念是融入了“时代精神运动”(Zeitgeist Movement)的理念。这...
8. 版本控制与项目管理:项目名称中的`giant-app-LiveWallpaper-3042c41`可能是Git仓库的一个特定提交哈希,表明这个动态壁纸工具的开发可能使用了版本控制系统,如Git,来进行协作和版本管理。 总的来说,"dotnet-...
2. Livewallpaper的实现: Livewallpaper是Android动态壁纸的实现,需要继承自WallpaperService,并实现onCreateEngine方法。在onCreateEngine方法中,需要实现Engine类并返回。 3. MyEngine类的实现: MyEngine类...
"livewallpaper_i18n" 是一个与动态壁纸国际化的开源项目,它主要关注的是如何在不同的语言环境中提供动态壁纸服务。在Android平台上,动态壁纸(Live Wallpapers)是一种能够展示动态图像和交互效果的壁纸形式。i18...
在压缩包文件名"LiveWallpaper"中,我们可以推测这个项目可能包含了一个名为"LiveWallpaper"的Java类,它实现了上述的`LiveWallpaperService`,并包含了动态壁纸的实现代码。为了调试和运行这个项目,开发者需要将源...
开发动态壁纸涉及到对Android的WallpaperService类的扩展,并实现其onCreateEngine()方法,创建一个壁纸引擎实例。在这个实例中,开发者可以编写绘制和更新壁纸的逻辑。 "Live Battery Wallpaper"的核心功能是根据...
在Android平台上进行应用程序开发时,有时我们希望创建个性化的屏保(Live Wallpaper)来提升用户体验。这个"Android程序研发源码Android 屏保源码.rar"压缩包提供了一个实际的屏保应用源代码,这对于开发者来说是...
5. 提供设置动态壁纸的入口:在应用程序的设置界面或主界面,提供一个按钮或菜单项,点击后启动`LiveWallpaper Chooser` Intent。 ```java Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_...
"muzei-webcam"是Muzei Live Wallpaper的一个扩展,它允许用户将网络摄像头的实时图像设置为手机或设备的动态壁纸。这个扩展程序为Muzei增添了新的功能,使得用户可以享受到更加个性化和动态的桌面体验。 【描述...
我们先来看看 Livewallpaper(即动态墙纸)的实现,Android的动态墙纸并不是GIF图片,而是一个标准的Android应用程序,也就是APK。既然是应用程序,当然意味着天生具有GIF图片不具备的功能——能与用户发生交互,...
屏幕保护程序在Android中被称为“Live Wallpaper”,它不仅有静态壁纸的功能,还能展示动态效果,甚至具备交互性。 开发Android屏幕保护程序,首先需要熟悉Java或Kotlin编程语言,因为这两种语言是Android应用开发...