Android动态壁纸的制作教程

news/2025/1/12 4:02:00/

动态壁纸是在Android 2.1新增的一个功能。动态壁纸可以添加到Android的桌面,具有交互式的动画背景效果。在本教程中,我们将教会你如何去制作一个交互式的动态壁纸。

动态壁纸是一个Android应用程序,包括一个服务(WallpaperService)。该服务必须包括一个引擎(WallpaperService.Engine)。该引擎是连接用户、桌面、系统之间的桥梁。它也可以绘制桌面壁纸。

首先,必须由内在的Engine类创建一个WallpaperService类。该服务必须在AndroidManifest.xml中声明为"android.service.wallpaper.WallpaperService",这样它才会作为动态壁纸被手机识别。而且还要在服务配置中附加"android.permission.BIND_WALLPAPER"的权限许可: 

01 <service
02     android:name="LiveWallpaperService"
03     android:enabled="true"
04     android:icon="@drawable/icon"
05     android:label="@string/app_name"
06     android:permission="android.permission.BIND_WALLPAPER">
07     <intent-filter android:priority="1" >
08         <action android:name="android.service.wallpaper.WallpaperService" />
09     </intent-filter>
10     <meta-data
11       android:name="android.service.wallpaper"
12       android:resource="@xml/wallpaper" />
13 </service>

创建一个XML文件,放置在应用程序目录下的/res/xml/中。它用来描述你的动态壁纸。 

1 <?xml version="1.0" encoding="UTF-8"?>
2 <wallpaper
3     xmlns:android="http://schemas.android.com/apk/res/android" 
4     android:thumbnail="@drawable/thumbnail"
5     android:description="@string/description"
6     android:settingsActivity="PreferenceActivity"/>

再创建一个xml的属性文件 attrs.xml ,代码如下: 

01 <declare-styleable name="Wallpaper">
02     <!-- Component name of an activity that allows the user to modify
03          the current settings for this wallpaper. -->
04     <attr name="settingsActivity" />
05   
06     <!-- Reference to a the wallpaper's thumbnail bitmap. -->
07     <attr name="thumbnail" format="reference" />
08   
09     <!-- Name of the author of this component, e.g. Google. -->
10     <attr name="author" format="reference" />
11   
12     <!-- Short description of the component's purpose or behavior. -->
13     <attr name="description" />
14 </declare-styleable>

动态壁纸的服务代码如下: 

001 package net.androgames.blog.sample.livewallpaper;
002   
003 import android.content.SharedPreferences;
004 import android.service.wallpaper.WallpaperService;
005 import android.view.MotionEvent;
006 import android.view.SurfaceHolder;
007   
008 /**
009  * Android Live Wallpaper Archetype
010  * @author antoine vianey
011  * under GPL v3 : http://www.gnu.org/licenses/gpl-3.0.html
012  */
013 public class LiveWallpaperService extends WallpaperService {
014   
015     @Override
016     public Engine onCreateEngine() {
017         return new SampleEngine();
018     }
019   
020     @Override
021     public void onCreate() {
022         super.onCreate();
023     }
024   
025     @Override
026     public void onDestroy() {
027         super.onDestroy();
028     }
029   
030     public class SampleEngine extends Engine {
031   
032         private LiveWallpaperPainting painting;
033   
034         SampleEngine() {
035             SurfaceHolder holder = getSurfaceHolder();
036             painting = new LiveWallpaperPainting(holder,
037                 getApplicationContext());
038         }
039   
040         @Override
041         public void onCreate(SurfaceHolder surfaceHolder) {
042             super.onCreate(surfaceHolder);
043             // register listeners and callbacks here
044             setTouchEventsEnabled(true);
045         }
046   
047         @Override
048         public void onDestroy() {
049             super.onDestroy();
050             // remove listeners and callbacks here
051             painting.stopPainting();
052         }
053   
054         @Override
055         public void onVisibilityChanged(boolean visible) {
056             if (visible) {
057                 // register listeners and callbacks here
058                 painting.resumePainting();
059             else {
060                 // remove listeners and callbacks here
061                 painting.pausePainting();
062             }
063         }
064   
065         @Override
066         public void onSurfaceChanged(SurfaceHolder holder, int format,
067                 int width, int height) {
068             super.onSurfaceChanged(holder, format, width, height);
069             painting.setSurfaceSize(width, height);
070         }
071   
072         @Override
073         public void onSurfaceCreated(SurfaceHolder holder) {
074             super.onSurfaceCreated(holder);
075             // start painting
076             painting.start();
077         }
078   
079         @Override
080         public void onSurfaceDestroyed(SurfaceHolder holder) {
081             super.onSurfaceDestroyed(holder);
082             boolean retry = true;
083             painting.stopPainting();
084             while (retry) {
085                 try {
086                     painting.join();
087                     retry = false;
088                 catch (InterruptedException e) {}
089             }
090         }
091   
092         @Override
093         public void onOffsetsChanged(float xOffset, float yOffset,
094                 float xStep, float yStep, int xPixels, int yPixels) {
095         }
096   
097         @Override
098         public void onTouchEvent(MotionEvent event) {
099             super.onTouchEvent(event);
100             painting.doTouchEvent(event);
101         }
102   
103     }
104   
105 }

当壁纸的显示、状态或大小变化是,会调用Engine的onCreateonDestroyonVisibilityChanged,onSurfaceChangedonSurfaceCreated 和 onSurfaceDestroyed方法。有了这些方法,动态壁纸才能展现出动画效果。而通过设置setTouchEventsEnabled(true),并且调用onTouchEvent(MotionEvent event)方法,来激活触摸事件。

我们在绘画墙纸的时候,也会使用一个单独的绘画线程: 

001 package net.androgames.blog.sample.livewallpaper;
002   
003 import android.content.Context;
004 import android.graphics.Canvas;
005 import android.view.MotionEvent;
006 import android.view.SurfaceHolder;
007   
008 /**
009  * Android Live Wallpaper painting thread Archetype
010  * @author antoine vianey
011  * GPL v3 : http://www.gnu.org/licenses/gpl-3.0.html
012  */
013 public class LiveWallpaperPainting extends Thread {
014   
015     /** Reference to the View and the context */
016     private SurfaceHolder surfaceHolder;
017     private Context context;
018   
019     /** State */
020     private boolean wait;
021     private boolean run;
022   
023     /** Dimensions */
024     private int width;
025     private int height;
026   
027     /** Time tracking */
028     private long previousTime;
029     private long currentTime;
030   
031     public LiveWallpaperPainting(SurfaceHolder surfaceHolder,
032             Context context) {
033         // keep a reference of the context and the surface
034         // the context is needed if you want to inflate
035         // some resources from your livewallpaper .apk
036         this.surfaceHolder = surfaceHolder;
037         this.context = context;
038         // don't animate until surface is created and displayed
039         this.wait = true;
040     }
041   
042     /**
043      * Pauses the live wallpaper animation
044      */
045     public void pausePainting() {
046         this.wait = true;
047         synchronized(this) {
048             this.notify();
049         }
050     }
051   
052     /**
053      * Resume the live wallpaper animation
054      */
055     public void resumePainting() {
056         this.wait = false;
057         synchronized(this) {
058             this.notify();
059         }
060     }
061   
062     /**
063      * Stop the live wallpaper animation
064      */
065     public void stopPainting() {
066         this.run = false;
067         synchronized(this) {
068             this.notify();
069         }
070     }
071   
072     @Override
073     public void run() {
074         this.run = true;
075         Canvas c = null;
076         while (run) {
077             try {
078                 c = this.surfaceHolder.lockCanvas(null);
079                 synchronized (this.surfaceHolder) {
080                     currentTime = System.currentTimeMillis();
081                     updatePhysics();
082                     doDraw(c);
083                     previousTime = currentTime;
084                 }
085             finally {
086                 if (c != null) {
087                     this.surfaceHolder.unlockCanvasAndPost(c);
088                 }
089             }
090             // pause if no need to animate
091             synchronized (this) {
092                 if (wait) {
093                     try {
094                         wait();
095                     catch (Exception e) {}
096                 }
097             }
098         }
099     }
100   
101     /**
102      * Invoke when the surface dimension change
103      */
104     public void setSurfaceSize(int width, int height) {
105         this.width = width;
106         this.height = height;
107         synchronized(this) {
108             this.notify();
109         }
110     }
111   
112     /**
113      * Invoke while the screen is touched
114      */
115     public void doTouchEvent(MotionEvent event) {
116         // handle the event here
117         // if there is something to animate
118         // then wake up
119         this.wait = false;
120         synchronized(this) {
121             notify();
122         }
123     }
124   
125     /**
126      * Do the actual drawing stuff
127      */
128     private void doDraw(Canvas canvas) {}
129   
130     /**
131      * Update the animation, sprites or whatever.
132      * If there is nothing to animate set the wait
133      * attribute of the thread to true
134      */
135     private void updatePhysics() {
136         // if nothing was updated :
137         // this.wait = true;
138     }
139   
140 }

如果桌面壁纸是可见状态下,系统服务通知有新的东西,这个类会优先把它绘制在画布上。如果没有动画了,updatePhysics会通知线程去等待。通常SurfaceView在有两个画布交替绘制的时候,会在画布上绘制上一次......

如果要让你的动态墙纸有配置功能,只要创建一个PreferenceActivity,并将它在wallpaper.xml文件中声明。同时让SharedPreference对象可以找到你的配置选项。

教程就写到这里,如果还有什么不懂,你可以通过Eclipse来浏览完整的源代码:SampleLiveWallpaper。


http://www.ppmy.cn/news/120968.html

相关文章

Android 动态壁纸 Livepaper

动态壁纸原理 及 例子 最近做动态壁纸的项目&#xff0c;原来觉得动态壁纸是个很小的项目&#xff0c;但是看到Android Market上有个专门的动态壁纸分类(现在升级为Google Play了), 而且自己做的这个项目可连接上服务器&#xff0c;供用户购买下载图片&#xff0c;终于有了自信…

android动态壁纸---线条

android SDK2.1中有关于动态壁纸的2个演示DEMO&#xff0c;本人在网上查了相关资料。找到了一个演示DEMO的源代码&#xff0c;希望和大家分享。 同时谢谢提供代码的LZ.并且再此基础上本人做了一个简单的线条动态壁纸,后续还有动态壁纸---球的感应动作实例和大家一起分享学习。…

安卓动态壁纸开发

一般的壁纸设定&#xff0c;只需要在获取壁纸权限后&#xff0c;只需要getWallPagerManager对象来设定壁纸&#xff08;静态&#xff09; 与安卓应用的开发不同&#xff0c;动态壁纸的开发不需要传统的布局文件&#xff0c;也不要活动&#xff08;activity&#xff09;来管理&a…

Android-动态壁纸的实现

前言: 最近遇到了几个很恶心的问题&#xff0c;第一个是手机录制视频发现资源不够用&#xff0c;第二个是手机播放视频发现卡顿。找了半天两个问题的root cause都是手机动态壁纸。我们手机动态壁纸的实现是无论当前壁纸是否处于前台&#xff0c;video instance都是一直活跃的。…

Android自定义动态壁纸开发

看到有些手机酷炫的动态壁纸&#xff0c;有没有好奇过他们是如何实现的&#xff0c;其实我们自己也可以实现。 一、动态壁纸原理 如果你了解使用过SurfaceView的话&#xff0c;那么开发一款动态壁纸对你来说其实非常简单。 动态壁纸的本质其实就是一个服务在维护一个动态壁纸…

Android 壁纸应用之动态壁纸

效果图&#xff0c;图中桌面背景为一段视频 对动态壁纸进行一些设置 在res下创建一个xml文件夹&#xff0c;在创建一个wallpager标签文件 <?xml version"1.0" encoding"utf-8"?> <wallpaper xmlns:android"http://schemas.android.co…

Android动态桌面,设置壁纸篇

最近要做一个动态桌面。就看了下动态桌面有关的东西。 1&#xff0c;通过WallpaperManager设置静态壁纸 1.1先通过以下方法获取到WallpaperManager 1.2这个WallpaperManager里面有多种方式设置静态壁纸&#xff0c;需要android.Manifest.permission.SET_WALLPAPER这个权限不…

Android_动态壁纸介绍

Android的动态壁纸主要用到三个类&#xff1a; android.app.WallpaperManager&#xff1a;这个类主要用于获取系统壁纸的信息。再写动态壁纸的时候用不到。 android.service.wallpaper.WallpaperService&#xff1a;这个类作为服务在运行&#xff0c;同时负责产生一个Engine。 …