Android 使用Overlay现实主题切换

server/2024/12/15 2:50:27/

最近项目上,想做一个主题切换的功能,整理了一下发布出来,主要使用的是IOverlayManager,大体思路如下:

1、想切换的应用,各自做overlay apk(简称皮肤包)

2、将overlay apk push 到vendor/overlay目录下(如果没有这个目录,push到system/app里面也可以),这个主要目的是为了让overlay 找到这个overlay apk。

3、重启设备

4、点击切换主题

5、各个应用重走生命周期,然后显示出来新的资源

这个主题切换的原理,我自己感觉,就是将overlay apk里面的资源替换到原来apk里面,然后重新加载。

一、app准备,制作overlay apk皮肤包

1、AS内新建项目    文件命名方式:xxxx.Red/xxxx.Young/xxxx.Gold

例如:LocalSetting   新建替换资源的模块名可命名为 LocalSetting.Red /LocalSetting.Young/LocalSetting.Gold,其实就和新建的app 项目一样。

 仅保留AndroidManifest.xml 和res目录下仅保留需要替换的资源信息(values下的colors.xml , strings.xml , dimens.xml themes.xml等 和 drawables/xml目录下的资源, 不支持替换布局文件),想替换那个文件,就在对应的目录下用相同的资源名字放进去。

下图是launcher的主题app目录。

AndroidManifest.xml仅包含以下信息即可,其中targetPackage为要替换资源的app包名。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.test.launcher.young"><overlayandroid:priority="9"android:targetPackage="com.test.launcher" />
</manifest>

 2、生成overlay apk;
        overlay apk 中 AndroidManifest.xml 包名命名方式:xxxx.red/xxxx.young/xxxx.gold,如上示例
        eg: package="com.neusoft.localsetting.red"
        替换  红色(酷炫)主题的apk名为localsetting_red.apk
        替换  金色(酷睿)主题的apk名为localsetting_gold.apk
        替换  年轻色(酷潮)主题的apk名为 localsetting_young.apk
注意:其中red、gold、young是需要打合定义的,目的是为了在切换主题时,获取对应主题的包名

 3、每套主题如果对应2套UI(日夜模式)大家正常在对应的主题中建-night文件夹即可。
 本地测试:将生成的overlay apk签名  push 到vendor/overlay/red/xxxx.apk目录下; 然后调用切换主题即可。

二、实现主题切换流程

主题切换流程:
主要使用原生方法IOverlayManager,调用setEnabledExclusive方法切换主题。

1、开机遍历获取/vendor/overlay下的主题包
使用如下代码可以把不同主题的包名方法一个list中,等后续切换时直接使用。
注意:这个包名是之前和app打合的,必须所有的app都要按照这个要求规则命名apk。

private List<String> mRed1List = new ArrayList<String>(); //存放红色主题包名list
private List<String> mYoungList = new ArrayList<String>(); //存放young主题包名list
private IOverlayManager mOverlayManager = IOverlayManager.Stub.asInterface(ServiceManager.getService("overlay"));public void getThemeOverlayList() {IOverlayManager mOverlayManager = IOverlayManager.Stub.asInterface(ServiceManager.getService("overlay"));mRed1List.clear();mYoungList.clear();try {mOverlayInfoMap = mOverlayManager.getAllOverlays(0);for (List<OverlayInfo> overlayInfos : mOverlayInfoMap.values()) {for (int j = 0; j < overlayInfos.size(); j++) {String overlayPackageName = overlayInfos.get(j).packageName;if (overlayPackageName.contains("red")) {mRed1List.add(overlayPackageName);} else if (overlayPackageName.contains("young")) {mYoungList.add(overlayPackageName);}}}} catch (RemoteException e) {e.printStackTrace();}}

2、切换时遍历list,调用原生方法mOverlayManager.setEnabledExclusive切换主题。

mOverlayManager.setEnabledExclusive(mYoungList.get(i), true, 0);方法是把对应的主题包资源替换进去。
mOverlayManager.setEnabled(mRed1List.get(i), false, 0);方法是把主题包禁用,从而显示显示源代码里面的资源。
    private void changeThemeColor(int themeChange) {List<Boolean> changeThemeResult = new ArrayList<>();List<String> changeResultFail = new ArrayList<>();try {if (themeChange == SettingConfig.THEME_RED) {if (mRed1List.size() != 0) {for (int i = 0; i < mRed1List.size(); i++) {boolean isSuccess = mOverlayManager.setEnabledExclusive(mRed1List.get(i), true, 0);if (!isSuccess) {changeThemeResult.add(isSuccess);changeResultFail.add(mRed1List.get(i));}}Log.d(TAG, "---mRed1List.get(i):" + mRed1List.toString());}} else if (themeChange == SettingConfig.THEME_YOUNG) {if (mYoungList.size() != 0) {for (int i = 0; i < mYoungList.size(); i++) {boolean isSuccess = mOverlayManager.setEnabledExclusive(mYoungList.get(i), true, 0);if (!isSuccess) {changeThemeResult.add(isSuccess);changeResultFail.add(mYoungList.get(i));}}Log.d(TAG, "---mYoungList.get(i):" + mYoungList.toString());}} else if (themeChange == SettingConfig.THEME_GOLD) {if (mRed1List.size() != 0) {for (int i = 0; i < mRed1List.size(); i++) {boolean isSuccess = mOverlayManager.setEnabled(mRed1List.get(i), false, 0);if (!isSuccess) {changeThemeResult.add(isSuccess);changeResultFail.add(mRed1List.get(i));}}Log.d(TAG, "---mRed1List.get(i):" + mRed1List.toString());}if (mYoungList.size() != 0) {for (int i = 0; i < mYoungList.size(); i++) {boolean isSuccess = mOverlayManager.setEnabled(mYoungList.get(i), false, 0);if (!isSuccess) {changeThemeResult.add(isSuccess);changeResultFail.add(mYoungList.get(i));}}Log.d(TAG, "---mYoungList.get(i):" + mYoungList.toString());}}if (changeThemeResult != null && changeThemeResult.size() > 0&& changeResultFail != null && changeResultFail.size() > 0) {Log.d(TAG, "---changeThemeResult:" + changeThemeResult.toString());Log.d(TAG, "---changeResultFail:" + changeResultFail.toString());} else {Log.d(TAG, "---changeThemeResult   无");Log.d(TAG, "---changeResultFail    无");}} catch (RemoteException e) {e.printStackTrace();}}

总结一下,留着以后用。


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

相关文章

antdv-<a-button>中属性的使用

UI组件库&#xff08;User Interface Component Library&#xff09;是一种预先构建好的、可重用的用户界面元素集合&#xff0c;旨在帮助开发者更快速、更简便地构建用户界面。这些组件通常包括按钮、表单、导航栏、模态框等&#xff0c;能够提供一致的外观和交互风格&#xf…

计算机毕设-基于springboot的宠物寄领养网站的设计与实现(附源码+lw+ppt+开题报告)

博主介绍&#xff1a;✌多个项目实战经验、多个大型网购商城开发经验、在某机构指导学员上千名、专注于本行业领域✌ 技术范围&#xff1a;Java实战项目、Python实战项目、微信小程序/安卓实战项目、爬虫大数据实战项目、Nodejs实战项目、PHP实战项目、.NET实战项目、Golang实战…

STL库中list的使用与迭代器的实现

STL库中list的使用与迭代器的实现 1.使用list中的部分函数assignspliceremoveuniquemeger 2.list的部分功能实现&#xff08;重点&#xff09;框架迭代器的实现 1.使用list中的部分函数 assign 功能一&#xff1a;当前链表的节点全部销毁&#xff0c;替换成迭代区间的值 功能二…

ESP32-S3模组上跑通ES8388(29)

接前一篇文章:ESP32-S3模组上跑通ES8388(28) 二、利用ESP-ADF操作ES8388 2. 详细解析 上一回解析到了es8388_init函数中的第11段也是最后一段代码,没有解析完,本回继续解析。为了便于理解和回顾,再次贴出该片段,在components\audio_hal\driver\es8388\es8388.c中,如下…

HarmonyOS:多线程并发-Worker

Worker主要作用是为应用程序提供一个多线程的运行环境&#xff0c;可满足应用程序在执行过程中与宿主线程分离&#xff0c;在后台线程中运行一个脚本进行耗时操作&#xff0c;极大避免类似于计算密集型或高延迟的任务阻塞宿主线程的运行。具体接口信息及使用方法详情请见Worker…

【C++初阶】第8课—标准模板库STL(string_2)

文章目录 1. string类对象遍历操作1.1 标准库中的成员函数begin( )和end( )1.2 标准库中的成员函数rbegin( )和rend( )1.3 C11引入的4个标准库中的成员函数 2. string类对象的访问2.1 operator[ ]运算符重载访问字符串字符2.2 公有成员函数at访问字符2.3 公有成员函数back()和f…

批量导出工作簿中高清图片-Excel易用宝

我同事在工作簿中做了三个图表&#xff0c;现在需要将工作簿中的图标导出保存为高清图片&#xff0c;通过右键另存为保存的图片并非高清图片&#xff0c;其实要把Excel工作簿中的图表或图片对象导出为高清图片也很简单。 单击Excel易用宝 Plus&#xff0c;导出高清图片。 在导出…

CAN和CANopen及CAN FD协议区别及通讯

CAN&#xff08;Controller Area Network&#xff09;协议 基本定义和起源&#xff1a;CAN 协议是一种串行通信协议&#xff0c;最初是为汽车内部的电子控制单元&#xff08;ECU&#xff09;之间的通信而开发的。它是一种多主站总线&#xff0c;这意味着多个节点可以同时发起通…