[关闭]
@Tyhj 2018-01-24T14:01:23.000000Z 字数 3296 阅读 1736

Android动态壁纸解析

Android


原文:https://www.zybuluo.com/Tyhj/note/765583

最近搞了一下Android的动态壁纸,像实现“萤火视频桌面”那样,本来以为很难的,但是了解了一下感觉还是很容易的。首先想要做好一个东西必须先了解其原理,不能代码随便抄一下,改一下就行了,这也是最近去阿里和贝贝网几个大公司面试的感悟。

效果图:http://ac-fgtnb2h8.clouddn.com/82f4e474384b28b5739a.gif

Android壁纸的实现和管理分为三层:

只想了解动态壁纸的看第一个就好了

WallpaperService与Engine

壁纸运行在一个Android服务之中,这个服务的名字叫做WallpaperService。当用户选择了一个壁纸之后,此壁纸所对应的WallpaperService便会启动并开始进行壁纸的绘制工作。Engine是WallpaperService中的一个内部类,实现了壁纸窗口的创建以及Surface的维护工作。这一层次的内容主要体现了壁纸的实现原理。

WallpaperManagerService

这个系统服务用于管理壁纸的运行与切换,并通过WallpaperManager类向外界提供操作壁纸的接口。这一层次主要体现了Android对壁纸的管理方式。

WindowManagerService

用于计算壁纸窗口的Z序、可见性以及为壁纸应用窗口动画。这一层次主要体现了Android对壁纸窗口的管理方式。

实现

首先静态壁纸是很简单的,大概就是如下几种方法,我也没有试过,

  • 使用WallpaperManager的setResource(int ResourceID)方法
  • 使用WallpaperManager的setBitmap(Bitmap bitmap)方法
  • 使用WallpaperManager的setStream(InputStream data)方法
  1. //需要权限
  2. <uses-permission android:name = "android.permission.SET_WALLPAPER"/>
  3. WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
  4. try {
  5. wallpaperManager.setResource(R.drawable.picture);
  6. } catch (IOException e) {
  7. e.printStackTrace();
  8. }

动态壁纸

刚才讲了,动态壁纸就是一个服务,我们先创建一个服务并继承WallpaperService。这个服务里面有个内部类Engine,实现了壁纸窗口的创建以及Surface的维护工作。就是说我们可以获取到一个SurfaceHolder,拿到这个东西就好办了,我们可以在上面画自己想要的东西或者把视频输出到上面去。

我就直接上代码了

设置视频桌面

  1. public class VideoWallpaper extends WallpaperService {
  2. private MediaPlayer mp;
  3. private int progress = 0;
  4. //这里就是返回我们自定义的Engine
  5. @Override
  6. public Engine onCreateEngine() {
  7. return new VideoEngine();
  8. }
  9. //自定义Engine
  10. class VideoEngine extends Engine {
  11. @Override
  12. public void onCreate(SurfaceHolder surfaceHolder) {
  13. super.onCreate(surfaceHolder);
  14. //可以设置点击事件
  15. setTouchEventsEnabled(true);
  16. }
  17. @Override
  18. public void onSurfaceCreated(SurfaceHolder holder) {
  19. //把视频输出到SurfaceHolder上面
  20. if (mp != null && mp.isPlaying())
  21. return;
  22. //可以设置SD卡的视频
  23. mp = MediaPlayer.create(getApplicationContext(), R.raw.bird);
  24. //这句话并不简单
  25. mp.setSurface(holder.getSurface());
  26. //重复播放
  27. mp.setLooping(true);
  28. mp.start();
  29. }
  30. //当桌面不可见的时候的处理
  31. @Override
  32. public void onVisibilityChanged(boolean visible) {
  33. if (visible) {
  34. if (mp != null)
  35. return;
  36. mp = MediaPlayer.create(getApplicationContext(), R.raw.bird);
  37. mp.setSurface(getSurfaceHolder().getSurface());
  38. mp.setLooping(true);
  39. //获取进度播放
  40. mp.seekTo(progress);
  41. mp.start();
  42. } else {
  43. if (mp != null && mp.isPlaying()) {
  44. //保存进度
  45. progress = mp.getCurrentPosition();
  46. mp.stop();
  47. mp.release();
  48. mp = null;
  49. }
  50. }
  51. }
  52. @Override
  53. public void onDestroy() {
  54. if (mp != null) {
  55. mp.stop();
  56. mp.release();
  57. }
  58. super.onDestroy();
  59. }
  60. }
  61. }

上面的代码并不复杂,只是自己做的时候会遇到一些问题,首在不能在Engine的onCreate的方法里面设置视频播放,应该是SurfaceHolder还没有创建吧,还有mediaPlayer设置输出的Surface

  1. //正确设置代码
  2. mediaPlayer.setSurface(holder.getSurface());
  3. //一般是这样设置,这里这样设置报错
  4. mediaPlayer.setDisplay(holder);

是Service那肯定要注册的

  1. <service
  2. android:name="ui.service.VideoWallpaper"
  3. android:permission="android.permission.BIND_WALLPAPER">
  4. <!-- 为动态壁纸配置intent-filter -->
  5. <intent-filter>
  6. <action android:name="android.service.wallpaper.WallpaperService" />
  7. </intent-filter>
  8. <!-- 为动态壁纸配置meta-data -->
  9. <meta-data
  10. android:name="android.service.wallpaper"
  11. android:resource="@xml/livewallpapervideo" />
  12. </service>

然后关于"livewallpapervideo.xml",就是一个正常的布局文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:settingsActivity="ui.activity.LiveWallPreference"
  4. android:thumbnail="@mipmap/ic_video"
  5. android:description="@string/wallpaper_description4"
  6. />

里面有个settingsActivity,这个东西我不知道有什么用,就是随便一个Activity,你也要注册这个Activity,

其他玩法

除了将视频作为壁纸以为还可以将GIF作为壁纸,将摄像头获取到的图象作为壁纸,甚至直接自己在SurfaceHolder自己画东西都可以,道理都是一样的

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注