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…

C++构造器设计模式

构造器模式可以简化复杂对象或一系列对象的构造过程&#xff0c;从而单独定义构成该复杂对象的各个组件的构建方法。 这篇文章只讲解较为简单的构造器的创建。创建一个构造器我们得了解如何实现流式调用以及如何关闭外界的访问权对构造函数的访问权限。 流式调用 所谓流式调…

【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入门教程中执行的命令。…

100道大模型面试八股文

算法暑期实习机会快结束了&#xff0c;校招大考即将来袭。 当前就业环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;岗位在变少&#xff0c;要求还更高了。 最近&#xff0c;我们陆续整理了很多大厂的面试题&#xff0c;帮助球友解惑答疑和职业规划&#xff0c;分…

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

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

javascript中的flat和faltmap的区别

JavaScript 中的 flat 和 flatMap 是数组方法&#xff0c;它们用于处理嵌套数组&#xff08;即数组中的元素也是数组&#xff09;。下面是它们的区别&#xff1a; flat 方法: flat 方法用于将嵌套数组“展平”成一个新数组&#xff0c;但不会改变原始数组。它接受一个可选的深…

Anaconda 环境管理的一些特殊操作

在指定位置创建虚拟环境 第一步&#xff1a;在现有/your/paht/目录创建env_name的环境变量 conda create -p /your/paht/env_name python3.x第二步&#xff1a;通过一下命令发现环境变量没有名字&#xff1a; conda env list第三步&#xff1a;将/your/paht/ 加入到conda 的en…

资源描述框架的用途及实际应用解析

什么是RDF&#xff1f; RDF代表 资源描述框架 RDF是用于描述网络资源的框架 RDF旨在被计算机阅读和理解 RDF并非设计用于供人阅读 RDF以 XML 编写 示例 描述购物商品的属性&#xff0c;如价格和可用性描述网络活动的时间表描述网页的信息&#xff08;内容&#xff0c;作者&a…

使用 Nacos 在 C# (.NET Core) 应用程序中实现高效配置管理和服务发现

在分布式系统架构日益流行的今天&#xff0c;服务配置管理和发现成为了开发和运维团队面临的重大挑战。Nacos&#xff0c;作为阿里巴巴开源的一款强大的动态配置管理与服务发现平台&#xff0c;为解决这一难题提供了有效方案。本文将介绍如何在C# (.NET Core)应用程序中集成Nac…

springboot,配置类加载过程

加载过程 首先来看启动类&#xff0c;启动类上包含了SpringBootApplication注解 SpringBootApplication MapperScan("com.cskaoyan.mapper") public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);…

后端开发面经系列 --中望C++面经

中望C面经&#xff0c;全部内容&#xff01; 公众号&#xff1a;阿Q技术站 文章目录 中望C面经&#xff0c;全部内容&#xff01;一面 8.15 时长45min1、介绍项目相关2、gdb怎么调试的&#xff1f;打断点用什么指令&#xff1f;3、gcc的编译过程4、cmake添加头文件搜索路径用…

Werkzeug的Response

Werkzeug的Response Werkzeug是一个WSGI工具包&#xff0c;提供了一组工具用于开发基于WSGI的Python Web应用。它不仅仅是一个简单的库&#xff0c;还提供了许多方便的工具来处理HTTP请求和响应。本文将深入探讨Werkzeug中Response类的讲解。 官方文档链接 Werkzeug Respons…

大语言模型 (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…

特征工程,减小过拟合

目录 特征工程 减小过拟合 图像增强方法 特征工程是机器学习和数据分析中不可或缺的一环,其重要性不言而喻。以下是关于特征工程的详细回答: 一、定义 特征工程是将原始数据转化为更好的表达问题本质的特征的过程,旨在发现对因变量y有明显影响作用的特征(通常称自变量…