Android動態壁紙的製作教程

來源:互聯網
上載者:User

動態壁紙是在Android 2.1新增的一個功能。動態壁紙可以添加到Android的案頭,具有互動動畫背景效果。在本教程中,我們將教會你如何去製作一個互動動態壁紙。

動態壁紙是一個Android應用程式,包括一個服務(WallpaperService)。該服務必須包括一個引擎(WallpaperService.Engine)。該引擎是串連使用者、案頭、系統之間的橋樑。它也可以繪製案頭壁紙。

首先,必須由內在的Engine類建立一個WallpaperService類。該服務必須在AndroidManifest.xml中聲明為"android.service.wallpaper.WallpaperService",這樣它才會作為動態壁紙被手機識別。而且還要在服務配置中附加"android.permission.BIND_WALLPAPER"的許可權許可:

 

<service
    android:name="LiveWallpaperService"
    android:enabled="true"
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:permission="android.permission.BIND_WALLPAPER">

    <intent-filter android:priority="1" >
        <action android:name="android.service.wallpaper.WallpaperService" />
    </intent-filter>
    <meta-data
      android:name="android.service.wallpaper"
      android:resource="@xml/wallpaper" />

</service>

 

 

建立一個XML檔案,放置在應用程式目錄下的/res/xml/中。它用來描述你的動態壁紙。

 

 

<?xml version="1.0" encoding="UTF-8"?>

<wallpaper
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:thumbnail="@drawable/thumbnail"
    android:description="@string/description"
    android:settingsActivity="PreferenceActivity"/>

 

再建立一個xml的屬性檔案 attrs.xml ,代碼如下:

<declare-styleable name="Wallpaper">
    <!-- Component name of an activity that allows the user to modify
         the current settings for this wallpaper. -->
    <attr name="settingsActivity" />
 
    <!-- Reference to a the wallpaper's thumbnail bitmap. -->

    <attr name="thumbnail" format="reference" />
 
    <!-- Name of the author of this component, e.g. Google. -->
    <attr name="author" format="reference" />

 
    <!-- Short description of the component's purpose or behavior. -->
    <attr name="description" />
</declare-styleable>

 

動態壁紙的服務代碼如下

 

package net.androgames.blog.sample.livewallpaper;
 
import android.content.SharedPreferences;
import android.service.wallpaper.WallpaperService;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
 
/**
 * Android Live Wallpaper Archetype
 * @author antoine vianey
 * under GPL v3 : http://www.gnu.org/licenses/gpl-3.0.html
 */
public class LiveWallpaperService extends WallpaperService {
 
    @Override
    public Engine onCreateEngine() {
        return new SampleEngine();
    }
 
    @Override
    public void onCreate() {
        super.onCreate();
    }
 
    @Override
    public void onDestroy() {
        super.onDestroy();
    }
 
    public class SampleEngine extends Engine {
 
        private LiveWallpaperPainting painting;
 
        SampleEngine() {
            SurfaceHolder holder = getSurfaceHolder();
            painting = new LiveWallpaperPainting(holder, 
                getApplicationContext());
        }
 
        @Override
        public void onCreate(SurfaceHolder surfaceHolder) {
            super.onCreate(surfaceHolder);
            // register listeners and callbacks here
            setTouchEventsEnabled(true);
        }
 
        @Override
        public void onDestroy() {
            super.onDestroy();
            // remove listeners and callbacks here
            painting.stopPainting();
        }
 
        @Override
        public void onVisibilityChanged(boolean visible) {
            if (visible) {
                // register listeners and callbacks here
                painting.resumePainting();
            } else {
                // remove listeners and callbacks here
                painting.pausePainting();
            }
        }
 
        @Override
        public void onSurfaceChanged(SurfaceHolder holder, int format, 
                int width, int height) {
            super.onSurfaceChanged(holder, format, width, height);
            painting.setSurfaceSize(width, height);
        }
 
        @Override
        public void onSurfaceCreated(SurfaceHolder holder) {
            super.onSurfaceCreated(holder);
            // start painting
            painting.start();
        }
 
        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder) {
            super.onSurfaceDestroyed(holder);
            boolean retry = true;
            painting.stopPainting();
            while (retry) {
                try {
                    painting.join();
                    retry = false;
                } catch (InterruptedException e) {}
            }
        }
 
        @Override
        public void onOffsetsChanged(float xOffset, float yOffset, 
                float xStep, float yStep, int xPixels, int yPixels) {
        }
 
        @Override
        public void onTouchEvent(MotionEvent event) {
            super.onTouchEvent(event);
            painting.doTouchEvent(event);
        }
 
    }
 
}

 

當壁紙的顯示、狀態或大小變化是,會調用Engine的onCreate, onDestroy, onVisibilityChanged, onSurfaceChanged, onSurfaceCreatedonSurfaceDestroyed方法。有了這些方法,動態壁紙才能展現齣動畫效果。而通過設定setTouchEventsEnabled(true),並且調用onTouchEvent(MotionEvent event)方法,來啟用觸摸事件。

我們在繪畫牆紙的時候,也會使用一個單獨的繪畫線程

 

package net.androgames.blog.sample.livewallpaper;
 
import android.content.Context;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
 
/**
 * Android Live Wallpaper painting thread Archetype
 * @author antoine vianey
 * GPL v3 : http://www.gnu.org/licenses/gpl-3.0.html
 */
public class LiveWallpaperPainting extends Thread {
 
    /** Reference to the View and the context */
    private SurfaceHolder surfaceHolder;
    private Context context;
 
    /** State */
    private boolean wait;
    private boolean run;
 
    /** Dimensions */
    private int width;
    private int height;
 
    /** Time tracking */
    private long previousTime;
    private long currentTime;
 
    public LiveWallpaperPainting(SurfaceHolder surfaceHolder, 
            Context context) {
        // keep a reference of the context and the surface
        // the context is needed if you want to inflate
        // some resources from your livewallpaper .apk
        this.surfaceHolder = surfaceHolder;
        this.context = context;
        // don't animate until surface is created and displayed
        this.wait = true;
    }
 
    /**
     * Pauses the live wallpaper animation
     */
    public void pausePainting() {
        this.wait = true;
        synchronized(this) {
            this.notify();
        }
    }
 
    /**
     * Resume the live wallpaper animation
     */
    public void resumePainting() {
        this.wait = false;
        synchronized(this) {
            this.notify();
        }
    }
 
    /**
     * Stop the live wallpaper animation
     */
    public void stopPainting() {
        this.run = false;
        synchronized(this) {
            this.notify();
        }
    }
 
    @Override
    public void run() {
        this.run = true;
        Canvas c = null;
        while (run) {
            try {
                c = this.surfaceHolder.lockCanvas(null);
                synchronized (this.surfaceHolder) {
                    currentTime = System.currentTimeMillis();
                    updatePhysics();
                    doDraw(c);
                    previousTime = currentTime;
                }
            } finally {
                if (c != null) {
                    this.surfaceHolder.unlockCanvasAndPost(c);
                }
            }
            // pause if no need to animate
            synchronized (this) {
                if (wait) {
                    try {
                        wait();
                    } catch (Exception e) {}
                }
            }
        }
    }
 
    /**
     * Invoke when the surface dimension change
     */
    public void setSurfaceSize(int width, int height) {
        this.width = width;
        this.height = height;
        synchronized(this) {
            this.notify();
        }
    }
 
    /**
     * Invoke while the screen is touched
     */
    public void doTouchEvent(MotionEvent event) {
        // handle the event here
        // if there is something to animate
        // then wake up
        this.wait = false;
        synchronized(this) {
            notify();
        }
    }
 
    /**
     * Do the actual drawing stuff
     */
    private void doDraw(Canvas canvas) {}
 
    /**
     * Update the animation, sprites or whatever.
     * If there is nothing to animate set the wait
     * attribute of the thread to true
     */
    private void updatePhysics() {
        // if nothing was updated :
        // this.wait = true;
    }
 
}

 

如果案頭壁紙是可見狀態下,系統服務通知有新的東西,這個類會優先把它繪製在畫布上。如果沒有動畫了,updatePhysics會通知線程去等待。通常SurfaceView在有兩個畫布交替繪製的時候,會在畫布上繪製上一次......

如果要讓你的動態牆紙有配置功能,只要建立一個PreferenceActivity,並將它在wallpaper.xml檔案中聲明。同時讓SharedPreference對象可以找到你的配置選項。

教程就寫到這裡,如果還有什麼不懂,你可以通過Eclipse來瀏覽完整的原始碼:SampleLiveWallpaper

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.