Live Wallpaper, ou Papel de Parede Animado conforme a traducao, foram introduzidos na versao 2.1 (API 7) do Android. Como o nome sugere, ele nada mais e do que um fundo que se mexe. Mas ao contrario do que se imagina ele pode ser muito mais poderoso do que se imagina. E possivel fazer praticamente qualquer coisa que um aplicativo comum faz, inclusive interagir com toques do usuario.Mas, como dizia Tio Ben, com grandes poderes vem grandes responsabilidades. Lembre-se que o Live Wallpaper ira rodar boa parte do tempo, entao este nao deve fazer muitas operacoes pesadas para nao consumir muitos dados ou energia do aparelho.O exemplo mostrado aqui pode ser baixado clicando aqui.O Live Wallpaper nao passa de um Service que rodara infinitamente enquanto voce manter o Live Wallpaper. Entao vamos comecar definindo isso no AndroidManifest:<uses-feature android:name="android.software.live_wallpaper" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <service android:label="@string/app_name" android:name=".ExempleWallpaper" 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/wall" /> </service> </application>Note o uses-feature que e necessario e a definicao do Service. Assim como na definicao de um app widget aqui tambem definimos um meta-data que esta em xml/wall. Vamos cria-lo:<?xml version="1.0" encoding="utf-8"?><wallpaper xmlns:android="http://schemas.android.com/apk/res/android"/>So isso. Dentro dessa tag poderiamos definir android:settingsActivity que seria a Activity de configuracao, semelhante a Activity de configuracao do app widget, mas por enquanto nao iremos fazer isso. A seguir vamos criar nosso service ExempleWallpaper propriamente dito, como definido no Manifest:package com.gdacarv.tutoriandroid.livewallpaper;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.os.Handler;import android.service.wallpaper.WallpaperService;import android.view.MotionEvent;import android.view.SurfaceHolder;public class ExempleWallpaper extends WallpaperService { // Handler utilizado para redesenhar a tela private final Handler mHandler = new Handler(); @Override public Engine onCreateEngine() { return new ExempleEngine(); } class ExempleEngine extends Engine { // Frames Por Segundo private static final int FPS = 30; // Velocidade da animacao private static final float SPEED = 3; // Utilizado quando a tela e movida private float mOffset; // Registra toques na tela private float mTouchX = -1; private float mTouchY = -1; private int height, width; private Bitmap mBitmap; private float x,y; private int dirHorizontal = 1, dirVertical = 1; private final Runnable mDrawCube = new Runnable() { public void run() { drawFrame(); } }; private boolean mVisible; @Override public void onCreate(SurfaceHolder surfaceHolder) { super.onCreate(surfaceHolder); mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); //setTouchEventsEnabled(true); // Ativa eventos de toque (Atualmente desativados por default) } @Override public void onDestroy() { super.onDestroy(); mHandler.removeCallbacks(mDrawCube); } @Override public void onVisibilityChanged(boolean visible) { mVisible = visible; if (visible) { drawFrame(); } else { mHandler.removeCallbacks(mDrawCube); } } @Override public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { super.onSurfaceChanged(holder, format, width, height); // Salva largura e altura da tela this.width = width; this.height = height; } @Override public void onSurfaceCreated(SurfaceHolder holder) { super.onSurfaceCreated(holder); } @Override public void onSurfaceDestroyed(SurfaceHolder holder) { super.onSurfaceDestroyed(holder); mVisible = false; mHandler.removeCallbacks(mDrawCube); } @Override public void onOffsetsChanged(float xOffset, float yOffset, float xStep, float yStep, int xPixels, int yPixels) { mOffset = xOffset; } @Override public void onTouchEvent(MotionEvent event) { // Guarda toques na tela. So e executado se comando setTouchEventsEnabled(true) for executado previamente. if (event.getAction() == MotionEvent.ACTION_MOVE) { mTouchX = event.getX(); mTouchY = event.getY(); } else { mTouchX = -1; mTouchY