zoukankan      html  css  js  c++  java
  • Android 默认壁纸 简单分析


    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决定,代码如下:

    // We always want to have some reasonable width hint.
    WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
    Display d = wm.getDefaultDisplay();
    int baseSize = d.getMaximumSizeDimension();
    if (mWidth < baseSize) {
    mWidth = baseSize;
    }
    if (mHeight < baseSize) {
    mHeight = baseSize;
    }

    这有可能带来背景图不能充满整个屏幕的问题,因为ImageWallpaper.drawFrameLocked会根据surface大小来确定绘制背景:

    SurfaceHolder sh = getSurfaceHolder();
    final Rect frame = sh.getSurfaceFrame();
    final int dw = frame.width();
    final int dh = frame.height();
    final int availw = dw - mBackgroundWidth;
    final int availh = dh - mBackgroundHeight;
    int xPixels = availw < 0 ? (int)(availw * mXOffset + .5f) : (availw / 2);
    int yPixels = availh < 0 ? (int)(availh * mYOffset + .5f) : (availh / 2);

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

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

    public void setDimensionHints(int width, int height) throws RemoteException {
    checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
    -
    + Slog.d(“@BillYang_ycg”, “setDimensionHints: width=”+width+”,height=”+height);
    if (width }
    @@ -809,7 +809,12 @@ class WallpaperManagerService extends IWallpaperManager.Stub {
    Display d = wm.getDefaultDisplay();
    int baseSize = d.getMaximumSizeDimension();
    if (mWidth < baseSize) {
    – mWidth = baseSize;
    + //The width of background paper is not correct if use getMaximumSizeDimension
    + // when first time boot after factory reset: wallpaper dose not cover the whole screen
    + //Here I hacked it to correct this issue. Added by @BillYang_ycg, Nov 27 2012
    + int w = d.getRawWidth()*2;
    + Slog.d(“@BillYang_ycg”,”mWidth=”+w);
    + mWidth = w;
    }
    if (mHeight < baseSize) {
    mHeight = baseSize;

    以上代码基于Android 4.4.4 分析。




  • 相关阅读:
    在使用SMO时,检索IsSystemObject属性将导致性能急剧下降的解决方法
    在没有安装.NET Framework 3.5的机器上使用LINQ等特性
    我的网站中的组织层次结构图信息与AD的同步问题
    有关视图状态(ViewState)的一些问题
    窗体控件visible属性问题
    SiteMapNode的几个特殊属性
    创建本地数据库时发生错误及其解决方案
    在基于Windows验证的Web应用程序中检索当前用户的所有角色
    在数据库恢复之前将数据库置为单用户模式
    将ASP.NET网站嵌入到MOSS站点下面的做法
  • 原文地址:https://www.cnblogs.com/liulaolaiu/p/11744522.html
Copyright © 2011-2022 走看看