之前的一个项目开发的支持锁屏壁纸和桌面壁纸。
开始时,有考虑从lockscreen做文章。在锁屏时,切换锁屏壁纸,进入home,再切换home壁纸。效果很差,卡顿,效率极低。
后来只能从WallpaperManager,WindowManager从考虑。最终实现了锁屏壁纸,效果很好。
WindowManagerService管理着各种窗口,Launcher, Lockscreen, InputMethodWindow, 以及其他的应用APP窗口。对于WindowManagerService来说他们都是一个个Window。ActivityManagerService调整这些Window的Z轴位置,以及可见性。来达到我们所看到的效果。因为android默认支持Launcher壁纸。所以在WindowManagerService的windows里只能看到这一个wallpaper。所以要再支持lockscreen wallpaper。只要再启动一个wallpaper window。当lockscreen时,将lockscreen wallpaper window, 调整到home wallpaper的窗口上面。就OK了。
首先看针对WindowManagerService的修改:
我们在WindowManagerService.java里添加支持lockscreen wallpaper 窗口方法addWallpaperWindowToken(),以及lockscreen wallpaper窗口变量mLockScreenWallpaperWindowToken。
这样WallpaperManagerService就可以调用WindowManagerService.addWallpaperWindowToken()来把Lockscreen wallpaper window 添加到系统的窗口列表中。
设置了Lockscreen Wallpaper 后,在adjustWallpaperWindowsLocked() 方法里,就可以对Lockscreen Wallpaper 和Home Wallpaper这两个壁纸窗口的位置进行调整。
如果当前的窗口为Lockscreen,就将Lockscreen Wallpaper调整到Home Wallpaper上面。反之,则调整到下面。
怎么区分当前要显示的是Lockscreen还是Home?
通过获取当前需要显示wallpaper的窗口名称,Lockscreen 为 ,Keyguard 而home则可能为Launcher2等。
这样通过名称来区分,下述代码中1875行,String title = mWallpaperTarget.getWindowTitle();
是在WindowState中增加的一个方法,用于返回该窗口title。
在removeWindowToken()方法里,还有将wallpaper window token 从mWallpaperTokens里删除,否则会有重复的Lockscreen wallpaper 窗口。
代码如下:
if (wtoken.windowType == TYPE_WALLPAPER) {
mWallpaperTokens.remove(wtoken);
}
对WindowManagerService的改动,到这里就结束了。这部分改动也是最关键的部分。
接下来看下上面提到的WindowState的改动,增加一个方法getWindowTitle()返回窗口title:
代码如下:
接着看对WallpaperManagerService的改动,改动首先从systemReady()开始。因为系统启动后,会调用该方法。
可以仿照启动Home Wallpaper的code, 再开启一个Lockscreen Wallpaper。
(锁屏壁纸功能是在android 4.3 上开发的,framework部分的改动代码,在patch 文件lockscreen_independent_wallpaper.patch里。可从下面连接下载
http://download.csdn.net/detail/lavashengpeng/7469425)
开启Lockscreen Wallpaper组件后,就可以调用WindowManagerService.java里添加支持lockscreen wallpaper 窗口方法addWallpaperWindowToken()将锁屏壁纸窗口添加到window列表中。
开启Lockscreen Wallpaper组件时,要设置默认的组件。同样copy一份Home wallpaper的代码即可。
Home wallpaper default component: /SystemUI/src/com/android/systemui/ImageWallpaper.java
我们copy 一份 /SystemUI/src/com/android/systemui/ImageWallpaperLockScreen.java,对里面的代码稍加改动,改动点就是对壁纸图片的bitmap使用,加上 synchronize锁,不然会导致出错。
接下来就是添加接口供应用层调用,在WallpaperManager添加setLockscreenWallpaper(),setLockscreenWallpaperComponent(),getLockScreenWallpaper()等,以及需要改动IWindowManager.aidl添加addWallpaperWindowToken()接口。
涉及到的文件如下:
core/java/android/app/IWallpaperManager.aidl
core/java/android/app/WallpaperManager.java
core/java/android/view/IWindowManager.aidl
tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
这样framework部分的改动就完成了。应用这边就可以调用接口,设置锁屏壁纸了。