Is it possible to set an animated gif file as live wallpaper in android?

This is the basic wallpaper service (as supplied in the Live Wallpaper Tutorial) hacked to display an animated gif.

First – create a project & set up your manifest as a Live wallpaper.
Then – download a gif, like this one

   nyan nyan

Save that gif in res/raw/nyan.gif in your project.
Create a live wallpaper service, like shown in this example.

public class NyanNyanService extends WallpaperService {
    static final String TAG = "NYAN";
    static final Handler mNyanHandler = new Handler();

    /**
     * @see android.service.wallpaper.WallpaperService#onCreate()
     */
    @Override
    public void onCreate() {
        super.onCreate();
    }

    /**
     * @see android.service.wallpaper.WallpaperService#onCreateEngine()
     */
    @Override
    public Engine onCreateEngine() {
        try {
            return new NyanEngine();
        } catch (IOException e) {
            Log.w(TAG, "Error creating NyanEngine", e);
            stopSelf();
            return null;
        }
    }

    class NyanEngine extends Engine {
        private final Movie mNyan;
        private final int mNyanDuration;
        private final Runnable mNyanNyan;
        float mScaleX;
        float mScaleY;
        int mWhen;
        long mStart;

        NyanEngine() throws IOException {
            InputStream is = getResources().openRawResource(R.raw.nyan);
            if (is != null) {
                try {
                    mNyan = Movie.decodeStream(is);
                    mNyanDuration = mNyan.duration();
                } finally {
                    is.close();
                }
            } else {
                throw new IOException("Unable to open R.raw.nyan");
            }

            mWhen = -1;
            mNyanNyan = new Runnable() {
                public void run() {
                    nyan();
                }
            };
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            mNyanHandler.removeCallbacks(mNyanNyan);
        }

        @Override
        public void onVisibilityChanged(boolean visible) {
            super.onVisibilityChanged(visible);
            if (visible) {
                nyan();
            } else {
                mNyanHandler.removeCallbacks(mNyanNyan);
            }
        }

        @Override
        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            super.onSurfaceChanged(holder, format, width, height);
            mScaleX = width / (1f * mNyan.width());
            mScaleY = height / (1f * mNyan.height());
            nyan();
        }

        @Override
        public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
                float yOffsetStep, int xPixelOffset, int yPixelOffset) {
            super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixelOffset, yPixelOffset);
            nyan();
        }

        void nyan() {
            tick();
            SurfaceHolder surfaceHolder = getSurfaceHolder();
            Canvas canvas = null;
            try {
                canvas = surfaceHolder.lockCanvas();
                if (canvas != null) {
                    nyanNyan(canvas);
                }
            } finally {
                if (canvas != null) {
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
            mNyanHandler.removeCallbacks(mNyanNyan);
            if (isVisible()) {
                mNyanHandler.postDelayed(mNyanNyan, 1000L/25L);
            }
        }

        void tick() {
            if (mWhen == -1L) {
                mWhen = 0;
                mStart = SystemClock.uptimeMillis();
            } else {
                long mDiff = SystemClock.uptimeMillis() - mStart;
                mWhen = (int) (mDiff % mNyanDuration);
            }
        }

        void nyanNyan(Canvas canvas) {
            canvas.save();
            canvas.scale(mScaleX, mScaleY);
            mNyan.setTime(mWhen);
            mNyan.draw(canvas, 0, 0);
            canvas.restore();
        }
    }
}

This will basically scale the nyan-nyan cat to fit the screen and animate it perpetually.

A Live wallpaper manifest looks sort-of-like this (this example does not contain a configuration activity):

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="your.nyan.nyan.package"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="10" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/application_nyan" > 
        <service 
            android:label="@string/wallpaper_nyan"
            android:name=".NyanNyanService"
            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/nyan" />
        </service>
    </application>
</manifest>

The AndroidManifest.xml has a reference to a file in res/xml, in this case named “nyan.xml”:

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

Leave a Comment