Android 使用Overlay现实主题切换

最近项目上,想做一个主题切换的功能,整理了一下发布出来,主要使用的是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.mzph.cn/bicheng/64295.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【原生js案例】如何实现一个穿透字体颜色的导航

普通的导航大家都会做&#xff0c;像这种穿透字体的导航应该很少见吧。高亮不是通过单独设置一个active类来设置字体高亮颜色&#xff0c;鼠标滑过导航项&#xff0c;字体可以部分是黑色&#xff0c;不分是白色&#xff0c;这种效果的实现 感兴趣的可以关注下我的系列课程【we…

IDEA 2023.3.6 下载、安装、激活与使用

一、IDEA2023.3.6下载 国际官网&#xff1a;https://www.jetbrains.com/ 国内官网&#xff1a;https://www.jetbrains.com.cn/ 如果国际官网无法访问&#xff0c;就使用国内官网&#xff0c;我们以国内官网为例下载IDEA2023.3.6 首先进入首页如下图&#xf…

ip_done

文章目录 路由结论 IP分片 数据链路层重谈Mac地址MAC帧报头局域网的通信原理MSS&#xff0c;以及MAC帧对上层的影响ARP协议 1.公司是不是这样呢? 类似的要给运营商交钱&#xff0c;构建公司的子网&#xff0c;具有公司级别的入口路由器 2&#xff0e;为什么要这样呢?? IP地…

深度学习作业 - 作业十一 - LSTM

问题一 推导LSTM网络中参数的梯度&#xff0c;并的分析其避免梯度消失的效果 LSTM网络是为了解简单RNN中存在的长程依赖问题而提出的一种新型网络结构&#xff0c;其主要思想是通过引入门控机制来控制数据的流通&#xff0c;门控机制包括输入门、遗忘门与输出门&#xff0c;同…

医院与医疗设备供应商网络安全事故综述

医院与医疗设备供应商网络安全事故综述 在医疗行业中&#xff0c;医院和医疗设备供应商的网络安全问题同样不容忽视。以下是一些近年来发生的重大网络安全事故的总结&#xff1a; 1. 德国杜塞尔多夫大学医院勒索软件攻击&#xff08;2020年&#xff09; 事件描述&#xff1a…

修改vscode中emmet中jsx和tsx语法中className的扩展符号从单引号到双引号 - HTML代码补全 - 单引号双引号

效果图 实现步骤 文件 > 首选项 > 设置搜索“”在settings.json中修改&#xff0c;增加 "emmet.syntaxProfiles": {"html": {"attr_quotes": "single"},"jsx": {"attr_quotes": "double","…

从0到1实现vue3+vite++elementuiPlus+ts的后台管理系统(一)

前言&#xff1a;从这篇文章开始实现vue3vite的后台管理系统&#xff0c;记录下自己搭建后台系统图的过程。 这篇文章完成项目的初始化和基本配置&#xff0c;这一步可以直接跟着vue3官网进行。整个系列只有前端部分&#xff0c;不涉及后端。 vue3官网&#xff1a;https://cn.…

JavaEE初阶——多线程(线程安全-锁)

复习上节内容&#xff08;部分-掌握程度不够的&#xff09; 加锁&#xff0c;解决线程安全问题。 synchronized关键字&#xff0c;对锁对象进行加锁。 锁对象&#xff0c;可以是随便一个Object对象&#xff08;或者其子类的对象&#xff09;&#xff0c;需要关注的是&#xff…

如何在NGINX中实现基于IP的访问控制(IP黑白名单)?

大家好&#xff0c;我是锋哥。今天分享关于【如何在NGINX中实现基于IP的访问控制&#xff08;IP黑白名单&#xff09;&#xff1f;】面试题。希望对大家有帮助&#xff1b; 如何在NGINX中实现基于IP的访问控制&#xff08;IP黑白名单&#xff09;&#xff1f; 1000道 互联网大…

Docker--Docker Registry(镜像仓库)

什么是Docker Registry&#xff1f; 镜像仓库&#xff08;Docker Registry&#xff09;是Docker生态系统中用于存储、管理和分发Docker镜像的关键组件。 镜像仓库主要负责存储Docker镜像&#xff0c;这些镜像包含了应用程序及其相关的依赖项和配置&#xff0c;是构建和运行Doc…

微信小程序:实现节点进度条的效果;正在完成的节点有动态循环效果;横向,纵向排列

参考说明 微信小程序实现流程进度功能 - 知乎 上面的为一个节点进度条的例子&#xff0c;但并不完整&#xff0c;根据上述代码&#xff0c;进行修改完善&#xff0c;实现其效果 横向效果 代码 wxml <view classorder_process><view classprocess_wrap wx:for&quo…

window下的qt5.14.2配置vs2022

这里做一个笔记&#xff0c;已知qt5.14.2和vs2022不兼容&#xff0c;无法自动扫描到vs的编译器。但由于团队协作原因&#xff0c;必须使用qt5.14.2&#xff0c;并且第三方库又依赖vs2022。其实qt5.15.2是支持vs2022的&#xff0c;如果能够用qt5.15.2&#xff0c;还是建议使用qt…

Java-27 深入浅出 Spring - 实现简易Ioc-03 在上节的业务下手动实现IoC

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大数据篇正在更新&#xff01;https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了&#xff1a; MyBatis&#xff…

梳理你的思路(从OOP到架构设计)_UML应用:业务内涵的分析抽象表达01

目录 1、 系统分析(System Analysis) 系統分析的涵意 业务(领域)知识 业务内涵 业务(领域)概念 2、举例(一) &#xff1a;东方传说 UML与建模工具 1、 系统分析(System Analysis) 系統分析的涵意 许多人在学习系统分析(System Analysis)时&#xff0c;常迷失于其字面上…

Web 安全 跨站 跨域 XSS CSRF

跨站 跨站即 cross-site&#xff0c;它和同站&#xff08;same-site&#xff09;相对&#xff0c;对协议和端口号无要求&#xff0c;只要两个 URL 的 eTLD 1 一致&#xff0c;就能称为同站。那么什么是 eTLD 呢&#xff1f; eTLD 即 effective top level domain&#xff0c;…

k8s服务搭建与实战案例

Kubernetes&#xff08;K8s&#xff09;作为一个开源的容器编排平台&#xff0c;广泛应用于现代的云原生应用架构中。以下是一些常见的 **Kubernetes 实战案例**&#xff0c;包括从基础部署到高级应用场景的使用。通过这些案例&#xff0c;可以更好地理解 K8s 的运作原理和最佳…

PYQT5程序框架

pyqt5程序框架_哔哩哔哩_bilibili 1.UI代码 Qhkuja.py # -*- coding: utf-8 -*-# Form implementation generated from reading ui file Qhkuja.ui # # Created by: PyQt5 UI code generator 5.15.7 # # WARNING: Any manual changes made to this file will be lost when py…

基于MobileNet v2模型的口罩实时检测系统实现

基于kaggle数据集训练的模型其实现结果如下&#xff1a; 代码结构如下&#xff1a; 实时口罩检测器&#xff1a; 从导航栏中的链接“实时的口罩检测器”功能&#xff0c;该系统包含一个实时检测用户是否佩戴口罩的功能。基于图片的口罩检测器&#xff1a; 从另一个导航链接“基…

高效项目托管指南:从本地到 GitHub 的完整流程

在现代软件开发中&#xff0c;将项目托管在 GitHub 上是一个常见且高效的方式。GitHub 不仅可以用作版本控制工具&#xff0c;还能帮助你与团队协作或展示自己的项目。本文将带你一步步完成项目的打包和上传。 高效项目托管指南&#xff1a;从本地到 GitHub 的完整流程 1. 准备…

用TPS54531绘制BUCK电路板

首先&#xff0c;这TPS54531 是一款非同步降压转换器芯片&#xff08;异步&#xff09;。 这是BUCK的基本原理图&#xff0c;它是异步的。 我们用这款芯片来控制MOS管的高频开关&#xff0c;以此实现降压。 这里使用的应该是CCM模式。 这里&#xff1a; Vi为24V&#xff0c;…