Android Live Wallpaper Tutorial | Simple Easy Steps

In this blog about Android Live Wallpaper Tutorial, learn how to build your own android live wallpaper in simple steps.

Need some career advice or prepping for an Android developer interview? Hit me up on Topmate.io, and let's chat!

The Android Live Wallpapers are the way to redesign your mobile background into something amazing animated GIF using different effects and motions.

Many developers are making good money by creating android live wallpapers. Henceforth here is Android Live Wallpaper tutorial for you to build your own Live wallpaper and start earning today as a developer!

In this tutorial for beginners, you’ll learn how by using Android Studio 3.0 and by having basic knowledge of Java, we will teach you to build your own Live wallpaper for Android which you may later publish in the Google Play Store.

Android Live Wallpaper Tutorial

What we will do

To build an Android Live Wallpaper app, the first thing we will need to do is to declare the feature that the app will use (i.e, live wallpaper) in the Manifest file (we will show in the tutorial below).

Also, we need to declare permission that the app must have in order to launch the service or bind to it.

Once this is done, we will create a java file named ‘GIFWallpapaerService’ (which is a service as declared in AndroidManifest.xml). In this file we will create GIFWallpaperService which extends WallpaperService.Engine.

So now Android gets to know when and what to display as GIF wallpaper and when to hide or destroy it also for effective use of memory and mobile battery.

However such services requir android.permission.BIND_WALLPAPER and must be registered via an <intent-filter> for the android.service.wallpaper.WallpaperService action in AndroidManifest.xml.

Here is a sneak peek at what you’ll build today. (Disclaimer: You may not like the wallpaper but you can use any other gif file)

Android live wallpaper tutorial

Getting Started

Create a new project with an empty activity in Android Studio and head over to AndroidManifest.xml file.

Open AndroidManifest.xml from the Manifest folder and declare the feature used by the app.

<uses-feature
    android:name="android.software.live_wallpaper"
    android:required="true"></uses-feature>

Now create service tag after tag, here we will declare service for our app and set required permissions, android.permission.BIND_WALLPAPER and use for the android.service.wallpaper.WallpaperService action.

<service
    android:name=".GIFWallpaperService"
    android:enabled="true"
    android:label="DayTime LWP"
    android:permission="android.permission.BIND_WALLPAPER">
    <intent-filter>
        <action android:name="android.service.wallpaper.WallpaperService" />
    </intent-filter>

Also, we will have some meta-data here, its an additional information that will be used to declare App name and set icon in Live wallpaper settings of our Android app.

<meta-data
    android:name="android.service.wallpaper"
    android:resource="@xml/wallpaper"></meta-data>

Here is what our AndroidManifest.xml file should be after coding:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.androiddvlpr.daytime">

    <uses-feature
        android:name="android.software.live_wallpaper"
        android:required="true"></uses-feature>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <service
            android:name=".GIFWallpaperService"
            android:enabled="true"
            android:label="DayTime LWP"
            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/wallpaper"></meta-data>
        </service>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Now in Project window (See on the Left side of Android Studio v3.x), go to java folder (inside app > java), right click and create a new java file with name, ‘GIFWallpaperService.java’.

Once the file is created, extend GIFWallpaperService class to WallpaperService.

public class GIFWallpaperService extends WallpaperService {

 }

Interested in adding fragments to your wallpaper app? See here.

A wallpaper service may have multiple instances running (for example as a real wallpaper and as a preview), each of which is represented by its own Engine instance.

Therefore we will implement onCreateEngine() to return concrete Engine implementation.

@Override
public WallpaperService.Engine onCreateEngine() {
    try {
        Movie movie = Movie.decodeStream(
                getResources().getAssets().open("daytime.gif"));

        return new GIFWallpaperEngine(movie);
    }catch(IOException e){
        Log.d("GIF", "Could not load asset");
        return null;
    }
}

In the code above we have implemented an onCreateEngine() and declared our GIF Wallpaper (which is ‘daytime.gif’, resources will be made available in the links below after the blog!).

The try { } catch { } is a Java code in which try block is used to enclose the code that might throw an exception. It must be used within the method.

Now create a private GIFWallpaperEngine which extends WallpaperService.Engine that will be used to display the Graphic component movie, i.e, daytime.gif.

 public GIFWallpaperEngine(Movie movie) {
        //A Handler allows you to send and process Message and Runnable objects associated
        //with a thread's MessageQueue
        this.movie = movie;
        handler = new Handler();
                }

In the code above we have used the Handler to help run the GIF movie and using the surfaceholder() as shown below we are setting GIF as wallpaper.

public void onCreate(SurfaceHolder surfaceHolder) {
    /** Abstract interface to someone holding a display surface. Allows you to control
     the surface size and format, edit the pixels in the surface, and monitor changes
     to the surface. This interface is typically available through the SurfaceView class.
     **/
    super.onCreate(surfaceHolder);
    this.holder = surfaceHolder;

}

Now the Runnable interface below will help us to run the draw method in the thread.

private Runnable drawGIF = new Runnable() {
    public void run() {
        draw();
    }
};

In this example to draw the GIF wallpaper in the background, we need 3 basic components.

  1. The holder (declared above) to hold the pixels
  2. A Canvas to host the draw calls (writing into the holder)
  3. A drawing primitive (i.e, the DayTime GIF in this example).

Add animation to your app and drive user engagement, click here. to know more

Well having said we have coded the draw method below:

private void draw() {
    if (visible) {
        Canvas canvas = holder.lockCanvas();
        canvas.save();
        // Adjust size and position so that
        // the image looks good on your screen
        canvas.scale(1f, 1f);
        movie.draw(canvas, 0, 0);
        canvas.restore();
        holder.unlockCanvasAndPost(canvas);
        movie.setTime((int) (System.currentTimeMillis() % movie.duration()));

        handler.removeCallbacks(drawGIF);
        handler.postDelayed(drawGIF, frameDuration);
    }
}

You must have heard that Live Wallpapers consume lots of memory and battery. However, you wouldn’t like your user to uninstall the app because of this.

Therefore we will use the onVisibility() method over here to prevent battery and memory drain which will disable wallpaper when the view is changed and wallpaper is no longer visible!

public void onVisibilityChanged(boolean visible) {
    //Called when the visibility of the view or an ancestor of the view has changed.
    this.visible = visible;
    if (visible) {
        handler.post(drawGIF);
    } else {
        handler.removeCallbacks(drawGIF);
    }
}

Finally we need the destroy method to destroy our wallpaper.

@Override
public void onDestroy() {
    super.onDestroy();
    handler.removeCallbacks(drawGIF);
}

Here is the complete code from GIFWallpaperService.java file.

package com.androiddvlpr.daytime;

import android.graphics.Canvas;
import android.graphics.Movie;
import android.os.Handler;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.SurfaceHolder;

import java.io.IOException;

public class GIFWallpaperService extends WallpaperService {

    @Override
    public WallpaperService.Engine onCreateEngine() {
        try {
            Movie movie = Movie.decodeStream(
                    getResources().getAssets().open("daytime.gif"));

            return new GIFWallpaperEngine(movie);
        }catch(IOException e){
            Log.d("GIF", "Could not load asset");
            return null;
        }
    }




    private class GIFWallpaperEngine extends WallpaperService.Engine {

        private final int frameDuration = 20;
        private SurfaceHolder holder;
        private Movie movie;
        private boolean visible;
        private Handler handler;

        public GIFWallpaperEngine(Movie movie) {
            //A Handler allows you to send and process Message and Runnable objects associated
            //with a thread's MessageQueue
            this.movie = movie;
            handler = new Handler();
                    }

        @Override
        public void onCreate(SurfaceHolder surfaceHolder) {
            /** Abstract interface to someone holding a display surface. Allows you to control
             the surface size and format, edit the pixels in the surface, and monitor changes
             to the surface. This interface is typically available through the SurfaceView class.
             **/
            super.onCreate(surfaceHolder);
            this.holder = surfaceHolder;

        }

        //The Runnable interface should be implemented by any class whose instances are intended to
        // be executed by a thread. The class must define a method of no arguments called run.
        private Runnable drawGIF = new Runnable() {
            public void run() {
                draw();
            }
        };


        private void draw() {
            if (visible) {
                Canvas canvas = holder.lockCanvas();
                canvas.save();
                // Adjust size and position so that
                // the image looks good on your screen
                canvas.scale(1f, 1f);
                movie.draw(canvas, 0, 0);
                canvas.restore();
                holder.unlockCanvasAndPost(canvas);
                movie.setTime((int) (System.currentTimeMillis() % movie.duration()));

                handler.removeCallbacks(drawGIF);
                handler.postDelayed(drawGIF, frameDuration);
            }
        }

        @Override
        public void onVisibilityChanged(boolean visible) {
            //Called when the visibility of the view or an ancestor of the view has changed.
            this.visible = visible;
            if (visible) {
                handler.post(drawGIF);
            } else {
                handler.removeCallbacks(drawGIF);
            }
        }


        @Override
        public void onDestroy() {
            super.onDestroy();
            handler.removeCallbacks(drawGIF);
        }
    }
}

17. Now go to MainActivity.java and set the Intent in onClick() method to set wallpaper when button in main_activity.xml file is clicked!

public void onClick(View view)
{
    Intent intent = new Intent(
            WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
    intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
            new ComponentName(this, GIFWallpaperService.class));
    startActivity(intent);
}

Here is the complete code from MainActivity.java file.

package com.androiddvlpr.daytime;

import android.app.WallpaperManager;
import android.content.ComponentName;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onClick(View view)
    {
        Intent intent = new Intent(
                WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
        intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
                new ComponentName(this, GIFWallpaperService.class));
        startActivity(intent);
    }
}

Now go to Project View (on the Left side window), inside res folder create Android resource directory named, ‘xml’, inside this directory create a resource file named ‘wallpaper.xml’

<?xml version="1.0" encoding="utf-8"?>
<wallpaper
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="DayTime LWP"
    android:thumbnail="@drawable/icon">
</wallpaper>

Create Assets folder in app folder (Do this in Explorer) and copy ‘daytime.gif’ file here and ‘icon.png’ inside the drawable folder (inside res).

Learn if the user is online while running your app, click here to know more.

Run and test your app, if in case you face some issue let us know in comments section below.