当前位置: 首页 > news >正文

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图标,可能会提示“应用数据读取失败”等。

相关文章:

  • 【Linux】Apache服务器配置
  • 高德POI数据-2024年5月数据-成都餐饮服务
  • java版spring cloud 深入探究ERP管理系统源码:功能模块详解与操作流程梳理
  • Qt 的 d_ptr (d-pointer) 和 q_ptr (q-pointer)解析;Q_D和Q_Q指针
  • LabVIEW如何确保步进电机的长期稳定运行
  • 如何离线下载 Microsoft Corporation II Windows Subsystem for Android
  • 前端柯里化
  • 【前端面试高频手写题】
  • 个人博客系统测试报告
  • 用Transformer做多元时序预测的最佳方法?
  • Python语言试卷:深入剖析Python编程的精髓
  • 基于Python+FFMPEG环境下载B站歌曲
  • Kali常用攻击方式
  • 【杂记-浅谈XSS跨站脚本攻击】
  • golang通道(chan)选择(select)与关闭(close)使用示例
  • Babel配置的不完全指南
  • DOM的那些事
  • export和import的用法总结
  • Github访问慢解决办法
  • Java Agent 学习笔记
  • PHP面试之三:MySQL数据库
  • PHP那些事儿
  • springMvc学习笔记(2)
  • vue 个人积累(使用工具,组件)
  • windows下如何用phpstorm同步测试服务器
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 爱情 北京女病人
  • 第2章 网络文档
  • 后端_MYSQL
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 前端技术周刊 2019-02-11 Serverless
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 数组的操作
  • 系统认识JavaScript正则表达式
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • elasticsearch-head插件安装
  • 阿里云API、SDK和CLI应用实践方案
  • ​马来语翻译中文去哪比较好?
  • #QT(串口助手-界面)
  • #WEB前端(HTML属性)
  • (2022 CVPR) Unbiased Teacher v2
  • (C#)一个最简单的链表类
  • (CPU/GPU)粒子继承贴图颜色发射
  • (WSI分类)WSI分类文献小综述 2024
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (六)vue-router+UI组件库
  • (四)opengl函数加载和错误处理
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (转)Google的Objective-C编码规范
  • (转)视频码率,帧率和分辨率的联系与区别
  • (转)为C# Windows服务添加安装程序
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .jks文件(JAVA KeyStore)
  • .NET Compact Framework 3.5 支持 WCF 的子集