Android 13 取色引擎详解

server/2025/2/3 16:16:15/

1、 应用如何获取壁纸颜色?

1.1、调用getWallpaperColors获取壁纸颜色

其实WallpaperManager从很早之前就提供了getWallpaperColors接口
/frameworks/base/core/java/android/app/WallpaperManager.java

...@UnsupportedAppUsagepublic @Nullable WallpaperColors getWallpaperColors(int which, int userId) {StrictMode.assertUiContext(mContext, "getWallpaperColors");return sGlobals.getWallpaperColors(which, userId, mContext.getDisplayId());}
...WallpaperColors getWallpaperColors(int which, int userId, int displayId) {if (which != FLAG_LOCK && which != FLAG_SYSTEM) {throw new IllegalArgumentException("Must request colors for exactly one kind of wallpaper");}try {return mService.getWallpaperColors(which, userId, displayId);} catch (RemoteException e) {// Can't get colors, connection lost.}return null;}
...

1.2、注册OnColorsChangedListener接口监听壁纸颜色

1.2.1、获取整个壁纸颜色

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

...public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener,@NonNull Handler handler) {addOnColorsChangedListener(listener, handler, mContext.getUserId());}
...
使用范例:
WallpaperManager wallpaperManager=(WallpaperManager) getSystemService(Context.WALLPAPER_SERVICE);wallpaperManager.addOnColorsChangedListener(new WallpaperManager.OnColorsChangedListener() {@Overridepublic void onColorsChanged(WallpaperColors colors, int which) {}});

1.2.2、获取壁纸区域颜色(需要源码引用)
/frameworks/base/core/java/android/app/WallpaperManager.java

.../*** @hide*/public void addOnColorsChangedListener(@NonNull LocalWallpaperColorConsumer callback,List<RectF> regions) throws IllegalArgumentException {for (RectF region : regions) {if (!LOCAL_COLOR_BOUNDS.contains(region)) {throw new IllegalArgumentException("Regions must be within bounds "+ LOCAL_COLOR_BOUNDS);}}sGlobals.addOnColorsChangedListener(callback, regions, FLAG_SYSTEM,mContext.getUserId(), mContext.getDisplayId());}
...

Tip: LocalWallpaperColorConsumer是hide接口,非源码编译的Apk无法引用

使用范例:
addOnColorsChangedListener(new LocalWallpaperColorConsumer() {@java.lang.Overridepublic void onColorsChanged(RectF area, WallpaperColors colors) {}
},handler);

1.3、使用WallpaperColors

取出的数据都封装在WallpaperColors中,可通过以下接口获取到原始数据
/frameworks/base/core/java/android/app/WallpaperColors.java

    //获取墙纸最具视觉代表性的颜色。“视觉上具有代表性”是指在图像中很容易被注意到,可能发生在高频率。不为空public @NonNull Color getPrimaryColor() {return mMainColors.get(0);}//获取壁纸的第二个最杰出的颜色。可以为空public @Nullable Color getSecondaryColor() {return mMainColors.size() < 2 ? null : mMainColors.get(1);}//获得壁纸的第三个最杰出的颜色。可以为空public @Nullable Color getTertiaryColor() {return mMainColors.size() < 3 ? null : mMainColors.get(2);}//最杰出的颜色列表,按重要性排序public @NonNull List<Color> getMainColors() {return Collections.unmodifiableList(mMainColors);}//得到所有提取出来的颜色,key是颜色的rgb int值 ,value是出现次数 public @NonNull Map<Integer, Integer> getAllColors() {return Collections.unmodifiableMap(mAllColors);}

框架中只是负责提取出原始颜色,但有些时候直接使用原始颜色,并不能达到最好的效果。

例如:PixelLauncher的插件实现颜色动态变化,除了从Wallpaper中拿到颜色,还进行了二次加工,使其更符合Material Desgin的风格,这也是符合“Monet”主题系统 中的一部分,目前是没有开源的。所以一方或三方若想使用该特性,可以按需进行选择和二次加工。

2、根据壁纸取色,能取出多少种颜色,颜色的格式和使用场景是什么?

在Android 13上,内存低的机器 ,最多取出五种色值,内存高的机器,最多取出128种颜色。
/frameworks/base/core/java/android/app/WallpaperColors.java

...public static WallpaperColors fromBitmap(@NonNull Bitmap bitmap,@FloatRange (from = 0f, to = 1f) float dimAmount) {
...if (ActivityManager.isLowRamDeviceStatic()) {palette = Palette.from(bitmap, new VariationalKMeansQuantizer()).maximumColorCount(5).resizeBitmapArea(MAX_WALLPAPER_EXTRACTION_AREA).generate();} else {palette = Palette.from(bitmap, new CelebiQuantizer()).maximumColorCount(128).resizeBitmapArea(MAX_WALLPAPER_EXTRACTION_AREA).generate();}
...
  • 取出的是一个WallpaperColors对象,其中包含三种主颜色,以及一个保存了所有提取出颜色的Color数组(Hide)。
  • 目前的应用场景主要是PixelLauncher、SystemUI、GBoard

3、能从动态壁纸中取色吗?

很可惜,Google并没有为动态壁纸提供默认的取色逻辑。

壁纸的取色,最终会调用到WallpaperService的onComputeColors中,但该方法是空实现,框架只是提供了最基本的获取接口而已。

所以在Android 13之前,无论是静态壁纸或是动态 壁纸,若想要其他模块能获取到壁纸颜色的话,需要壁纸提供方,在实现WallpaperService的Engine时,也一并实现onCompleteColors方法,然后在颜色变化时调用notifyColorsChanged。
/frameworks/base/core/java/android/service/wallpaper/WallpaperService.java

...
public void notifyColorsChanged() {...try {//关键调用final WallpaperColors newColors = onComputeColors();if (mConnection != null) {//通知给监听壁纸颜色变化的模块mConnection.onWallpaperColorsChanged(newColors, mDisplay.getDisplayId());} else {Log.w(TAG, "Can't notify system because wallpaper connection "+ "was not established.");}...} catch (RemoteException e) {Log.w(TAG, "Can't notify system because wallpaper connection was lost.", e);}
}//重写该方法
public @Nullable WallpaperColors onComputeColors() {return null;
}
...

如图:

特性< Android 13Android 13
静态壁纸没有默认实现提供了默认实现,可以根据区域取色
动态壁纸空实现空实现

4、壁纸取色失败会使用默认颜色吗?

壁纸其实是通过Palette接口进行颜色提取的,基本上都能取到至少一种颜色。当真的取出失败或取出的颜色如果不符合期望,需要采用另外一套默认颜色,这是由各个各个业务去处理的,比如Launcher中的LauncherAppWidgetHostView,重写了setColorResources方法
/packages/apps/Launcher3/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java

...
@Override
public void setColorResources(@Nullable SparseIntArray colors) {if (colors == null) {//关键点1,提取不到颜色,会重置插件的颜色resetColorResources();} else {//关键点2,设置插件的颜色super.setColorResources(colors);}
}
...

5、Widget 取色的整体流程是怎样?

具体流程见下图:

PixelLauncher是通过LocalWallpaperColorsExtractor的实现类进行颜色提取,该类继承于LocalColorExtractor,该类存在于Launcher3中,是空实现。可以看出,Google专门将Monet算法部分折分隐藏,只公开框架部分。

而LocalWallpaperColorsExtractor是通过调用WallpaperManager.addOnColorsChangedListener接口,获取onColorsChanged(RectF rectF, WallpaperColors wallpaperColors)中的返回信息,然后再对WallpaperColors中的颜色信息进行二次加工处理。

6、Widget 能使用的颜色数量和范围

Widget能使用的色值数量没有限制,从android.R.color.system_neutrall_0(#FFFFFF) 到android.R.color.system_accent3_1000(#000000)都是合法范围。

7、为什么现有第三方Launcher即使在Android13上,Widget的取色也会无效,而 Pixel Launcher可以。

第三方 Launcher 代码中虽然已经有调用AppWidgetHostView.setColorResources,但是因为其提取颜色的LocalColorExtractor是空实现,所以没有实际效果。而Pixel Launcher 自己写了一个LocalWallpaperColorsExtractor去继承LocalColorExtractor。详见以下代码:

/packages/apps/Launcher3/src/com/android/launcher3/widget/LocalColorExtractor.java

...
public static LocalColorExtractor newInstance(Context context) {return Overrides.getObject(WallpaperColors.class, context.getApplicationContext(),R.string.local_colors_extraction_class);
}
...

local_colors_extraction_class 该值定义在PixelLauncher中

<string name="local_colors_extraction_class">com.google.android.apps.nexuslauncher.widget.LocalWallpaperColorsExtractor</string>

8、是否可以固定设置一套或者几套颜色,去overlay 壁纸的取色?

可以,Android 13已经在secure表中预定义了theme_customization_overlay_packages字段,在其中配置了是否要根据主屏幕变色还是预置颜色,然后进行资源Overlay的。
Android 原生设置入口

theme_customization_overlay_packages字段含义

字段含义取值范围
android.theme.customization.color_index选择颜色索引0~n
android.theme.customization.system_palette中立色color
android.theme.customization.accent_color强调色color
android.theme.customization.color_source采用跟随壁纸颜色还是基本颜色present \ home_wallpaper \ lock_wallpaper
android.theme.customization.color_both"区分当前壁纸设置类型1 锁屏和主屏幕, 0 只设置其中一项

我们可以直接使用或借鉴这套逻辑,预置几套色值,并设置为使用基本颜色。


http://www.ppmy.cn/server/164654.html

相关文章

PHP Composer:高效依赖管理工具详解

PHP Composer:高效依赖管理工具详解 引言 在PHP开发领域,依赖管理是项目构建过程中的重要环节。Composer的出现,极大地简化了PHP项目的依赖管理,使得开发者可以更加高效地构建和维护PHP应用程序。本文将深入探讨PHP Composer的使用方法、功能特点以及它在项目开发中的应用…

ubuntu 下使用deepseek

安装Ollama sudo snap install ollama 执行 ollama run deepseek-coder 然后进行等待。。。

【含文档+PPT+源码】基于微信小程序的校园快递平台

项目介绍 本课程演示的是一款基于微信小程序的校园快递平台&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系统 3.该项目附带…

< OS 有关 > 阿里云:轻量应用服务器 的使用 :轻量化 阿里云 vpm 主机

原因&#xff1a; &#xff1c; OS 有关 &#xff1e; 阿里云&#xff1a;轻量应用服务器 的使用 &#xff1a;从新开始 配置 SSH 主机名 DNS Tailscale 更新OS安装包 最主要是 清除阿里云客户端这个性能杀手-CSDN博客 防止 I/O 祸害系统 操作&#xff1a; 查看进程&#x…

在Arm芯片苹果Mac系统上通过homebrew安装多版本mysql并解决各种报错,感谢deepseek帮助解决部分问题

背景&#xff1a; 1.苹果设备上安装mysql&#xff0c;随着苹果芯片的推出&#xff0c;很多地方都变得不一样了。 2.很多时候为了老项目能运行&#xff0c;我们需要能安装mysql5.7或者mysql8.0或者mysql8.2.虽然本文编写时最新的默认mysql已经是9.2版本。 安装步骤 1.执行hom…

解锁FPGA的故障免疫密码

我们身处“碳基智能”大步迈向“硅基智能”序曲中,前者更像是后者的引导程序,AI平民化时代,万物皆摩尔定律。 越快越好,几乎适用绝大多数场景。 在通往人工智能的征程中,算力无处不在,芯片作用无可替代。 十六年前,就已宣称自己是一家软件公司的英伟达,现已登顶全球…

冯诺依曼系统及操作系统

目录 一.冯诺依曼体系结构 二.操作系统 三.系统调用和库函数概念 一.冯诺依曼体系结构 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依曼体系 截至目前&#xff0c;我们所认识的计算机&#xff0c;都是由一…

GRAPHARG——学习

20250106 项目git地址&#xff1a;https://github.com/microsoft/graphrag.git 版本&#xff1a;1.2.0 ### This config file contains required core defaults that must be set, along with a handful of common optional settings. ### For a full list of available setti…