Video icon 64
Learn to Code. Start your free trial today.
Advertisement

Creating Live Wallpapers on Android

Student iconAre you a student? Get a yearly Tuts+ subscription for $45 →

Android has a number of personalization features to help users customize many aspects of their device user experience. One of these features is live wallpaper. Live wallpapers don’t remain as static background images but instead have interactive features. Learn how to create a live wallpaper in this tutorial!

A live wallpaper, on Android, is normally used as a background on the home screen that animates or changes over time in some way. If you have an Android device, you've probably seen a couple of the built-in live wallpapers, like the one where leaves appear to fall into rippling water.

As a developer, you can create and publish live wallpapers. The process is not particularly difficult. Making a live wallpaper that is fascinating and desirable while not draining the user’s device battery is, however, something of a challenge. In this tutorial, we'll walk you through the process of creating a live wallpaper that behaves. :)


Step 0: Getting Started

Recently, we showed you how to use RenderScript. The end result of that tutorial was a simple snow-falling effect. Let's turn that effect into a live wallpaper.

The open source code for this tutorial is available for download. We recommend using it to follow along. The code listings in this tutorial do not include the entire contents of each file and do not cover project setup or code covered in previous tutorials.


Step 1: Service or Engine?

You could say that a live wallpaper is just a service. After all, to create a live wallpaper, you simply extend from the WallpaperService class and implement a single method, often with just a single line of code, and then add your service definition to the manifest file.

Let's see what this looks like. Here's the WallpaperService:

public class FallingSnowWallpaperService extends WallpaperService {
    @Override
    public Engine onCreateEngine() {
        return new FallingSnowWallpaperEngine();
    }
}

And you're done! Okay, not really. The bulk of the work of a live wallpaper takes place in a WallpaperService.Engine implementation. This is where you can respond to callbacks such as onSurfaceChanged() and onSurfaceCreated(). Sound familiar? These are very similar to the callbacks you may have seen when implementing a View or other Surface-based object.

And now the reality of live wallpapers is revealed: When implementing the WallpaperService.Engine, all you're doing is drawing to a provided Surface (via a SurfaceHolder). It is almost that simple. Before we get to the implementation of the WallpaperService.Engine, let's look at some of the other configuration aspects.


Step 2: Defining the Wallpaper

Since a live wallpaper is a service, you must register the service in your manifest file. The service registration might look something like this:

        <service
            android:name="com.mamlambo.fallingsnow.FallingSnowWallpaperService"
            android:label="@string/app_name"
            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/fallingsnow_wp" />
        </service>

There are a couple of things to note here. First, using this service requires the BIND_WALLPAPER permission (i.e. another app using this wallpaper would require the BIND_WALLPAPER permission as a uses-permission entry in their manifest). Second, the intent filter is a string similar to the base class. Finally, the meta-data points to an XML file. This XML file, defined by the developer, provides some additional wallpaper configuration. Here's our XML file for the live wallpaper settings called fallingsnow_wp:

<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
    android:thumbnail="@drawable/ic_launcher" 
    android:description="@string/fallingsnow_wp_desc" />

Here, we simply use the regular launcher icon as the thumbnail and point to a string that will show up as the description in the listing of wallpapers. If your live wallpaper needs configuration, you'd point to it with the android:settingsActivity property.

Android SDK - Live Wallpaper Settings

Finally, back in your manifest file, don't forget to set the uses-feature for android.software.live_wallpaper:

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

Step 3: Wallpaper Service Engine Wiring

Now that the boring, yet critical, stuff is out of the way, let's return to the real work: creating the WallpaperService.Engine class. Since we already have a RenderScript file for doing some animation, all we need to do is link the rendering up to the new surface. The onSurfaceCreated() method of Engine is a great place to create the RenderScriptGL object we'll need:

        @Override
        public void onSurfaceCreated(SurfaceHolder holder) {
            super.onSurfaceCreated(holder);
            
            RenderScriptGL.SurfaceConfig surfaceConfig = new RenderScriptGL.SurfaceConfig();
            mRenderScriptGL = new RenderScriptGL(FallingSnowWallpaperService.this, surfaceConfig);
            
            // use low for wallpapers
            mRenderScriptGL.setPriority(RenderScript.Priority.LOW);
        }

We also set the rendering priority to low -- this is a live wallpaper and not a critical game or UI rendering engine. It should not slow down anything else on the system.

Clean this up in the onSurfaceDestroyed() method:


        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder) {
            super.onSurfaceDestroyed(holder);
            if (mSnowRS != null)  {
                mSnowRS.stop();
                mSnowRS = null;
            }
            if (mRenderScriptGL != null) {
                mRenderScriptGL.destroy();
                mRenderScriptGL = null;
            }
        }

The onSurfaceChanged() method is a great place to initialize the RenderScript class. This is the first place where you find out details of what you'll be rendering to, such as the width and height. This is also where we set the surface for the RenderScriptGL class.

        @Override
        public void onSurfaceChanged(SurfaceHolder holder, int format,
                int width, int height) {
            super.onSurfaceChanged(holder, format, width, height);
            
            
            if (mRenderScriptGL != null) {
                mRenderScriptGL.setSurface(holder, width, height);
            }
            if (mSnowRS == null) {
                mSnowRS = new SnowRS(width, height);
                mSnowRS.init(mRenderScriptGL, getResources(), isPreview());
                mSnowRS.start();
            } 
        }

It's a good idea to stop the wallpaper when it's not visible.

        @Override
        public void onVisibilityChanged(boolean visible) {
            super.onVisibilityChanged(visible);
            if (mSnowRS == null) {
                if (visible) {
                    mSnowRS.start();
                } else {
                    mSnowRS.stop();
                }
            }

And that's it. The live wallpaper rolls. Or animates. Or does whatever it is you want it to do.

Want to respond to taps? Override the onCommand() method of the WallpaperService.Engine class.

Want to adjust positions when the user swipes between home screen pages? Override the onOffsetsChanged() method of the WallpaperService.Engine class.

Want to know if the user is viewing the preview before setting the wallpaper? Call the isPreview() method of the WallpaperService.Engine class and check the results.

The full implementation of our WallpaperService.Engine class can be found in FallSnowWallpaperService.java of the open source project.

Let's take a look at the Live Wallpaper:

Android SDK - Live Wallpaper Preview

That should look familiar; it's the same thing we saw in the RenderScript activity.


Step 4: Some Notes On Performance

Live wallpapers are a great place to make highly efficient and great performing graphical effects. But you need to do so realizing that the user isn't necessarily sitting there watching a demo (you know, like those from scene.org). What this means is that you may need to reduce frame rates, reduce pixels, polygon counts, or texture details to keep the wallpaper interesting, but not stressful on the CPU, GPU, and battery. If users find that your live wallpaper is eating their battery, it makes your app look bad and it makes their device seem weak with low battery life. A bad experience with an Android device causes all developers to suffer a bad rap.


Step 5: The Demo View

The demo view and activity (from the previous tutorial) is still available when the app launches. Instead of removing it, why not just add a handler so that when a user clicks on it, the live wallpaper settings will come up so the user can select the live wallpaper?

    public void onWallpaperSettings(View view) {
        Intent wallpaperSettings = new Intent(Intent.ACTION_SET_WALLPAPER);
        startActivity(wallpaperSettings);
    }

Why not, indeed! That was easy. On any clickable view, just add the android:onClick="onWallpaperSettings" property and you're good to go.

Here's a still image:

Android SDK - Live Wallpaper Preview

Conclusion

Live wallpapers are a convenient way to expand your application beyond its typical boundaries. Got a role-playing game? Make some neat live wallpapers featuring the main characters. Just make sure you use common sense when rendering to the screen so that the user’s experience with their device does not suffer.

Let us know what cool live wallpapers you're building in the comments!

About the Authors

Mobile developers Lauren Darcey and Shane Conder have coauthored several books on Android development: an in-depth programming book entitled Android Wireless Application Development and Sams Teach Yourself Android Application Development in 24 Hours. When not writing, they spend their time developing mobile software at their company and providing consulting services. They can be reached at via email to androidwirelessdev+mt@gmail.com, via their blog at androidbook.blogspot.com, and on Twitter @androidwireless.

Need More Help Writing Android Apps? Check out our Latest Books and Resources!

Buy Android Wireless Application Development, 2nd Edition  Buy Sam's Teach Yourself Android Application Development in 24 Hours  Mamlambo code at Code Canyon

Advertisement