2011.09.21——— android 动态壁纸开发
参考: http://www.ophonesdn.com/article/show/278
resources/articles/live-wallpapers.html
自己做了一个非常简单的 只是想了解过程 源码见附件 步骤如下:
1、新建一个Android工程 然后进入工程的/res/文件夹,删除layout这个文件夹,当然里面的main.xml也会被删除的,对于Live Wallpaper来说传统的布局文件是不需要的。
2、在res下面新建一个xml文件夹 然后新建一个mylivewallpaper.xml 内容如下:
这里的android:thumbnail值得是你这个动态壁纸的小图标 会在你选着动态壁纸的时候出现 如下图:
这个可以自己选一个好看一点的
3、开始编写代码了 直接看吧
实现的效果是一个动态改变的时间 如下图:
我们一一来解释:
onCreateEngine() :
启动一个WallpaperService.Engine 这个engine才是负责绘制壁纸以及响应与用户交互事件的核心部件 这个方法也是必须要重写的 并且是WallpaperService和service的主要区别
onOffsetsChanged():
这个一般在几个屏幕滑动的时候调用 而且 当你拖动A屏幕向B屏幕过度时 会随着B屏幕的显示面积的变大或者变小一直调用这个方法
onVisibilityChanged()
这个是屏幕显示或者不显示的时候调用的 必须完全覆盖屏幕才会调用
onCommand()
可以给壁纸发送一些命令 让其执行
onTouchEvent()
处理壁纸的点击时间的
setTouchEventsEnabled(true)
作用是使壁纸能响应touch event,默认是false
其他的看名字应该就知道了 呵呵
这里也说下Engine的惯用写法吧
4、在AndroidManifes.xml里面注册service
除了
5、自己的一些关于方法执行顺序的测试信息:
当进入改壁纸的设置页面 但是还没有设置时
09-21 07:55:05.575: INFO/System.out(1337): service onCreate
09-21 07:55:05.614: INFO/System.out(1337): service onCreateEngine
09-21 07:55:05.634: INFO/System.out(1337): MyEngine
09-21 07:55:05.663: INFO/System.out(1337): onCreate
09-21 07:55:05.746: INFO/System.out(1337): onSurfaceCreated
09-21 07:55:05.753: INFO/System.out(1337): onSurfaceChanged
09-21 07:55:05.785: INFO/System.out(1337): onVisibilityChanged
当点击设置壁纸按钮后
09-21 07:55:19.434: INFO/System.out(1337): onTouchEvent
09-21 07:55:19.574: INFO/System.out(1337): onTouchEvent
09-21 07:55:20.283: INFO/System.out(1337): service onCreateEngine
09-21 07:55:20.294: INFO/System.out(1337): MyEngine
09-21 07:55:20.304: INFO/System.out(1337): onCreate
09-21 07:55:20.414: INFO/System.out(1337): onSurfaceCreated
09-21 07:55:20.424: INFO/System.out(1337): onSurfaceChanged
09-21 07:55:20.443: INFO/System.out(1337): onVisibilityChanged
09-21 07:55:20.443: INFO/System.out(1337): onoffsetsChanged
09-21 07:55:20.863: INFO/System.out(1337): onVisibilityChanged
09-21 07:55:21.305: INFO/System.out(1337): onSurfaceDestoryed
09-21 07:55:21.333: INFO/System.out(1337): onDestroy
在壁纸上面点击
09-21 07:55:34.654: INFO/System.out(1337): onTouchEvent
09-21 07:55:34.754: INFO/System.out(1337): onTouchEvent
09-21 07:55:34.754: INFO/System.out(1337): onCommand
启动其他程序 完全覆盖屏幕
09-21 07:56:03.855: INFO/System.out(1337): onTouchEvent
09-21 07:56:03.884: INFO/System.out(1337): onTouchEvent
09-21 07:56:04.494: INFO/System.out(1337): onVisibilityChanged
设置其他壁纸 代替自己的壁纸
09-21 07:56:34.893: INFO/System.out(1337): onSurfaceDestoryed
09-21 07:56:34.893: INFO/System.out(1337): onDestroy
09-21 07:56:34.953: INFO/System.out(1337): service onDestory
另:Engine的生命周期:
参考: http://www.ophonesdn.com/article/show/278
resources/articles/live-wallpapers.html
自己做了一个非常简单的 只是想了解过程 源码见附件 步骤如下:
1、新建一个Android工程 然后进入工程的/res/文件夹,删除layout这个文件夹,当然里面的main.xml也会被删除的,对于Live Wallpaper来说传统的布局文件是不需要的。
2、在res下面新建一个xml文件夹 然后新建一个mylivewallpaper.xml 内容如下:
<?xml version="1.0" encoding="utf-8"?> <wallpaper xmlns:android="http://schemas.android.com/apk/res/android" android:thumbnail="@drawable/icon" />
这里的android:thumbnail值得是你这个动态壁纸的小图标 会在你选着动态壁纸的时候出现 如下图:
这个可以自己选一个好看一点的
3、开始编写代码了 直接看吧
package com.lp.wallpaper; import java.text.SimpleDateFormat; import java.util.Date; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.os.Handler; import android.service.wallpaper.WallpaperService; import android.view.MotionEvent; import android.view.SurfaceHolder; public class MyWallpaper extends WallpaperService{ private Handler handler = new Handler(); @Override public void onCreate() { System.out.println("service onCreate"); super.onCreate(); } @Override public void onDestroy() { System.out.println("service onDestory"); super.onDestroy(); } @Override public Engine onCreateEngine() { System.out.println("service onCreateEngine"); return new MyEngine(); } private class MyEngine extends Engine{ private float x = 200; private float y = 300; private Paint mPaint; private boolean mVisible = false; private Runnable drawThread = new Runnable() { public void run() { drawWallpaper(); } }; public MyEngine(){ System.out.println("MyEngine"); mPaint = new Paint(); mPaint.setColor(Color.RED); mPaint.setAntiAlias(true); mPaint.setStrokeWidth(4); mPaint.setStyle(Paint.Style.STROKE); mPaint.setTextSize(24); } @Override public Bundle onCommand(String action, int x, int y, int z, Bundle extras, boolean resultRequested) { // TODO Auto-generated method stub System.out.println("onCommand"); return super.onCommand(action, x, y, z, extras, resultRequested); } @Override public void onCreate(SurfaceHolder surfaceHolder) { System.out.println("onCreate"); super.onCreate(surfaceHolder); //作用是使壁纸能响应touch event,默认是false setTouchEventsEnabled(true); } @Override public void onDestroy() { System.out.println("onDestroy"); super.onDestroy(); handler.removeCallbacks(drawThread); } @Override public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) { // TODO Auto-generated method stub System.out.println("onoffsetsChanged"); super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixelOffset, yPixelOffset); } @Override public void onVisibilityChanged(boolean visible) { System.out.println("onVisibilityChanged"); mVisible = visible; if (visible) { //开始 handler.postDelayed(drawThread, 50); } else { handler.removeCallbacks(drawThread); } } @Override public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { System.out.println("onSurfaceChanged"); // TODO Auto-generated method stub super.onSurfaceChanged(holder, format, width, height); } @Override public void onSurfaceCreated(SurfaceHolder holder) { System.out.println("onSurfaceCreated"); super.onSurfaceCreated(holder); } @Override public void onSurfaceDestroyed(SurfaceHolder holder) { System.out.println("onSurfaceDestoryed"); // TODO Auto-generated method stub super.onSurfaceDestroyed(holder); handler.removeCallbacks(drawThread); } @Override public void onTouchEvent(MotionEvent event) { System.out.println("onTouchEvent"); // TODO Auto-generated method stub super.onTouchEvent(event); } private void drawWallpaper() { SurfaceHolder holder = getSurfaceHolder(); Canvas canvas = holder.lockCanvas(); drawTime(canvas); holder.unlockCanvasAndPost(canvas); //循环执行 handler.postDelayed(drawThread, 50); } private void drawTime(Canvas canvas) { Date date = new Date(System.currentTimeMillis()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String dataStr = sdf.format(date); canvas.save(); canvas.drawColor(0xff00ff00); canvas.drawText(dataStr, x, y, mPaint); canvas.restore(); } } }
实现的效果是一个动态改变的时间 如下图:
我们一一来解释:
onCreateEngine() :
启动一个WallpaperService.Engine 这个engine才是负责绘制壁纸以及响应与用户交互事件的核心部件 这个方法也是必须要重写的 并且是WallpaperService和service的主要区别
onOffsetsChanged():
这个一般在几个屏幕滑动的时候调用 而且 当你拖动A屏幕向B屏幕过度时 会随着B屏幕的显示面积的变大或者变小一直调用这个方法
onVisibilityChanged()
这个是屏幕显示或者不显示的时候调用的 必须完全覆盖屏幕才会调用
onCommand()
可以给壁纸发送一些命令 让其执行
onTouchEvent()
处理壁纸的点击时间的
setTouchEventsEnabled(true)
作用是使壁纸能响应touch event,默认是false
其他的看名字应该就知道了 呵呵
这里也说下Engine的惯用写法吧
private class MyEngine extends Engine{ //这里定义一个线程 private Runnable drawThread = new Runnable() { public void run() { drawWallpaper(); } }; //构造方法里面 一般初始化Paint对象 public MyEngine(){ System.out.println("MyEngine"); mPaint = new Paint(); mPaint.setColor(Color.RED); mPaint.setAntiAlias(true); mPaint.setStrokeWidth(4); mPaint.setStyle(Paint.Style.STROKE); mPaint.setTextSize(24); } //这里 调用setTouchEventsEnabled(true);即可 @Override public void onCreate(SurfaceHolder surfaceHolder) { System.out.println("onCreate"); super.onCreate(surfaceHolder); //作用是使壁纸能响应touch event,默认是false setTouchEventsEnabled(true); } //取消callback @Override public void onDestroy() { System.out.println("onDestroy"); super.onDestroy(); handler.removeCallbacks(drawThread); } //当显示的时候 绑定callback 不显示时 取消callback @Override public void onVisibilityChanged(boolean visible) { System.out.println("onVisibilityChanged"); mVisible = visible; if (visible) { //开始 handler.postDelayed(drawThread, 50); } else { handler.removeCallbacks(drawThread); } } @Override public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { System.out.println("onSurfaceChanged"); // TODO Auto-generated method stub super.onSurfaceChanged(holder, format, width, height); } @Override public void onSurfaceCreated(SurfaceHolder holder) { System.out.println("onSurfaceCreated"); super.onSurfaceCreated(holder); } //取消callback @Override public void onSurfaceDestroyed(SurfaceHolder holder) { System.out.println("onSurfaceDestoryed"); // TODO Auto-generated method stub super.onSurfaceDestroyed(holder); handler.removeCallbacks(drawThread); } //处理点击事件 比如说 点击时 出现水波等 @Override public void onTouchEvent(MotionEvent event) { System.out.println("onTouchEvent"); // TODO Auto-generated method stub super.onTouchEvent(event); } //得到surfaceholder和canvas 并调用核心处理方法 private void drawWallpaper() { SurfaceHolder holder = getSurfaceHolder(); Canvas canvas = holder.lockCanvas(); drawTime(canvas); holder.unlockCanvasAndPost(canvas); //循环执行 handler.postDelayed(drawThread, 50); } //核心处理方法 private void drawTime(Canvas canvas) { } }
4、在AndroidManifes.xml里面注册service
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.lp.wallpaper"> <uses-sdk android:minSdkVersion="7" /> <uses-feature android:name="android.software.live_wallpaper" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <service android:label="@string/app_name" android:name=".MyWallpaper" 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>
除了
android:resource="@xml/mylivewallpaper"是可以自己修改 其他的都是必须得 特别强调几个:
<uses-sdk android:minSdkVersion="7" /> <uses-feature android:name="android.software.live_wallpaper" /> android:permission="android.permission.BIND_WALLPAPER"
5、自己的一些关于方法执行顺序的测试信息:
当进入改壁纸的设置页面 但是还没有设置时
09-21 07:55:05.575: INFO/System.out(1337): service onCreate
09-21 07:55:05.614: INFO/System.out(1337): service onCreateEngine
09-21 07:55:05.634: INFO/System.out(1337): MyEngine
09-21 07:55:05.663: INFO/System.out(1337): onCreate
09-21 07:55:05.746: INFO/System.out(1337): onSurfaceCreated
09-21 07:55:05.753: INFO/System.out(1337): onSurfaceChanged
09-21 07:55:05.785: INFO/System.out(1337): onVisibilityChanged
当点击设置壁纸按钮后
09-21 07:55:19.434: INFO/System.out(1337): onTouchEvent
09-21 07:55:19.574: INFO/System.out(1337): onTouchEvent
09-21 07:55:20.283: INFO/System.out(1337): service onCreateEngine
09-21 07:55:20.294: INFO/System.out(1337): MyEngine
09-21 07:55:20.304: INFO/System.out(1337): onCreate
09-21 07:55:20.414: INFO/System.out(1337): onSurfaceCreated
09-21 07:55:20.424: INFO/System.out(1337): onSurfaceChanged
09-21 07:55:20.443: INFO/System.out(1337): onVisibilityChanged
09-21 07:55:20.443: INFO/System.out(1337): onoffsetsChanged
09-21 07:55:20.863: INFO/System.out(1337): onVisibilityChanged
09-21 07:55:21.305: INFO/System.out(1337): onSurfaceDestoryed
09-21 07:55:21.333: INFO/System.out(1337): onDestroy
在壁纸上面点击
09-21 07:55:34.654: INFO/System.out(1337): onTouchEvent
09-21 07:55:34.754: INFO/System.out(1337): onTouchEvent
09-21 07:55:34.754: INFO/System.out(1337): onCommand
启动其他程序 完全覆盖屏幕
09-21 07:56:03.855: INFO/System.out(1337): onTouchEvent
09-21 07:56:03.884: INFO/System.out(1337): onTouchEvent
09-21 07:56:04.494: INFO/System.out(1337): onVisibilityChanged
设置其他壁纸 代替自己的壁纸
09-21 07:56:34.893: INFO/System.out(1337): onSurfaceDestoryed
09-21 07:56:34.893: INFO/System.out(1337): onDestroy
09-21 07:56:34.953: INFO/System.out(1337): service onDestory
另:Engine的生命周期: