一般的壁纸设定,只需要在获取壁纸权限后,只需要getWallPagerManager对象来设定壁纸(静态)
与安卓应用的开发不同,动态壁纸的开发不需要传统的布局文件,也不要活动(activity)来管理,也是一种服务(WallPagerService)来维护着,里面自带有一个SurfaceHolder来进行图形的实时渲染,来达到壁纸动态的效果。
动态壁纸的设定可分为如下三步:
1 。创建一个 WallpagerService的子类
2。 创建一个Engine的子类,以后所有的绘制代码都写在这个类中。
3。 在wallpagerservice子类中的oncreate方法中,返回一个engine(我们自己创建的enginner子类)。
4。 在res目录下 创建一个xml文件夹,在其中编写一个xml文件,内容如下:
<?xml version="1.0" encoding="utf-8"?><wallpaper xmlns:android="http://schemas.android.com/apk/res/android" android:thumbnail="@drawable/icon"/>
<!-- 红色表示 在选择动态壁纸时 显示的缩略图-->
5。 在清单文件mainifest.xml 中进行service的配置,并在service节点内部添加绑定壁纸的权限,在节点下添加 意图过滤器和元数据,如下:
<applicationandroid:icon="@drawable/icon"android:label="@string/app_name"><!-- 配置实时壁纸Service --><service android:label="@string/app_name"android:name=".LiveWallpaper"android:permission="android.permission.BIND_WALLPAPER"><!-- 为实时壁纸配置intent-filter --><intent-filter><action android:name="android.service.wallpaper.WallpaperService" /></intent-filter><!-- 为实时壁纸配置meta-data --><meta-data android:name="android.service.wallpaper"android:resource="@xml/livewallpaper" /></service></application>
</manifest>
既然所有的核心代码都写在了Engine的子类中,所以必须的明白它的方法在什么时候回调用,下面给出我的一个测试DEMO
原理是: 背景是一个图通的bitmap 但是当手机在屏幕上面按下时,就会在按下的位置绘制出一个笑脸。
package com.xtu.wallpaper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Handler;
import android.service.wallpaper.WallpaperService;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
public class CuteWallPaper extends WallpaperService {
private Bitmap bg;
private Bitmap figer;
// 动态墙纸 需要提供一个渲染引擎
@Override
public Engine onCreateEngine() {
bg = BitmapFactory.decodeResource(getResources(), R.drawable.register);
figer = BitmapFactory.decodeResource(getResources(), R.drawable.one);
return new CuteEngine();
}
class CuteEngine extends Engine {
private Handler mHandler = new Handler();
private Paint paint = new Paint();
private float positionX = 10, positionY = 10;
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
onPaint();
}
};
// 创建引擎对象,这个方法 只会调用一次
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
paint.setColor(Color.RED);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
setTouchEventsEnabled(true);
}
@Override
public void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(mRunnable);
}
@Override
public void onOffsetsChanged(float xOffset, float yOffset,
float xOffsetStep, float yOffsetStep, int xPixelOffset,
int yPixelOffset) {
super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,
xPixelOffset, yPixelOffset);
onPaint();
}
//当壁纸的可见状态发生变化时,调用
@Override
public void onVisibilityChanged(boolean visible) {
super.onVisibilityChanged(visible);
if (visible) {
// 当壁纸为可见状态
onPaint();
} else {
// 当壁纸为不可见的时候
mHandler.removeCallbacks(mRunnable);
}
}
// 当手指接触到引擎时 调用
@Override
public void onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
positionX = event.getX();
positionY = event.getY();
}
super.onTouchEvent(event);
}
//画笔绘制的方法,绘制在surfaceholder上面, 注意surfaceholder.lockCanvas() 和 surfaceholder.unlockandposd()的调用(用try-catch包裹着) surfaceholder在绘制时候,由于锁定了,此时surfaceview的双//缓冲是不能用的。
private void onPaint() {
SurfaceHolder surfaceHolder = getSurfaceHolder();
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
canvas.drawBitmap(bg, new Matrix(), paint);
canvas.drawBitmap(figer, positionX, positionY, paint);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
mHandler.postDelayed(mRunnable, 80);
}
}
}