2024年1月7日发(作者:)

动态壁纸是在Android 2.1新增的一个功能。动态壁纸可以添加到Android的桌面,具有交互式的动画背景效果。在本教程中,我们将教会你如何去制作一个交互式的动态壁纸。

动态壁纸是一个Android应用程序,包括一个服务(WallpaperService)。该服务必须包括一个引擎()。该引擎是连接用户、桌面、系统之间的桥梁。它也可以绘制桌面壁纸。

首先,必须由内在的Engine类创建一个WallpaperService类。该服务必须在中声明为"perService",这样它才会作为动态壁纸被手机识别。而且还要在服务配置中附加"_WALLPAPER"的权限许可:

1

2

android:name="LiveWallpaperService"

3

android:enabled="true"

4

android:icon="@drawable/icon"

5

android:label="@string/app_name"

6

android:permission="_WALLPAPER">

7

8

9

android:name="perService" />

10

11

12

android:name="per"

13

android:resource="@xml/wallpaper" />

创建一个XML文件,放置在应用程序目录下的/res/xml/中。它用来描述你的动态壁纸。

1

2

3

xmlns:android="/apk/res/android"

4

android:thumbnail="@drawable/thumbnail"

5

android:description="@string/description"

6

android:settingsActivity="PreferenceActivity"/>

再创建一个xml的属性文件 ,代码如下:

1

2

4

5

6

7

8

9

10

11

12

13

14

动态壁纸的服务代码如下:

1

package llpaper;

2

3

import Preferences;

4

import perService;

5

import Event;

6

import eHolder;

7

8

/**

9

* Android Live Wallpaper Archetype

10

*

11

rel="nofollow">@author antoine vianey

12

* under GPL v3 : /licenses/

13

*/

14

public class LiveWallpaperService extends WallpaperService {

15

16

@Override

17

public Engine onCreateEngine() {

18

return new SampleEngine();

19

}

20

21

@Override

22

public void onCreate() {

23

te();

24

}

25

26

@Override

27

public void onDestroy() {

28

roy();

29

}

30

31

public class SampleEngine extends Engine {

32

33

private LiveWallpaperPainting painting;

34

35

SampleEngine() {

36

SurfaceHolder holder = getSurfaceHolder();

37

painting = new LiveWallpaperPainting(holder,

38

getApplicationContext());

39

}

40

41

@Override

42

public void onCreate(SurfaceHolder surfaceHolder) {

43

te(surfaceHolder);

44

// register listeners and callbacks here

45

setTouchEventsEnabled(true);

46

}

47

48

@Override

49

public void onDestroy() {

50

roy();

51

// remove listeners and callbacks here

52

inting();

53

}

54

55

@Override

56

public void onVisibilityChanged(boolean visible) {

57

if (visible) {

58

// register listeners and callbacks here

59

Painting();

60

} else {

61

// remove listeners and callbacks here

62

ainting();

63

}

64

}

65

66

@Override

67

public void onSurfaceChanged(SurfaceHolder holder, int format,

68

int width, int height) {

69

aceChanged(holder, format, width, height);

70

faceSize(width, height);

71

}

72

73

@Override

74

public void onSurfaceCreated(SurfaceHolder holder) {

75

aceCreated(holder);

76

// start painting

77

();

78

}

79

80

@Override

81

public void onSurfaceDestroyed(SurfaceHolder holder) {

82

aceDestroyed(holder);

83

boolean retry = true;

84

inting();

85

while (retry) {

86

try {

87

();

88

retry = false;

89

} catch (InterruptedException e) {}

90

}

91

}

92

93

@Override

94

public void onOffsetsChanged(float xOffset, float yOffset,

95

float xStep, float yStep, int xPixels, int yPixels) {

96

}

97

98

@Override

99

public void onTouchEvent(MotionEvent event) {

100

hEvent(event);

101

hEvent(event);

102

}

103

104

}

105

}

当壁纸的显示、状态或大小变化是,会调用Engine的onCreate, onDestroy, onVisibilityChanged,onSurfaceChanged, onSurfaceCreated 和 onSurfaceDestroyed方法。有了这些方法,动态壁纸才能展现出动画效果。而通

过设置setTouchEventsEnabled(true),并且调用onTouchEvent(MotionEvent

event)方法,来激活触摸事件。

我们在绘画墙纸的时候,也会使用一个单独的绘画线程:

1

package llpaper;

2

3

import t;

4

import ;

5

import Event;

6

import eHolder;

7

8

/**

9

* Android Live Wallpaper painting thread Archetype

10

*

11

rel="nofollow">@author antoine vianey

12

* GPL v3 : /licenses/

13

*/

14

public class LiveWallpaperPainting extends Thread {

15

16

/** Reference to the View and the context */

17

private SurfaceHolder surfaceHolder;

18

private Context context;

19

20

/** State */

21

private boolean wait;

22

private boolean run;

23

24

/** Dimensions */

25

private int width;

26

private int height;

27

28

/** Time tracking */

29

private long previousTime;

30

private long currentTime;

31

32

public LiveWallpaperPainting(SurfaceHolder surfaceHolder,

33

Context context) {

34

// keep a reference of the context and the surface

35

// the context is needed if you want to inflate

36

// some resources from your livewallpaper .apk

37

eHolder = surfaceHolder;

38

t = context;

39

// don't animate until surface is created and displayed

40

= true;

41

}

42

43

/**

44

* Pauses the live wallpaper animation

45

*/

46

public void pausePainting() {

47

= true;

48

synchronized(this) {

49

();

50

}

51

}

52

53

/**

54

* Resume the live wallpaper animation

55

*/

56

public void resumePainting() {

57

= false;

58

synchronized(this) {

59

();

60

}

61

}

62

63

/**

64

* Stop the live wallpaper animation

65

*/

66

public void stopPainting() {

67

= false;

68

synchronized(this) {

69

();

70

}

71

}

72

73

@Override

74

public void run() {

75

= true;

76

Canvas c = null;

77

while (run) {

78

try {

79

c = nvas(null);

80

synchronized (eHolder) {

81

currentTime = tTimeMillis();

82

updatePhysics();

83

doDraw(c);

84

previousTime = currentTime;

85

}

86

} finally {

87

if (c != null) {

88

CanvasAndPost(c);

89

}

90

}

91

// pause if no need to animate

92

synchronized (this) {

93

if (wait) {

94

try {

95

wait();

96

} catch (Exception e) {}

97

}

98

}

99

}

100

}

101

102

/**

103

* Invoke when the surface dimension change

104

*/

105

public void setSurfaceSize(int width, int height) {

106

= width;

107

= height;

108

synchronized(this) {

109

();

110

}

111

}

112

113

/**

114

* Invoke while the screen is touched

115

*/

116

public void doTouchEvent(MotionEvent event) {

117

// handle the event here

118

// if there is something to animate

119

// then wake up

120

= false;

121

synchronized(this) {

122

notify();

123

}

124

}

125

126

/**

127

* Do the actual drawing stuff

128

*/

129

private void doDraw(Canvas canvas) {}

130

131

/**

132

* Update the animation, sprites or whatever.

133

* If there is nothing to animate set the wait

134

* attribute of the thread to true

135

*/

136

private void updatePhysics() {

137

// if nothing was updated :

138

// = true;

139

}

140

}

如果桌面壁纸是可见状态下,系统服务通知有新的东西,这个类会优先把它绘制在画布上。如果没有动画了,updatePhysics会通知线程去等待。通常SurfaceView在有两个画布交替绘制的时候,会在画布上绘制上一次......