Saturday, August 27, 2011

How to create LIve Wallpaper in Android ?

1.1. Live Wallpapers

Live Wallpapers are animated, interactive backgrounds for the Android homescreen. A live wallpaper is similar to other Android applications and can use most of the same functionality.
To create a live wallpaper, you need to create a XML file which describes your wallpaper. This file should contain a description of the application and can contain a preview and a link to a preference activity which allow to customize the live wallpaper.
You also maintain a service which must extend the abstract class "WallpaperService". "WallpaperService"is the base class for all live wallpapers in the system. You must implement the method onCreateEngine() and return an object of type "Engine". This engine will handle the life cycle events, animations and drawings of the wallpaper. Here you find life cycle hooks, as for example onCreate(), onSurfaceCreated(), onVisibilityChanged(), onOffsetsChanged(), onTouchEvent() and onCommand() .
This service requires the permission "android.permission.BIND_WALLPAPER" and must be registered via an intent-filter to the action "android.service.wallpaper.WallpaperService".
The service returns in its method onCreateEngine() an instance "android.service.wallpaper.WallpaperService.Engine". This class is responsible for handling the Live Wallpaper.
You should also maintain in your "AndroidManifest.xml" that your application uses the feature "" in "AndroidManifest.xml". This will prevent that your wallpaper can be installed on devices which do not support live wallpapers.

2. Android Wallpaper Example

Create a new project "". Do not create an Activity.
Create the folder "/res/xml" and maintain the following file "mywallpaper.xml. This file contains a description of your wallpaper and a preview graphic. You can also maintain a link to an activity which allow to configure your wallpaper. This resource file will be linked to from the "AndroidManifest.xml". You could also include the "android:thumbnail attribute" which would point to a drawable which gives a smaller image of the running wallpaper.

<?xml version="1.0" encoding="UTF-8"?>
Change your "AndroidManifest.xml" to the following to define your service ""MyWallpaperService" and to maintain the uses-feature. 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=""
	package="" android:versionCode="1"
<application android:icon="@drawable/icon" android:label="@string/app_name">

<service android:name="MyWallpaperService" android:enabled="true"
android:label="Wallpaper Example ">
<action android:name="android.service.wallpaper.WallpaperService"></action>
	<meta-data android:name="android.service.wallpaper"
<activity android:label="@string/app_name" android:name=".MyPreferencesActivity"
	<uses-sdk android:minSdkVersion="10" />
	<uses-feature android:name=""

We create the class "MyPoint" to save the elements we have drawn. 

public class MyPoint {
	String text;
	private int x;
	private int y;

	public MyPoint(String text, int x, int y) {
		this.text = text;
		this.x = x;
		this.y = y;

Create a preference activity . Create the preference value files "prefs.xml" in the folder "res/xml".

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="">
	<CheckBoxPreference android:key="touch"
		android:title="Enable Touch"></CheckBoxPreference>
	<EditTextPreference android:key="numberOfCircles"
		android:title="Number of Circles"></EditTextPreference>
Create the following coding for your preference activity. 

import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import android.widget.Toast;

public class MyPreferencesActivity extends PreferenceActivity {
	protected void onCreate(Bundle savedInstanceState) {

	// We want to add a validator to the number of circles so that it only
	// accepts numbers
	Preference circlePreference = getPreferenceScreen().findPreference(

		// Add the validator

	 * Checks that a preference is a valid numerical value
	Preference.OnPreferenceChangeListener numberCheckListener = 
new OnPreferenceChangeListener() {

	public boolean onPreferenceChange(Preference preference,
Object newValue) {
		// Check that the string is an integer
		if (newValue != null && newValue.toString().length() > 0
				&& newValue.toString().matches("\\d*")) {
			return true;
		// If now create a message to the user
		Toast.makeText(MyPreferencesActivity.this, "Invalid Input",
			return false;

Create the following coding for the Wallpaper Service. 

import java.util.ArrayList;
import java.util.List;

import android.content.SharedPreferences;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.service.wallpaper.WallpaperService;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class MyWallpaperService extends WallpaperService {

	public Engine onCreateEngine() {
		return new MyWallpaperEngine();

	private class MyWallpaperEngine extends Engine {
		private final Handler handler = new Handler();
		private final Runnable drawRunner = new Runnable() {
			public void run() {

		private List<MyPoint> circles;
		private Paint paint = new Paint();
		private int width;
		int height;
		private boolean visible = true;
		private int maxNumber;
		private boolean touchEnabled;

		public MyWallpaperEngine() {
	SharedPreferences prefs = PreferenceManager
		maxNumber = Integer
			.valueOf(prefs.getString("numberOfCircles", "4"));
			touchEnabled = prefs.getBoolean("touch", false);
			circles = new ArrayList<MyPoint>();

		public void onVisibilityChanged(boolean visible) {
			this.visible = visible;
			if (visible) {;
			} else {


		public void onSurfaceDestroyed(SurfaceHolder holder) {
			this.visible = false;

		public void onSurfaceChanged(SurfaceHolder holder, int format,
				int width, int height) {
			this.width = width;
			this.height = height;
			super.onSurfaceChanged(holder, format, width, height);

		public void onTouchEvent(MotionEvent event) {
			if (touchEnabled) {

				float x = event.getX();
				float y = event.getY();
				SurfaceHolder holder = getSurfaceHolder();
				Canvas canvas = null;
				try {
					canvas = holder.lockCanvas();
			if (canvas != null) {
				circles.add(new MyPoint(
				String.valueOf(circles.size() + 1), x, y));
				drawCircles(canvas, circles);
			} finally {
				if (canvas != null)
		private void draw() {
	SurfaceHolder holder = getSurfaceHolder();
	Canvas canvas = null;
		try {
			canvas = holder.lockCanvas();
			if (canvas != null) {
				if (circles.size() >= maxNumber) {
			int x = (int) (width * Math.random());
			int y = (int) (height * Math.random());
	circles.add(new MyPoint(String.valueOf(circles.size() + 1),
						x, y));
					drawCircles(canvas, circles);
			} finally {
				if (canvas != null)
			if (visible) {
				handler.postDelayed(drawRunner, 5000);

		// Surface view requires that all elements are drawn completely
		private void drawCircles(Canvas canvas, List<MyPoint> circles) {
			for (MyPoint point : circles) {
			canvas.drawCircle(point.x, point.y, 20.0f, paint);
If you start your application and set this wallpaper as
background your emulator should similar to the following. If you have
Touch enabled via the preferences you can click on the screen to
remove the existing circles, also via the settings you can define the
number of circles which should be displayed.

No comments:

Post a Comment