在Android中,壁纸分为静态与动态两种。静态壁纸是一张图片,而动态壁纸则以动画为表现形式,或者可以对用户的操作作出反应。这两种形式看似差异很大,其实二者的本质是统一的。它们都以一个Service的形式运行在系统后台,并在一个类型为TYPE_WALLPAPER的窗口上绘制内容。进一步讲,静态壁纸是一种特殊的动态壁纸,它仅在窗口上渲染一张图片,并且不会对用户的操作作出反应。

一、 初识Android壁纸

在Android中,壁纸分为静态与动态两种。静态壁纸是一张图片,而动态壁纸则以动画为表现形式,或者可以对用户的操作作出反应。这两种形式看似差异很大,其实二者的本质是统一的。它们都以一个Service的形式运行在系统后台,并在一个类型为TYPE_WALLPAPER的窗口上绘制内容。进一步讲,静态壁纸是一种特殊的动态壁纸,它仅在窗口上渲染一张图片,并且不会对用户的操作作出反应。因此本章将首先通过动态壁纸的实现讨论Android壁纸的实现与管理原理,然后在对静态壁纸的实现做介绍。

Android壁纸的实现与管理分为三个层次:

1、**WallpaperService和Engine(壁纸的实现原理):**同SystemUI一样,壁纸运行在一个Android服务之中,这个服务的名字叫做WallpaperService。当用户选择了一个壁纸之后,此壁纸所对应的WallpaperService便会启动并开始进行壁纸的绘制工作,因此继承并定制WallpaperService是开发者进行壁纸开发的第一步。Engine是WallpaperService中的一个内部类,实现了壁纸窗口的创建以及Surface的维护工作。另外,Engine提供了可供子类重写的一系列回调,用于通知壁纸开发者关于壁纸的生命周期、Surface状态的变化以及对用户的输入事件进行响应。可以说,Engine类是壁纸实现的核心所在。壁纸开发者需要继承Engine类,并重写其提供的回调以完成壁纸的开发。这一层次的内容主要体现了壁纸的实现原理。

2、**WallpaperManagerService(对壁纸的管理方式):**这个系统服务用于管理壁纸的运行与切换,并通过WallpaperManager类向外界提供操作壁纸的接口。当通过WallpaperManagaer的接口进行壁纸的切换时,WallpaperManagerService会取消当前壁纸的WallpaperService的绑定,并启动新壁纸的WallpaperService。另外,Engine类进行窗口创建时所使用的窗口令牌也是由WallpaperManagerService提供的。这一层次主要体现了Android对壁纸的管理方式。

3、**WindowManagerService(对壁纸窗口的管理):**用于计算壁纸窗口的Z序、可见性以及为壁纸应用窗口动画。壁纸窗口(TYPE_WALLPAPER)的Z序计算不同于其他类型的窗口。其他窗口依照其类型会有固定的mBaseLayer以及mSubLayer,并结合它们所属的Activity的顺序或创建顺序进行Z序的计算,因此这些窗口的Z序相对固定。而壁纸窗口则不然,它的Z序会根据FLAG_SHOW_WALLPAPER标记在其它窗口的LayoutParams.flags中的存在情况而不断地被调整。这一层次主要体现了Android对壁纸窗口的管理方式。

二、动态壁纸的设置流程

1、通过调用WallpaperManager的setWallpaperComponent方法可以帮我们开启自定义动态壁纸。

frameworks/base/core/java/android/app/WallpaperManager.java

public class WallpaperManager {@SystemApi@RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT)public boolean setWallpaperComponent(ComponentName name) {return setWallpaperComponent(name, mContext.getUserId());}@RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT)@UnsupportedAppUsagepublic boolean setWallpaperComponent(ComponentName name, int userId) {if (sGlobals.mService == null) {Log.w(TAG, "WallpaperService not running");throw new RuntimeException(new DeadSystemException());}try {//通过binder调用WallpaperManagerService的setWallpaperComponentChecked方法sGlobals.mService.setWallpaperComponentChecked(name, mContext.getOpPackageName(),userId);return true;} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}private static class Globals extends IWallpaperManagerCallback.Stub {private final IWallpaperManager mService;//WallpaperManagerService的binder代理对象}
}

类型为Globals的sGlobals对象,内部属性mService是一个代理者,setWallpaperComponent最终会调用WallpaperManagerService的setWallpaperComponentChecked方法。

2、WallpaperManagerService的setWallpaperComponentChecked方法如下所示。

frameworks/base/core/java/android/app/WallpaperManager.java

public class WallpaperManagerService extends IWallpaperManager.Stubimplements IWallpaperManagerService {@Overridepublic void setWallpaperComponentChecked(ComponentName name, String callingPackage,int userId) {//权限验证if (isWallpaperSupported(callingPackage) && isSetWallpaperAllowed(callingPackage)) {setWallpaperComponent(name, userId);}}//设置动态壁纸private void setWallpaperComponent(ComponentName name, int userId) {userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,false /* all */, true /* full */, "changing live wallpaper", null /* pkg */);//权限检测checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);int which = FLAG_SYSTEM;boolean shouldNotifyColors = false;WallpaperData wallpaper;//壁纸数据synchronized (mLock) {Slog.v(TAG, "setWallpaperComponent name=" + name);wallpaper = mWallpaperMap.get(userId);if (wallpaper == null) {throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);}final long ident = Binder.clearCallingIdentity();// Live wallpapers can't be specified for keyguard.  If we're using a static// system+lock image currently, migrate the system wallpaper to be a lock-only// image as part of making a different live component active as the system// wallpaper.if (mImageWallpaper.equals(wallpaper.wallpaperComponent)) {if (mLockWallpaperMap.get(userId) == null) {// We're using the static imagery and there is no lock-specific image in place,// therefore it's a shared system+lock image that we need to migrate.Slog.i(TAG, "Migrating current wallpaper to be lock-only before"+ "updating system wallpaper");migrateSystemToLockWallpaperLocked(userId);}}// New live wallpaper is also a lock wallpaper if nothing is setif (mLockWallpaperMap.get(userId) == null) {which |= FLAG_LOCK;}try {wallpaper.imageWallpaperPending = false;boolean same = changingToSame(name, wallpaper);//启动新壁纸的WallpaperServiceif (bindWallpaperComponentLocked(name, false, true, wallpaper, null)) {if (!same) {wallpaper.primaryColors = null;} else {if (wallpaper.connection != null) {wallpaper.connection.forEachDisplayConnector(displayConnector -> {try {if (displayConnector.mEngine != null) {displayConnector.mEngine.dispatchWallpaperCommand(COMMAND_REAPPLY, 0, 0, 0, null);}} catch (RemoteException e) {Slog.w(TAG, "Error sending apply message to wallpaper", e);}});}}wallpaper.wallpaperId = makeWallpaperIdLocked();notifyCallbacksLocked(wallpaper);shouldNotifyColors = true;}} finally {Binder.restoreCallingIdentity(ident);}}if (shouldNotifyColors) {notifyWallpaperColorsChanged(wallpaper, which);notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);}}
}

参考文章:https://www.kancloud.cn/wizardforcel/deepin-android-vol3/122360
https://www.freesion.com/article/6656482862/

Android 12系统源码_系统壁纸(二)动态壁纸的设置流程相关推荐

  1. 赚多多V10自动抢单系统源码_派单连单管理新增设置订单佣金

    收到用户反馈需要连单设置时需要单独设置佣金,于是针对派单连单管理这一块做了个调整,新增了设置佣金栏目. 功能说明:派单时有设置佣金会按照设置的佣金进行计算,设置佣金为单商品价格的百分比,比如设置价格为 ...

  2. Android 12系统源码_系统壁纸(一)系统壁纸的原理分析

    前言 在Android中,壁纸分为静态与动态两种.静态壁纸是一张图片,而动态壁纸则以动画为表现形式,或者可以对用户的操作作出反应.这两种形式看似差异很大,其实二者的本质是统一的.它们都以一个Servi ...

  3. android系统源码之 系统应用安装过程(下)

    android系统源码之 系统应用安装过程(上) :http://blog.csdn.net/king1425/article/details/70135813 下图是PackageParser主要数 ...

  4. 英皇cms影视网站系统源码_多种模板_自带采集_支持APP+pc+wap三端_(亲测可用有搭建教程)

    源码介绍 影视网站源码,自带采集功能多入口,带会员,卡密,代理等功能,免费模板可自选 支持三端:pc+wap+app端,支持视频下载,有直播,开通会员等功能,带短视频,论坛等等功能自行搭建查看,一款功 ...

  5. 小鱼授权系统源码_无加密

    介绍: 小鱼授权系统源码_无加密 网盘下载地址: https://zijiewangpan.com/yVgkJXzhFYU 图片:

  6. 辰光php客服系统源码_仿伊对梵高相亲交友系统产品特性以及构成基础,你了解吗?...

    梵高婚恋相亲交友系统,顾名思义是一个集相亲.交友于一身的婚恋社交App.可搭建平台,出售源码. 仿伊对梵高相亲交友系统开发特色及应用场景 1.仿伊对梵高相亲交友系统开发特色:直播间在线相亲,红娘在线视 ...

  7. java计算机毕业设计特色农产品供需销售系统源码+数据库+系统+lw文档+mybatis+运行部署

    java计算机毕业设计特色农产品供需销售系统源码+数据库+系统+lw文档+mybatis+运行部署 java计算机毕业设计特色农产品供需销售系统源码+数据库+系统+lw文档+mybatis+运行部署 ...

  8. java计算机毕业设计大学生校园兼职系统源码+数据库+系统+lw文档+部署

    java计算机毕业设计大学生校园兼职系统源码+数据库+系统+lw文档+部署 java计算机毕业设计大学生校园兼职系统源码+数据库+系统+lw文档+部署 本源码技术栈: 项目架构:B/S架构 开发语言: ...

  9. java计算机毕业设计苗木购销系统源码+数据库+系统+lw文档+mybatis+运行部署

    java计算机毕业设计苗木购销系统源码+数据库+系统+lw文档+mybatis+运行部署 java计算机毕业设计苗木购销系统源码+数据库+系统+lw文档+mybatis+运行部署 本源码技术栈: 项目 ...

最新文章

  1. android layout属性介绍
  2. 在Spring Framework中@Inject和@Autowired有什么区别? 在什么条件下使用哪一个?
  3. vba 定义类_VBA|自定义类型、枚举类型和类模块及其使用
  4. 使用 pipe 在程序正文中捕获和处理信号
  5. centos文本查看及处理相关的常用命令
  6. kmp oj 亲和串
  7. 将ABAP数据库表的定义导入到PostgreSQL
  8. extjs2.0 文件上传_extjs数据存储与传输
  9. 《是碰巧还是执着?python所阅读的每一场知识点,唯一的共同点就是——参赛选手中,有详解Python的装饰器!》
  10. AOP之proceedingjoinpoint和joinpoint区别(获取各对象备忘)、动态代理机制及获取原理代理对象、获取Mybatis Mapper接口原始对象...
  11. python 求组合数最快方法_快速计算投资组合波动率的方法
  12. topcoder srm 686 div1 -3
  13. CAD如何完成10以上带圈序号的输入?
  14. 使用软件测试路由器性能报告,路由器软件测试报告
  15. 黑马程序员:Java学习路线图上线了
  16. 怎么在计算机网络上添加文件,教你win7如何设置网络共享文件夹
  17. C#中使用Regex类来实现正则表达式
  18. 2022腾讯云服务器租用费用价格表(轻量和CVM精准报价)
  19. 《Android源码设计模式》之策略模式
  20. 花了1晚上diy的matlab解数独算法,很好理解!

热门文章

  1. 2018年长沙理工大学第十三届程序设计竞赛 - zzq的离散数学教室1
  2. 野蛮时代一直显示无法连接服务器,野蛮时代手游
  3. 打开tomcat指定服务器未安装,处理tomcat7提示“指定的服务未安装”的方案
  4. 产品三维动画成为新一代营销手段
  5. 玩吃鸡提示显卡内存不足闪退的解决办法
  6. 怒砸一亿,工银二维码支付
  7. 中望3D 2021 “拔模”命令使用曲面做中性面
  8. mysql m admin_mysqladmin 详解
  9. LabVIEW中创建毫秒时间标识
  10. 国产蓝牙耳机:什么牌子蓝牙耳机听歌音质最好?