请选择 进入手机版 | 继续访问电脑版

北南南北论坛

 找回密码
 立即注册
查看: 39|回复: 0

Android中的墙纸Wallpaper代码简析

[复制链接]

646

主题

898

帖子

2887

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2887
发表于 2017-10-22 18:05:12 | 显示全部楼层 |阅读模式
Android的背景墙纸功能的实现主要由散布在下面几个文件中的类来完成:
(1)frameworks/base/core/java/android/app/WallpaperManager.java
提供了API类,类WallpaperManager的各种函数接口为应用开发者所使用。
(2)frameworks/base/services/java/com/android/server/WallpaperManagerService.java
上述的API类将跨进程调用到system_server进程中的服务类WallpaperManagerService
(3)frameworks/base/core/java/android/service/wallpaper/WallpaperService.java
定义了抽象类WallpaperServic以及内嵌的墙纸绘制引擎基类Engine(子类用于实现墙纸的绘制渲染,若需preview则需创建多个引擎子类实例)。另外,该文件所在文件夹中还定义了几个AIDL接口文件,用于跨进程的调用。
(4)frameworks/base/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
类ImageWallpaper实现了上面的WallpaperServic,同时其里面嵌套类DrawableEngine作为一个引擎子类,用于HomeScreen状态下的墙纸的渲染绘制(见其drawFrameLocked函数以及drawWallpaperWithCanvas和drawWallpaperWithOpenGL,后者用于当机器的内存有512MB时采用硬件加速的OpenGL进行绘制渲染,因为其更耗内存)。在drawFrameLocked中 ,是否真的要绘制更新,则由是否可见(变量mVisible)、是否需要绘制更新(mRedrawNeeded)和位置偏移有改变(mOffsetsChanged)来控制。
背景图片的绘制区域,则在updateWallpaperLocked中通过WallpaperManager获取背景图的位图来得到:
mBackground = mWallpaperManager.getBitmap();
注意:所得到的位图的尺寸则在WallpaperManagerService.java中确定,见WallpaperManagerService的两个函数getWidthHint和getHeightHint。而后两者中的背景图片中的高和寬的值则由WallpaperManagerService.loadSettingsLocked装载手机中的/data/system/wallpaer_info.xml得到(当刷机第一次重启或恢复出厂设置后重启时,该文件被生成,其中的值来自调用者对WallpaperManagerService.setDimensionHints的调用)。但是,第一次启动时,wallpaer_info.xml不存在,也就不采用其里面的值。这时,则采用的是getMaximumSizeDimension,也就是背景图的宽和高由getMaximumSizeDimension决定,代码如下:

  1. // We always want to have some reasonable width hint.
  2. WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
  3. Display d = wm.getDefaultDisplay();
  4. int baseSize = d.getMaximumSizeDimension();
  5. if (mWidth < baseSize) {
  6. mWidth = baseSize;
  7. }
  8. if (mHeight < baseSize) {
  9. mHeight = baseSize;
  10. }
复制代码
这有可能带来背景图不能充满整个屏幕的问题,因为ImageWallpaper.drawFrameLocked会根据surface大小来确定绘制背景:
  1. SurfaceHolder sh = getSurfaceHolder();
  2. final Rect frame = sh.getSurfaceFrame();
  3. final int dw = frame.width();
  4. final int dh = frame.height();
  5. final int availw = dw - mBackgroundWidth;
  6. final int availh = dh - mBackgroundHeight;
  7. int xPixels = availw < 0 ? (int)(availw * mXOffset + .5f) : (availw / 2);
  8. int yPixels = availh < 0 ? (int)(availh * mYOffset + .5f) : (availh / 2);
复制代码

其中mBackgroundWidth和mBackgroundHeight来自WallpaperManagerService中的两个函数getWidthHint和getHeightHint中的变量的值。笔者的一个工程样机的调试log输出如下:
  1. 11-27 09:43:20.030 2041 2041 D ImageWallpaper: dw=1080,dh=960,mBackgroundWidth=960,mBackgroundHeight=960,availw=120,availh=0,xPixels=60,yP
复制代码
通过在WallpaperManagerService.loadSettingsLocked中改变其值的方式可以解决这一问题,但只能针对该产品,不具有普遍性:


  1. diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
  2. index 4925a4e..79cb8b8 100644
  3. --- a/services/java/com/android/server/WallpaperManagerService.java
  4. +++ b/services/java/com/android/server/WallpaperManagerService.java
  5. @@ -388,7 +388,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub {

  6. public void setDimensionHints(int width, int height) throws RemoteException {
  7. checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
  8. -
  9. + Slog.d(“@BillYang_ycg”, “setDimensionHints: width=”+width+”,height=”+height);
  10. if (width }
  11. @@ -809,7 +809,12 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
  12. Display d = wm.getDefaultDisplay();
  13. int baseSize = d.getMaximumSizeDimension();
  14. if (mWidth < baseSize) {
  15. – mWidth = baseSize;
  16. + //The width of background paper is not correct if use getMaximumSizeDimension
  17. + // when first time boot after factory reset: wallpaper dose not cover the whole screen
  18. + //Here I hacked it to correct this issue. Added by @BillYang_ycg, Nov 27 2012
  19. + int w = d.getRawWidth()*2;
  20. + Slog.d(“@BillYang_ycg”,”mWidth=”+w);
  21. + mWidth = w;
  22. }
  23. if (mHeight < baseSize) {
  24. mHeight = baseSize;
复制代码
以上代码基于Android 4.0.4,4.x其它版本如4.1.2应该亦适用。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


手机版|北南南北论坛  

GMT+8, 2017-12-18 14:58 , Processed in 0.060901 second(s), 29 queries .

© 2001-2016 VxWorks6 Inc.

快速回复 返回顶部 返回列表