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
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
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)
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.
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
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.
- The holder (declared above) to hold the pixels
- A Canvas to host the draw calls (writing into the holder)
- 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.