Belajar Membuat Live Wallpaper Untuk Android


Selain wallpaper dalam bentuk gambar statis, Android juga mendukung wallpaper animasi dan interaktif yang disebut sebagai live wallpaper. Sebagai latihan, pada kesempatan ini, saya akan mencoba membuat sebuah live wallpaper sederhana. Saya akan mulai dengan membuat sebuah proyek baru di Android Studio. Sebuah live wallpaper pada dasarnya adalah sebuah service. Oleh sebab itu, saya kemudian membuat service baru dengan nama LiveWallpaperService yang isinya seperti berikut ini:

public class LiveWallpaperService extends WallpaperService {

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

}

Service yang mewakili live wallpaper harus diturunkan dari WallpaperService. Satu-satunya method yang perlu dibuat disini adalah onCreateEngine() yang menghasilkan sebuah WallpaperService.Engine.

Kode program yang berhubungan dengan live wallpaper justru lebih banyak terdapat di turunan WallpaperService.Engine ini. Sebagai contoh, saya membuat sebuah nested class dengan nama MyAnimationEngine dengan isi seperti berikut ini:

public class LiveWallpaperService extends WallpaperService {

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

    class MyAnimationEngine extends Engine {

        private AnimasiThread animasiThread;
        private int width, height;

        private void startAnimation() {
            animasiThread = new AnimasiThread(getSurfaceHolder(), width, height, getApplicationContext());
            animasiThread.setRunning(true);
            animasiThread.start();
        }

        private void stopAnimation() {
            if (animasiThread != null) {
                animasiThread.setRunning(false);
                try {
                    animasiThread.join();
                } catch (InterruptedException e) {
                }
            }
        }

        private void restartAnimation() {
            if (animasiThread != null) {
                stopAnimation();
            }
            startAnimation();
        }

        @Override
        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            this.width = width;
            this.height = height;
            restartAnimation();
        }

        @Override
        public void onSurfaceCreated(SurfaceHolder holder) {
            startAnimation();
        }

        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder) {
            stopAnimation();
        }

        @Override
        public void onVisibilityChanged(boolean visible) {
            if (!visible) {
                stopAnimation();
            } else {
                restartAnimation();
            }
        }

    }

}   

Sama seperti saat menggambar pada SurfaceView, saya memulai proses penggambaran pada onSurfaceCreated() yang akan dipanggil setelah SurfaceHolder dibuat. Selain itu, saya juga perlu memperbaharui layar bila terjadi perubahan ukuran layar yang akan memanggil onSurfaceChanged(). Bila proses penggambaran selesai, onSurfaceDestroyed() akan dipanggil.

Pada saat menggambar untuk live wallpaper, saya perlu menghemat sumber daya dan tidak mengerjakan sesuatu yang tidak perlu. Bila terlalu berlebihan, bukan saja CPU akan habis dikonsumsi kode program yang menggambar, tetapi baterai juga akan cepat habis. Oleh sebab itu, saya men-override method onVisiblityChanged() untuk mematikan proses penggambaran bila live wallpaper tidak visible.

Pada implementasi WallpaperService.Engine di atas, saya menggambar pada sebuah thread baru yang diwakili oleh sebuah class seperti berikut ini:

public class AnimasiThread extends Thread {

    private SurfaceHolder surfaceHolder;
    private boolean running = false;
    private int width, height;
    private List<Gambar> gambars;
    private final Object lock = new Object();

    public AnimasiThread(SurfaceHolder surfaceHolder, int width, int height, Context context) {
        this.surfaceHolder = surfaceHolder;
        this.width = width;
        this.height = height;
        gambars = new ArrayList<>();
        for (int i=0; i<20; i++) {
            gambars.add(new Gambar(width, height, BitmapFactory.decodeResource(context.getResources(), R.drawable.hati)));
        }
    }

    public void setRunning(boolean running) {
        this.running = running;
    }

    @Override
    public void run() {
        while (running) {
            Canvas c = null;
            try {
                c = surfaceHolder.lockCanvas();
                if (running) {
                    c.drawColor(Color.BLACK);
                    synchronized (lock) {
                        for (Gambar gambar: gambars) {
                            gambar.gambar(c);
                            gambar.gerak();
                        }
                    }
                }
            } finally {
                if (c != null) {
                    surfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }

}

Class di atas membutuhkan sebuah gambar yang saya letakkan dalam folder drawable. Saya memberi nama file tersebut sebagai hati.png.

Tidak ada yang spesial pada class AnimasiThread di atas. Saya hanya menciptakan beberapa object Gambar dan memanggil method gerak() pada setiap object yang ada secara terus menerus berulang kali. Isi dari class Gambar terlihat seperti berikut ini:

public class Gambar {

    private float x, y, xmax, ymax;
    private Bitmap gambar;
    private float kecepatan;

    public Gambar(float xmax, float ymax, Bitmap gambar) {
        this.xmax = xmax;
        this.ymax = ymax;
        this.gambar = gambar;
        this.kecepatan = 0.1f;
        Random random = new Random();
        this.x = random.nextFloat() * xmax;
        this.y = random.nextFloat() * ymax;
    }

    public void gerak() {
        y += kecepatan;
        kecepatan += 0.1f;
        if (y > ymax) {
            y = (float)(Math.random() * -ymax);
            x = (float)(Math.random() * xmax);
            kecepatan = 0.1f;
        }
    }

    public void gambar(Canvas c) {
        c.drawBitmap(gambar, x, y, null);
    }

}

Sebagai langkah terakhir, agar live wallpaper ini bisa dikenali, saya perlu membuat sebuah file XML yang berisi <wallpaper>. Untuk itu, saya men-klik kanan nama proyek dan memilih menu New, Android Resource File. Pada dialog yang muncul, saya mengisi File name dengan mylivewallpaper. Pada Resource type, saya memilih XML. Saya juga mengganti Root element dengan wallpaper. Setelah itu, saya men-klik tombol Ok. Saya kemudian mengubah file yang dihasilkan menjadi seperti berikut ini:

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

Setelah itu, saya mengubah deklarasi service di AndroidManifest.xml menjadi seperti berikut ini:

<?xml version="1.0" encoding="utf-8"?>
<manifest... >

    <application ...>
        <service
            android:name=".LiveWallpaperService"
            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/mylivewallpaper" />
        </service>
    </application>

</manifest>

Saya tidak bisa begitu saja menjalankan aplikasi ini karena tidak ada activity yang berfungsi sebagai launcher. Hal ini terlihat dari tanda silang pada tombol yang biasa saya gunakan untuk menjalankan aplikasi di Android Studio:

Tidak ada launcher activity

Tidak ada launcher activity

Yang bisa saya lakukan hanya men-deploy aplikasi ke perangkat. Oleh sebab itu, saya memilih Edit Configurations…. Pada dialog yang muncul, saya mengubah Launch default Activity menjadi Do not launch Activity seperti pada gambar berikut ini:

Mendeploy project tanpa menjalankan activity

Mendeploy project tanpa menjalankan activity

Setelah men-klik OK, saya kini bisa men-deploy aplikasi ke perangkat Android.

Untuk menggunakan live wallpaper yang telah saya buat, saya perlu membuka Settings di perangkat Android lalu memilih menu Display, Wallpaper, Home screen. Pada daftar pilihan yang muncul, saya memilih Live wallpapers seperti pada gambar berikut ini:

Memilih live wallpaper untuk dipakai

Memilih live wallpaper untuk dipakai

Setelah itu, saya dapat memilih live wallpaper yang telah saya buat seperti pada gambar berikut ini:

Memilih live wallpaper untuk dipakai

Memilih live wallpaper untuk dipakai

Sekarang, tampilan live wallpaper akan muncul dalam bentuk animasi seperti pada video berikut ini:

Tampilan live wallpaper setelah dipakai

Tampilan live wallpaper setelah dipakai

Perihal Solid Snake
I'm nothing...

Apa komentar Anda?

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: