I just started android programming this week and am curently working on a Live Wallpaper.
I have 2 Images, the Background Image (720x1280 png) and a slidebar (2276x290 png) that slides from right to left in an endles loop. my Problem is I only get it to slide with about 3-4fps with 1 px per Frame (on my actual phone, on AVD I get about 1/3fps ), wich is way to choppy for a live wallpaper. The code is working fine so far but way to slow.
It would be very nice if someone would know a way to get this "a lot" faster.
My code:
private class WEngine extends Engine {
private final Handler handler = new Handler();
private final Runnable drawRunner = new Runnable() {
@Override
public void run() {
draw();
}
};
private Paint paint = new Paint();
private int width;
int height;
private boolean visible = true;
int x = -1;
int x2 = 0;
int y = -1;
public WEngine() {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(WService.this);
handler.post(drawRunner);
}
@Override
public void onVisibilityChanged(boolean visible) {
this.visible = visible;
if (visible) {
handler.post(drawRunner);
} else {
handler.removeCallbacks(drawRunner);
}
}
@Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
this.visible = false;
handler.removeCallbacks(drawRunner);
}
@Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
this.width = width;
this.height = height;
super.onSurfaceChanged(holder, format, width, height);
}
private void draw() {
SurfaceHolder holder = getSurfaceHolder();
Canvas canvas = null;
Resources res = getResources();
Bitmap backgroundimg = BitmapFactory.decodeResource(res, R.drawable.background);
Bitmap slidebarimg = BitmapFactory.decodeResource(res, R.drawable.slidebar);
try {
canvas = holder.lockCanvas();
canvas.drawBitmap(backgroundimg, 0, 0, paint);
if (canvas != null) {
if (x<0 && y<0) {
x = 0;
y = Math.round(height / 2);
} else {
x -= 1;
}
if (x - width < -height * 1.778125) {
x2 -= 1;
}
if (x < -height * 1.778125) {
x = x2;
x2 = 0;
}
canvas.drawBitmap(slidebarimg, x, y, paint);
if (x2 < 0) {
canvas.drawBitmap(slidebarimg, x2, y, paint);
}
}
} finally {
if (canvas != null)
holder.unlockCanvasAndPost(canvas);
}
handler.removeCallbacks(drawRunner);
handler.postDelayed(drawRunner, 30);
}
}
Edit:
After changing the Images to jpg files I get about 6 fps, but thats still way to slow.
Edit 2:
I just figured out that hardwareaccceleration is not possible while using .lockCanvas() Is there another way to draw an image on livewallpaper (surfaceview) that provides hardwareaccceleration?
private void draw() {
...
Bitmap backgroundimg = BitmapFactory.decodeResource(res, R.drawable.background);
Bitmap slidebarimg = BitmapFactory.decodeResource(res, R.drawable.slidebar);
...
Don't do this. If you're decoding bitmaps in every frame, it's going to be slow. Very slow. It doesn't matter if you're hardware accelerated or not. Decode them once, and just draw them on each frame.