Android 动态修改APP图标

文章目录

  • Android 动态修改APP图标
    • 定义activity-alias
    • 修改图标和App名
    • 监听APP前后台状态切换
    • 进入后台时切换修改图标和名字
    • 缺点

Android 动态修改APP图标

修改前:

在这里插入图片描述

修改后:

在这里插入图片描述

定义activity-alias

在 AndroidManifest.xml 中设置 activity-alias:

activity-alias标签中的属性:

标签作用
android:name别名
android:enabled是否启用别名
android:icon应用图标
android:label应用名
android:targetActivity必须指向原入口Activity

下面定义了2个alias标签:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.myapplication"><applicationandroid:name=".BaseApplication"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.MyApplication"><activity android:name=".SecondActivity" /><activity android:name=".MainActivity" /><activity-aliasandroid:name=".DefaultAliasActivity"android:enabled="true"android:exported="true"android:icon="@mipmap/ic_launcher"android:roundIcon="@mipmap/ic_launcher_round"android:targetActivity=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity-alias><activity-aliasandroid:name=".TaobaoAliasActivity"android:enabled="false"android:exported="true"android:icon="@mipmap/ic_taobao"android:label="taobao"android:targetActivity=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity-alias></application></manifest>

修改图标和App名

object AliasUtils {private const val DEFAULT_ALIAS = "com.example.myapplication.DefaultAliasActivity"private const val TAOBAO_ALIAS = "com.example.myapplication.TaobaoAliasActivity"fun setDefaultAlias(context: Context) {context.packageManager.apply {setComponentEnabledSetting(ComponentName(context, DEFAULT_ALIAS),PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP)setComponentEnabledSetting(ComponentName(context, TAOBAO_ALIAS),PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP)}}fun setTaobaoAlias(context: Context) {context.packageManager.apply {setComponentEnabledSetting(ComponentName(context, TAOBAO_ALIAS),PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP)setComponentEnabledSetting(ComponentName(context, DEFAULT_ALIAS),PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP)}}
}

监听APP前后台状态切换

class BaseApplication : Application() {companion object {private lateinit var INSTANCE: BaseApplicationfun getInstance(): BaseApplication {return INSTANCE}}override fun onCreate() {super.onCreate()INSTANCE = thisActivityManager.getInstance().init(INSTANCE)}
}
public final class ActivityManager implements Application.ActivityLifecycleCallbacks {private static volatile ActivityManager sInstance;/*** Activity 存放集合*/private final ArrayMap<String, Activity> mActivitySet = new ArrayMap<>();/*** 应用生命周期回调*/private final ArrayList<ApplicationLifecycleCallback> mLifecycleCallbacks = new ArrayList<>();/*** 当前应用上下文对象*/private Application mApplication;/*** 栈顶的 Activity 对象*/private Activity mTopActivity;/*** 前台并且可见的 Activity 对象*/private Activity mResumedActivity;private ActivityManager() {}public static ActivityManager getInstance() {if (sInstance == null) {synchronized (ActivityManager.class) {if (sInstance == null) {sInstance = new ActivityManager();}}}return sInstance;}public void init(Application application) {mApplication = application;mApplication.registerActivityLifecycleCallbacks(this);}/*** 获取 Application 对象*/public Application getApplication() {return mApplication;}/*** 获取栈顶的 Activity*/@Nullablepublic Activity getTopActivity() {return mTopActivity;}/*** 获取前台并且可见的 Activity*/@Nullablepublic Activity getResumedActivity() {return mResumedActivity;}/*** 判断当前应用是否处于前台状态*/public boolean isForeground() {return getResumedActivity() != null;}/*** 注册应用生命周期回调*/public void registerApplicationLifecycleCallback(ApplicationLifecycleCallback callback) {mLifecycleCallbacks.add(callback);}/*** 取消注册应用生命周期回调*/public void unregisterApplicationLifecycleCallback(ApplicationLifecycleCallback callback) {mLifecycleCallbacks.remove(callback);}/*** 销毁指定的 Activity*/public void finishActivity(Class<? extends Activity> clazz) {if (clazz == null) {return;}String[] keys = mActivitySet.keySet().toArray(new String[]{});for (String key : keys) {Activity activity = mActivitySet.get(key);if (activity == null || activity.isFinishing()) {continue;}if (activity.getClass().equals(clazz)) {activity.finish();mActivitySet.remove(key);break;}}}/*** 销毁所有的 Activity*/public void finishAllActivities() {finishAllActivities((Class<? extends Activity>) null);}/*** 销毁所有的 Activity** @param classArray 白名单 Activity*/@SafeVarargspublic final void finishAllActivities(Class<? extends Activity>... classArray) {String[] keys = mActivitySet.keySet().toArray(new String[]{});for (String key : keys) {Activity activity = mActivitySet.get(key);if (activity == null || activity.isFinishing()) {continue;}boolean whiteClazz = false;if (classArray != null) {for (Class<? extends Activity> clazz : classArray) {if (activity.getClass().equals(clazz)) {whiteClazz = true;}}}if (whiteClazz) {continue;}// 如果不是白名单上面的 Activity 就销毁掉activity.finish();mActivitySet.remove(key);}}@Overridepublic void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {if (mActivitySet.size() == 0) {for (ApplicationLifecycleCallback callback : mLifecycleCallbacks) {callback.onApplicationCreate(activity);}}mActivitySet.put(getObjectTag(activity), activity);mTopActivity = activity;}@Overridepublic void onActivityStarted(@NonNull Activity activity) {}@Overridepublic void onActivityResumed(@NonNull Activity activity) {if (mTopActivity == activity && mResumedActivity == null) {for (ApplicationLifecycleCallback callback : mLifecycleCallbacks) {callback.onApplicationForeground(activity);}}mTopActivity = activity;mResumedActivity = activity;}@Overridepublic void onActivityPaused(@NonNull Activity activity) {}@Overridepublic void onActivityStopped(@NonNull Activity activity) {if (mResumedActivity == activity) {mResumedActivity = null;}if (mResumedActivity == null) {for (ApplicationLifecycleCallback callback : mLifecycleCallbacks) {callback.onApplicationBackground(activity);}}}@Overridepublic void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {}@Overridepublic void onActivityDestroyed(@NonNull Activity activity) {mActivitySet.remove(getObjectTag(activity));if (mTopActivity == activity) {mTopActivity = null;}if (mActivitySet.size() == 0) {for (ApplicationLifecycleCallback callback : mLifecycleCallbacks) {callback.onApplicationDestroy(activity);}}}/*** 获取一个对象的独立无二的标记*/private static String getObjectTag(Object object) {// 对象所在的包名 + 对象的内存地址return object.getClass().getName() + Integer.toHexString(object.hashCode());}/*** 应用生命周期回调*/public interface ApplicationLifecycleCallback {/*** 第一个 Activity 创建了*/void onApplicationCreate(Activity activity);/*** 最后一个 Activity 销毁了*/void onApplicationDestroy(Activity activity);/*** 应用从前台进入到后台*/void onApplicationBackground(Activity activity);/*** 应用从后台进入到前台*/void onApplicationForeground(Activity activity);}
}

进入后台时切换修改图标和名字

override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)ActivityManager.getInstance().registerApplicationLifecycleCallback(object :ActivityManager.ApplicationLifecycleCallback {override fun onApplicationCreate(activity: Activity?) {}override fun onApplicationDestroy(activity: Activity?) {}override fun onApplicationBackground(activity: Activity?) {Log.e("TAG", "App处于后台")if (type == TYPE_DEFAULT) {AliasUtils.setDefaultAlias(this@MainActivity)} else if (type == TYPE_TAOBAO) {AliasUtils.setTaobaoAlias(this@MainActivity)}}override fun onApplicationForeground(activity: Activity?) {Log.e("TAG", "App处于前台")}})
}

缺点

  • 切换图标时,应用会自动退出,因此放在后台执行相对有好些。
  • 切换图标是一个耗时过程,1s~10s不等。
  • 在切换图标过程中,点击App图标,可能会提示“应用数据读取失败”等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/23615.shtml

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

相关文章

RTA_OS基础功能讲解 2.8-Tick计数器

RTA_OS基础功能讲解 2.8-Tick计数器 文章目录 RTA_OS基础功能讲解 2.8-Tick计数器一、计数器简介二、计数器配置三、计数器驱动3.1 软件计数器驱动3.1.1 递增软件计数器3.1.2 静态计数器接口3.2 硬件计数器驱动3.2.1 Advancing硬件计数器3.2.2 回调函数四、在运行时访问计数器属…

JVM之【类的生命周期】

首先&#xff0c;请区分Bean的声明周期和类的声明周期。此处讲的是类的声明周期 可以同步观看另一篇文章JVM之【类加载机制】 概述 在Java中数据类型分为基本数据类型和引用数据类型 基本数据类型由虚拟机预先定义&#xff0c;引用数据类型则需要进行类的加载 按照]ava虚拟机…

AI大模型日报#0606:智谱AI开源GLM-4-9B、Pika再融5.8亿

导读&#xff1a;AI大模型日报&#xff0c;爬虫LLM自动生成&#xff0c;一文览尽每日AI大模型要点资讯&#xff01;目前采用“文心一言”&#xff08;ERNIE 4.0&#xff09;、“零一万物”&#xff08;Yi-Large&#xff09;生成了今日要点以及每条资讯的摘要。欢迎阅读&#xf…

【Linux】进程切换环境变量

目录 一.进程切换 1.进程特性 2.进程切换 1.进程切换的现象 2.如何实现 3.现实例子 2.环境变量 一.基本概念 二.常见环境变量 三.查询常见环境变量的方法 四.和环境变量相关的命令 五.环境变量表的组织方式 六.使用系统调用接口方式查询环境变量 1.getenv 2.反思 …

【简单讲解下TalkingData】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

Signac|成年小鼠大脑 单细胞ATAC分析(1)

引言 在本教程中&#xff0c;我们将探讨由10x Genomics公司提供的成年小鼠大脑细胞的单细胞ATAC-seq数据集。本教程中使用的所有相关文件均可在10x Genomics官方网站上获取。 本教程复现了之前在人类外周血单核细胞&#xff08;PBMC&#xff09;的Signac入门教程中执行的命令。…

【Python报错】已解决ModuleNotFoundError: No Module Named ‘openyxl’

成功解决“ModuleNotFoundError: No Module Named ‘openyxl’”错误的全面指南 在Python编程中&#xff0c;遇到ModuleNotFoundError: No Module Named openyxl这样的错误通常意味着Python解释器无法找到名为openyxl的模块。然而&#xff0c;这里存在一个常见的拼写错误&#…

大语言模型 (LLM) 窥探未来

随着2023年的岁月渐渐走向尾声&#xff0c;我们站在人工智能的前沿&#xff0c;回望大语言模型&#xff08;Large Language Models, LLM&#xff09;所走过的道路&#xff0c;同时也不禁展望未来。从初步尝试到成为人工智能领域的万千宠爱&#xff0c;一种又一种的技术突破&…

搜维尔科技:「案例」Faceware电影中面部动画的演变历程

面部动画是电影中角色表演的一个重要方面&#xff0c;尤其是在严重依赖电子动画、化妆效果和动作捕捉系统的奇幻电影中。在《龙与地下城&#xff1a;盗贼荣誉》电影中&#xff0c;龙裔角色的面部动画是一个复杂的系统&#xff0c;使该生物在大屏幕上栩栩如生。该系统依赖于一种…

超速解读多模态InternVL-Chat1.5 ,如何做到开源SOTA——非官方首发核心技巧版(待修订)

解读InternVL-chat1.5系列 最近并行是事情太杂乱了&#xff0c;静下心来看一看优秀的开源项目,但是AI技术迭代这么快&#xff0c;现在基本是同时看五、六个方向的技术架构和代码&#xff0c;哪个我都不想放&#xff0c;都想知道原理和代码细节&#xff0c;还要自己训练起来&am…

Linux驱动开发笔记(四)设备树进阶及GPIO、Pinctrl子系统

文章目录 前言一、设备树的进阶知识1. 追加/修改节点内容2.chosen子节点3. 获取设备树节点信息3.1 of_find_node_by_path( )函数3.2 of_find_node_by_name( )函数3.3 of_find_node_by_type( )函数3.4 of_find_compatible_node( )函数3.5 of_find_matching_node_and_match( )函数…

Day30 登录界面设计

​ 本章节,实现了登录界面窗口设计 一.准备登录界面图片素材(透明背景图片) 把准备好的图片放在 Images 文件夹下面,格式分别是 .png和 .icoico 图片,右键属性,生成操作选 内容 png 图片,右键属性,生成操作选 资源 选中 login.png图片鼠标右键,选择属性。生成的操作选…

多目标应用:MOHHO多目标哈里斯鹰优化算法求解无人机三维路径规划(MATLAB代码)

详细介绍 多目标应用&#xff1a;MOHHO多目标哈里斯鹰优化算法求解无人机三维路径规划&#xff08;MATLAB代码&#xff09;-CSDN博客 一次运行结果 完整MATLAB代码

CentOS6系统因目录有隐含i权限属性致下属文件无法删除的故障一例

CentOS6服务器在升级openssh时因系统目录权限异常&#xff08;有隐含i权限属性&#xff09;&#xff0c;下属文件无法删除&#xff0c;导致系统问题的故障一例。 一、问题现象 CentOS6在升级openssh时&#xff0c;提示如下问题&#xff1a; warning: /etc/ssh/sshd_config c…

springboot vue 开源 会员收银系统 (6) 收银台的搭建

前言 完整版演示 前面我们对会员系统 分类和商品的开发 完成了收银所需的基础信息 下面我们开始完成收银台的开发 简单画了一个收银的流程图大家参考下 从这张图我们可以分析一下几点 可以选择会员或散客收银选择会员使用相应的会员价结算使用会员卡则在价格基础根据卡折扣…

node.js漏洞——

一.什么是node.js 简单的说 Node.js 就是运行在服务端的 JavaScript。 Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台。 Node.js 是一个事件驱动 I/O 服务端 JavaScript 环境&#xff0c;基于 Google 的 V8 引擎&#xff0c;V8 引擎执行 Javascript 的速度非常…

神经网络搭建(1)----nn.Sequential

神经网络模型构建 采用CIFAR10中的数据&#xff0c;并对其进行简单的分类。以下图为例 输入&#xff1a;3通道&#xff0c;3232 ( 经过一个55的卷积) → 变成32通道&#xff0c;3232的图像 (经过22的最大池化) → 变成32通道&#xff0c;1616的图像 ( 经过一个55的卷积) → 变…

linux虚拟机免密登录配置

1、假设A服务器要免密登录B服务器 2、在A服务器上执行命令&#xff1a; cd /root/.ssh/ ssh-keygen -t rsa #这里会生成两个文件 一个是id_rsa私钥和公钥rsa.pub2、我们把公钥的内容复制粘贴到B服务器的/root/.ssh/authorized_keys文件下 #在A服务器上执行命令记录内容 cat …

ArkTs-TaskPool和Worker的使用

TaskPool和Worker的区别 实现TaskPoolWorker内存模型线程间隔离&#xff0c;内存不共享。线程间隔离&#xff0c;内存不共享。参数传递机制 采用标准的结构化克隆算法&#xff08;Structured Clone&#xff09;进行序列化、反序列化&#xff0c;完成参数传递。 支持ArrayBuffe…

python调用excel的demo

在本地安装Pycharm之后&#xff0c;新建工程&#xff0c;在main.py中键入如下代码,即可实现Python调用excel&#xff1a; import pandas as pd sheet pd.read_excel(test.xlsx) data sheet.loc[0].values print("读取指定行的数据:\n{0}".format(data)) 第一次编…