原文地址:
http://blog.csdn.net/oldmtn/article/details/9177123
学习到的知识总结:
先贴上我的AndroidManifest.xml的内容。
-
<?
xml
version
=
“1.0”
encoding
=
“utf-8”
?>
-
<
manifest
xmlns:android
=
“http://schemas.android.com/apk/res/android”
-
package
=
“com.example.testlivewallpaper”
-
android:versionCode
=
“1”
-
android:versionName
=
“1.0”
>
-
-
<
uses-sdk
-
android:minSdkVersion
=
“8”
-
android:targetSdkVersion
=
“16”
/>
-
-
<
application
-
android:allowBackup
=
“true”
-
android:icon
=
“@drawable/ic_launcher”
-
android:label
=
“@string/app_name”
-
android:theme
=
“@style/AppTheme”
>
-
<
service
-
android:name
=
“com.example.testlivewallpaper.Wallpaper”
-
android:label
=
“@string/service_name”
-
android:permission
=
“android.permission.BIND_WALLPAPER”
>
-
<
intent-filter
>
-
<
action
android:name
=
“android.service.wallpaper.WallpaperService”
/>
-
</
intent-filter
>
-
-
<
meta-data
-
android:name
=
“android.service.wallpaper”
-
android:resource
=
“@xml/wallpaper”
/>
-
</
service
>
-
</
application
>
-
-
</
manifest
>
1. 自己编写的动态壁纸相关的类必须从WallpaperService类派生
。
2. 需要自己提供一个xml描述的wallpaper,该wallpaper作为你选择动态壁纸时候的预览图片。
我这里为:
-
<
meta-data
-
android:name
=
“android.service.wallpaper”
-
android:resource
=
“@xml/wallpaper”
/>
其中wallpaper内容为:
-
<?
xml
version
=
“1.0”
encoding
=
“utf-8”
?>
-
<
wallpaper
xmlns:android
=
“http://schemas.android.com/apk/res/android”
-
android:author
=
“@+string/author”
-
android:description
=
“@string/description”
-
android:thumbnail
=
“@drawable/cold”
/>
3.因为动态壁纸是一种服务,是给系统的壁纸管理程序调用的,所以可以不需要Activity。
当然你也可以添加一个Activity,然后给出列表,提供多个LiveWallpaper供用户选择。
///
参考链接1:
地址:http://blog.csdn.net/blogercn/article/details/7407647
安卓从2.1开始支持动态墙纸编程,英文名字叫live wallpaper 。自己编写的动态壁纸必须从WallpaperService类派生,并且在重载其方法onCreateEngine里实现自己的动态效果。其代码如下,SimpleWallpaperEngine是我们基于Engine类派生的类:
public Engine onCreateEngine() {
return new SimpleWallpaperEngine();
}
上面retun返回的代码就是我们用Engine类的派生类创建的对象,其实现过程使用surfaceview更新。所以要学习动态墙纸编程,最好是已经熟练的掌握了surfaceview使用技巧。在Engine类里,有很多方法,我们需要重载以下三个方法,
1.创建壁纸
public void onCreate(SurfaceHoldersurfaceHolder){…}
2.释放壁纸
public void onDestroy(){…}
3.VisibilityChanged是用来设置当前动态壁纸可见时显示动画。当其不可见时,壁纸会停止运行,不显示动画,代码如下:
[java]
view plain
copy
-
@Override
-
public
void
onVisibilityChanged(
boolean
visible) {
-
canDraw = visible;
-
if
(visible) {
-
drawDroid();
// 自己的绘屏函数
-
}
else
{
-
handler.removeCallbacks(drawRequest);
// 不可见时,移除回调
-
}
-
}
drawDroid
是我写的一个简单的根据随机数画线的函数,代码如下:
[java]
view plain
copy
-
private
void
drawDroid() {
-
final
SurfaceHolder holder = getSurfaceHolder();
-
Canvas canvas =
null
;
-
try
{
-
canvas = holder.lockCanvas();
-
if
(canvas !=
null
) {
-
paint.setColor(Color.BLUE);
-
paint.setStrokeWidth(
10
);
-
paint.setStyle(Style.STROKE);
-
nx = (
int
) (rand.nextFloat() * virtualWidth);
-
ny = (
int
) (rand.nextFloat() * virtualHeight);
-
m_path.lineTo(nx, ny);
-
canvas.drawPath(m_path, paint);
-
}
-
}
finally
{
-
if
(canvas !=
null
) {
-
holder.unlockCanvasAndPost(canvas);
-
}
-
}
-
handler.removeCallbacks(drawRequest);
-
if
(canDraw) {
-
handler.postDelayed(drawRequest,
33
);
-
}
-
}
由于动画是使用surfacewive实现的,所以我们也要重载surfacewive的方法:
1. 建立
onSurfaceCreated
2. 释放
onSurfaceDestroyed
3. 大小变化,横竖屏操作,与用户交互时修改
onSurfaceChanged
如果需要添加用户交互,需要重载
public voidonTouchEvent(MotionEvent event)
surfacewive使用线程更新屏幕,我们可以使用Runnable接口创建一个线程,把我们的绘画函数放进去,并把他添加到窗口handler回调里,代码如下:
[java]
view plain
copy
-
private
final
Runnable drawRequest =
new
Runnable() {
-
@Override
-
public
void
run() {
-
try
{
-
Thread.sleep(
1000
);
-
drawDroid();
-
}
catch
(InterruptedException e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
}
-
};
完整的代码如下“:
[java]
view plain
copy
-
package
com.androidbook.simplelivewallpaper;
-
-
import
java.util.Random;
-
import
android.graphics.Canvas;
-
import
android.graphics.Color;
-
import
android.graphics.Paint;
-
import
android.graphics.Path;
-
import
android.graphics.Paint.Style;
-
import
android.os.Handler;
-
import
android.service.wallpaper.WallpaperService;
-
import
android.view.MotionEvent;
-
import
android.view.SurfaceHolder;
-
-
public
class
SimpleDroidWallpaper
extends
WallpaperService {
-
// private static final String DEBUG_TAG = “SimpleDroidWallpaper”;
-
private
final
Handler handler =
new
Handler();
-
-
@Override
-
public
Engine onCreateEngine() {
-
return
new
SimpleWallpaperEngine();
-
}
-
-
class
SimpleWallpaperEngine
extends
WallpaperService.Engine {
-
-
boolean
canDraw =
true
;
-
private
int
virtualHeight;
-
private
int
virtualWidth;
-
Paint paint =
new
Paint();
-
Path m_path =
new
Path();
-
volatile
int
ox =
0
, oy =
0
, nx =
100
, ny =
200
;
-
final
Random rand =
new
Random();
-
-
private
final
Runnable drawRequest =
new
Runnable() {
-
@Override
-
public
void
run() {
-
try
{
-
Thread.sleep(
1000
);
-
drawDroid();
-
}
catch
(InterruptedException e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
}
-
};
-
-
public
SimpleWallpaperEngine() {
-
m_path.lineTo(ox, oy);
-
}
-
-
@Override
-
public
void
onCreate(SurfaceHolder surfaceHolder) {
-
super
.onCreate(surfaceHolder);
-
// When touch is enable, all MotionEvents are passed, even those
-
// handled by other widgets
-
setTouchEventsEnabled(
true
);
-
virtualHeight = getDesiredMinimumHeight();
-
virtualWidth = getDesiredMinimumWidth();
-
}
-
-
@Override
-
public
void
onDestroy() {
-
super
.onDestroy();
-
handler.removeCallbacks(drawRequest);
-
}
-
-
@Override
-
public
void
onVisibilityChanged(
boolean
visible) {
-
canDraw = visible;
-
if
(visible) {
-
drawDroid();
// 自己的绘屏函数
-
}
else
{
-
handler.removeCallbacks(drawRequest);
// 不可见时,移除回调
-
}
-
}
-
-
@Override
-
public
void
onOffsetsChanged(
float
xOffset,
float
yOffset,
-
float
xOffsetStep,
float
yOffsetStep,
int
xPixelOffset,
-
int
yPixelOffset) {
-
super
.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,
-
xPixelOffset, yPixelOffset);
-
}
-
-
@Override
-
public
void
onSurfaceCreated(SurfaceHolder holder) {
-
super
.onSurfaceCreated(holder);
-
}
-
-
@Override
-
public
void
onSurfaceChanged(SurfaceHolder holder,
int
format,
-
int
width,
int
height) {
-
super
.onSurfaceChanged(holder, format, width, height);
-
-
drawDroid();
-
}
-
-
@Override
-
public
void
onSurfaceDestroyed(SurfaceHolder holder) {
-
super
.onSurfaceDestroyed(holder);
-
canDraw =
false
;
-
handler.removeCallbacks(drawRequest);
-
}
-
-
private
void
drawDroid() {
-
final
SurfaceHolder holder = getSurfaceHolder();
-
Canvas canvas =
null
;
-
try
{
-
canvas = holder.lockCanvas();
-
if
(canvas !=
null
) {
-
paint.setColor(Color.BLUE);
-
paint.setStrokeWidth(
10
);
-
paint.setStyle(Style.STROKE);
-
nx = (
int
) (rand.nextFloat() * virtualWidth);
-
ny = (
int
) (rand.nextFloat() * virtualHeight);
-
m_path.lineTo(nx, ny);
-
canvas.drawPath(m_path, paint);
-
}
-
}
finally
{
-
if
(canvas !=
null
) {
-
holder.unlockCanvasAndPost(canvas);
-
}
-
}
-
handler.removeCallbacks(drawRequest);
-
if
(canDraw) {
-
handler.postDelayed(drawRequest,
33
);
-
}
-
}
-
-
@Override
-
public
void
onTouchEvent(MotionEvent event) {
-
/* 添加触屏效果 */
-
super
.onTouchEvent(event);
-
}
-
}
-
}
完整的XML文件如下:
<?xml version=”1.0″ encoding=”utf-8″?>
<manifest
xmlns:
Android
=”http://schemas.android.com/apk/res/android”
package=”com.androidbook.simplelivewallpaper”
android:versionCode=”1″
android:versionName=”1.0″>
<application
android:icon=”@drawable/icon”
android:label=”@string/app_name”
android:debuggable=”true”>
<activity
android:name=”.SimpleLiveWallpaperMenuActivity”
android:label=”@string/app_name”>
<intent-filter>
<action
android:name=”android.intent.action.MAIN” />
<category
android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
<service
android:label=”@string/wallpaper_name”
android:name=”SimpleDroidWallpaper”
android:permission=”android.permission.BIND_WALLPAPER”>
<intent-filter>
<action
android:name=”android.service.wallpaper.WallpaperService” />
</intent-filter>
<meta-data
android:name=”android.service.wallpaper”
android:resource=”@xml/droid_wallpaper” />
</service>
</application>
<uses-sdk
android:minSdkVersion=”7″
android:targetSdkVersion=”8″ />
<uses-feature
android:name=”android.software.live_wallpaper” />
</manifest>
其实我们这里创建的墙纸不需要Activity类,只是一种服务,是被墙纸管理程序调用的,所以对于eclipse生成的工程,你可以去掉XML中有关Activity窗口的声明,同时资源文件里你也可以去掉layout\main.xml文件和源代码文件夹里的Activit文件。当然,我们的墙纸如果支持自定义设置,那你也是需要Activit,那时你需要定义一个Activit供墙纸设置程序调用,以修改自定义墙纸默认设置。需要注意的是,设置文件需要在我们在/res/文件夹中新建一个名为xml的文件夹,名为livewallpaper.xml,内容为如下:
[html]
view plain
copy
-
<?
xml
version
=
“1.0”
encoding
=
“utf-8”
?>
-
<
wallpaper
xmlns:android
=
“http://schemas.android.com/apk/res/android”
-
android:settingsActivity
=
“ca.jvsh.livewallpaper.LiveWallpaperSettings”
-
android:thumbnail
=
“@drawable/icon”
/>
然后把设置的值引入到你自己的墙纸类中调用。墙纸设置类一般会派生于PreferenceActivity,以在作用户操作后保存设置内容!
