I already asked this, but it was migrated to android.stackexchange.com and closed there as offtopic. So here we go again:
I made a simple live wallpaper. On the preview I can see it but if I try to set it as my live wallpaper Android keeps the old wallpaper there.
Any ideas?
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.localfotos"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />
<uses-feature android:name="android.software.live_wallpaper" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<service android:name=".MyWallpaperService"
android:label="@string/app_name"
android:icon="@drawable/icon">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/livewallpaper" />
</service>
</application>
</manifest>
livewallpaper.xml
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
/>
MyWallpaperService.java
package com.localfotos;
import android.service.wallpaper.WallpaperService;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
public class MyWallpaperService extends WallpaperService {
@Override
public Engine onCreateEngine() {
return new MyEngine();
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
public class MyEngine extends Engine {
private MyWallpaperPainting painting;
MyEngine() {
SurfaceHolder holder = getSurfaceHolder();
painting = new MyWallpaperPainting(holder,
getApplicationContext());
}
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
// register listeners and callbacks here
setTouchEventsEnabled(true);
}
@Override
public void onDestroy() {
super.onDestroy();
// remove listeners and callbacks here
painting.stopPainting();
}
@Override
public void onVisibilityChanged(boolean visible) {
if (visible) {
// register listeners and callbacks here
painting.resumePainting();
} else {
// remove listeners and callbacks here
painting.pausePainting();
}
}
@Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
painting.setSurfaceSize(width, height);
}
@Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
// start painting
painting.start();
}
@Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
boolean retry = true;
painting.stopPainting();
while (retry) {
try {
painting.join();
retry = false;
} catch (InterruptedException e) {}
}
}
@Override
public void onOffsetsChanged(float xOffset, float yOffset,
float xStep, float yStep, int xPixels, int yPixels) {
}
@Override
public void onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
painting.doTouchEvent(event);
}
}
}
MyWallpaperPainting.java
package com.localfotos;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
public class MyWallpaperPainting extends Thread {
private static final String TAG = "MyWallpaperPainting";
/** Reference to the View and the context */
private SurfaceHolder surfaceHolder;
private Context context;
/** State */
private boolean wait;
private boolean run;
/** Dimensions */
private 开发者_如何学Cint width;
private int height;
/** Time tracking */
private long previousTime;
private long currentTime;
public MyWallpaperPainting(SurfaceHolder surfaceHolder, Context context) {
// keep a reference of the context and the surface
// the context is needed 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 wallpaper animation
*/
public void pausePainting() {
this.wait = true;
synchronized(this) {
this.notify();
}
}
/**
* Resume the live wallpaper animation
*/
public void resumePainting() {
this.wait = false;
synchronized(this) {
this.notify();
}
}
/**
* Stop the live wallpaper animation
*/
public void stopPainting() {
this.run = false;
synchronized(this) {
this.notify();
}
}
@Override
public void run() {
this.run = true;
Canvas c = null;
while (run) {
try {
c = this.surfaceHolder.lockCanvas(null);
synchronized (this.surfaceHolder) {
currentTime = System.currentTimeMillis();
updatePhysics();
doDraw(c);
previousTime = currentTime;
}
} finally {
if (c != null) {
this.surfaceHolder.unlockCanvasAndPost(c);
}
}
// pause if no need to animate
synchronized (this) {
if (wait) {
try {
wait();
} catch (Exception e) {}
}
}
synchronized (this){
try{
wait(1000);
}catch (InterruptedException e){}
}
}
}
/**
* Invoke when the surface dimension change
*/
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(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 doDraw(Canvas canvas) {
/**
* Update the animation, sprites or whatever.
* If there is nothing to animate set the wait
* attribute of the thread to true
*/
Paint mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(0xFFFFFF00);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(3);
Path path = new Path();
path.lineTo(10, 100);
canvas.drawColor(0xFFFFFF00);
Log.d(TAG, "doDraw");
}
private void updatePhysics() {
// if nothing was updated :
// this.wait = true;
}
}
Your manifest is missing the BIND_WALLPAPER permission. See the Cube example in the SDK.
android:permission="android.permission.BIND_WALLPAPER">
精彩评论