Search This Blog

30 May 2010

Live Wallpapers

Let's try doing some tabs.... We'll start with our basic app...

F:\work> mvn archetype:generate -DarchetypeCatalog=http://kallisti.eoti.org:8081/content/repositories/snapshots/archetype-catalog.xml
   
Choose the galatea-archetype plugin
groupId: org.eoti.android
artifactId: LiveWallpaperTest
version: 1.0-SNAPSHOT
package: org.eoti.android

Make sure the emulator is running...

F:\work> cd LiveWallpaperTest
F:\work\LiveWallpaperTest> mvn clean install

Rename your LiveWallpaperTestActivity to LiveWallpaperTestService and replace the contents:
public class LiveWallpaperTestService extends WallpaperService {
    private static String TAG = "LiveWallpaperTest";

    @Override
    public Engine onCreateEngine() {
        return new LiveWallpaperTestEngine();
    }

    class LiveWallpaperTestEngine
    extends WallpaperService.Engine
    {
        @Override
        public void onCreate(SurfaceHolder surfaceHolder) {
            super.onCreate(surfaceHolder);
        }
    }
}




Add yourself to src\main\android\res\values\strings.xml:
 <string name="author">Malachi de AElfweald</string>


Create a src\main\android\res\xml\wallpaper.xml:
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
   android:author="@string/author"
   android:description="@string/app_name"
   android:thumbnail="@drawable/icon"
/>


In the AndroidManifest.xml, replace this bit:
<activity android:name=".LiveWallpaperTestActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>
with this bit:
<service android:name=".LiveWallpaperTestService" 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"/>
</service>

Redeploy (mvn clean install), click Menu and choose LiveWallpaper. Select your wallpaper and click "Set Wallpaper".

Ok, just a black background doesn't feel very live... let's liven it up just a little...

Replace the contents of your LiveWallpaperTestService:

public class LiveWallpaperTestService extends WallpaperService {
    private static String TAG = "LiveWallpaperTest";

    @Override
    public Engine onCreateEngine() {
        return new LiveWallpaperTestEngine();
    }

    class LiveWallpaperTestPainter
    extends Thread
    {
        private SurfaceHolder holder;
        private Rect frame;
        private boolean die = false;
        private MotionEvent event = null;
        private Paint cornsilk;
        private boolean visible = true;

        public LiveWallpaperTestPainter(SurfaceHolder holder)
        {
            this.holder = holder;
            frame = holder.getSurfaceFrame();
            cornsilk = new Paint(Paint.ANTI_ALIAS_FLAG);
            cornsilk.setColor(Color.rgb(255,248,220));
        }

        public void die()
        {
            this.die = true;
        }

        public void setVisible(boolean visible)
        {
            this.visible = visible;
        }

        public void setTouch(MotionEvent event)
        {
            this.event = event;
        }

        public void run()
        {
            Canvas canvas = null;
            while(!die)
            {
                if(!visible)
                {
                    try{Thread.sleep(500);}catch(Exception e){}
                    continue;
                }

                canvas = holder.lockCanvas();
                if(canvas != null)
                {
                    render(canvas);
                    holder.unlockCanvasAndPost(canvas);
                }
            }
        }

        protected void render(Canvas canvas)
        {
            if(event == null) return;
            canvas.drawColor(0xFF000000);
           
            canvas.drawLine(frame.left, frame.top, event.getX(), event.getY(), cornsilk);
            canvas.drawLine(frame.right, frame.top, event.getX(), event.getY(), cornsilk);
            canvas.drawLine(frame.left, frame.bottom, event.getX(), event.getY(), cornsilk);
            canvas.drawLine(frame.right, frame.bottom, event.getX(), event.getY(), cornsilk);
        }
    }

    class LiveWallpaperTestEngine
    extends WallpaperService.Engine
    {
        private LiveWallpaperTestPainter painter = null;

        @Override
        public void onCreate(SurfaceHolder surfaceHolder) {
            super.onCreate(surfaceHolder);
            this.setTouchEventsEnabled(true);
        }

        @Override
        public void onTouchEvent(MotionEvent event) {
            super.onTouchEvent(event);
            painter.setTouch(event);
        }

        @Override
        public void onSurfaceCreated(SurfaceHolder holder) {
            super.onSurfaceCreated(holder);
            painter = new LiveWallpaperTestPainter(holder);
            painter.start();
        }

        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder) {
            if(painter != null) painter.die();
            super.onSurfaceDestroyed(holder);
        }

        @Override
        public void onVisibilityChanged(boolean visible) {
            super.onVisibilityChanged(visible);
            painter.setVisible(visible);
        }
    }
}

Redeploy (mvn clean install) and set your wallpaper.  Now, a "X" will mark where you last touched/clicked.

1 comment:

  1. Actually, change the run method to save the CPU a bit:

    try{Thread.sleep(500);}catch(Exception e){}
    if(!visible)continue;

    This way the sleep is there whether it is visible or not.

    ReplyDelete