1、动态壁纸是在Android 2.1新增的一个功能。动态壁纸可以添加到Android的桌面,具有交互式的动画背景效果。在本教程中,我们将教会你如何去制作一个交互式的动态壁纸。 动态壁纸是一个Android应用程序,包括一个服务(WallpaperService)。该服务必须包括一个引擎(WallpaperService.Engine)。该引擎是连接用户、桌面、系统之间的桥梁。它也可以绘制桌面壁纸。 首先,必须由内在的Engine类创建一个WallpaperService类。该服务必须在AndroidManifest.xml中声明为"android.service.wallpaper.Wall
2、paperService",这样它才会作为动态壁纸被手机识别。而且还要在服务配置中附加"android.permission.BIND_WALLPAPER"的权限许可:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
3、mission="android.permission.BIND_WALLPAPER">
4、ervice>
创建一个XML文件,放置在应用程序目录下的/res/xml/中。它用来描述你的动态壁纸。
?
1
2
3
4
5
6
5、个xml的属性文件 attrs.xml ,代码如下:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
7、name="description" />
8、
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package net.androgames.blog.sample.livewallpaper;
import android.content.SharedPreferences;
import android.service 9、wallpaper.WallpaperService;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
/**
* Android Live Wallpaper Archetype
* @author antoine vianey
* under GPL v3 : http://www.gnu.org/licenses/gpl-3.0.html
*/
public class Live 10、WallpaperService extends WallpaperService {
@Override
public Engine onCreateEngine() {
return new SampleEngine();
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestro 11、y();
}
public class SampleEngine extends Engine {
private LiveWallpaperPainting painting;
SampleEngine() {
SurfaceHolder holder = getSurfaceHolder();
painting = new LiveWallpaperPainting(holder,
getApplicationContext 12、));
}
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
// register listeners and callbacks here
setTouchEventsEnabled(true);
}
@Override
public void onDes 13、troy() {
super.onDestroy();
// remove listeners and callbacks here
painting.stopPainting();
}
@Override
public void onVisibilityChanged(boolean visible) {
if (visible) {
// register listeners and call 14、backs here
painting.resumePainting();
} else {
// remove listeners and callbacks here
painting.pausePainting();
}
}
@Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
15、 int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
painting.setSurfaceSize(width, height);
}
@Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder) 16、
// start painting
painting.start();
}
@Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
boolean retry = true;
painting.stopPainting();
while 17、 (retry) {
try {
painting.join();
retry = false;
} catch (InterruptedException e) {}
}
}
@Override
public void onOffsetsChanged(float xOffset, float yOffset,
floa 18、t xStep, float yStep, int xPixels, int yPixels) {
}
@Override
public void onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
painting.doTouchEvent(event);
}
}
}
当壁纸的显示、状态或大小变化是,会调用Engine的onCreate, onDestroy, o 19、nVisibilityChanged,onSurfaceChanged, onSurfaceCreated 和 onSurfaceDestroyed方法。有了这些方法,动态壁纸才能展现出动画效果。而通过设置setTouchEventsEnabled(true),并且调用onTouchEvent(MotionEvent event)方法,来激活触摸事件。
我们在绘画墙纸的时候,也会使用一个单独的绘画线程:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
20、
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100 21、
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package net.androgames.blog.sample.livewallpaper;
import android.content.Context;
import and 22、roid.graphics.Canvas;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
/**
* Android Live Wallpaper painting thread Archetype
* @author antoine vianey
* GPL v3 : http://www.gnu.org/licenses/gpl-3.0.html
*/
public class L 23、iveWallpaperPainting extends Thread {
/** Reference to the View and the context */
private SurfaceHolder surfaceHolder;
private Context context;
/** State */
private boolean wait;
private boolean run;
/** Dimensions */
private int width;
priva 24、te int height;
/** Time tracking */
private long previousTime;
private long currentTime;
public LiveWallpaperPainting(SurfaceHolder surfaceHolder,
Context context) {
// keep a reference of the context and the surface
// the context is neede 25、d if you want to inflate
// some resources from your livewallpaper .apk
this.surfaceHolder = surfaceHolder;
this.context = context;
// don't animate until surface is created and displayed
this.wait = true;
}
/**
* Pauses the live wallp 26、aper animation
*/
public void pausePainting() {
this.wait = true;
synchronized(this) {
this.notify();
}
}
/**
* Resume the live wallpaper animation
*/
public void resumePainting() {
this.wait = false;
27、 synchronized(this) {
this.notify();
}
}
/**
* Stop the live wallpaper animation
*/
public void stopPainting() {
this.run = false;
synchronized(this) {
this.notify();
}
}
@Override
public 28、void run() {
this.run = true;
Canvas c = null;
while (run) {
try {
c = this.surfaceHolder.lockCanvas(null);
synchronized (this.surfaceHolder) {
currentTime = System.currentTimeMillis();
29、 updatePhysics();
doDraw(c);
previousTime = currentTime;
}
} finally {
if (c != null) {
this.surfaceHolder.unlockCanvasAndPost(c);
}
}
// pause if 30、 no need to animate
synchronized (this) {
if (wait) {
try {
wait();
} catch (Exception e) {}
}
}
}
}
/**
* Invoke when the surface dimension cha 31、nge
*/
public void setSurfaceSize(int width, int height) {
this.width = width;
this.height = height;
synchronized(this) {
this.notify();
}
}
/**
* Invoke while the screen is touched
*/
public void doTouchEvent 32、MotionEvent event) {
// handle the event here
// if there is something to animate
// then wake up
this.wait = false;
synchronized(this) {
notify();
}
}
/**
* Do the actual drawing stuff
*/
private void 33、 doDraw(Canvas canvas) {}
/**
* Update the animation, sprites or whatever.
* If there is nothing to animate set the wait
* attribute of the thread to true
*/
private void updatePhysics() {
// if nothing was updated :
// this.wait = true;
}
}
如果桌面壁纸是可见状态下,系统服务通知有新的东西,这个类会优先把它绘制在画布上。如果没有动画了,updatePhysics会通知线程去等待。通常SurfaceView在有两个画布交替绘制的时候,会在画布上绘制上一次......






