转载https://blog.csdn.net/pangjl1982/article/details/83308512

1、Android如何动态更换桌面图标
1.1使用场景
      APP,在中国电商行业中,某宝和某东是行业的标杆。其中有一点挺让人好奇的,那就是在双十一临近之时,他们的APP桌面图标突然变成了带有双十一字样的图标。可能就是本来就内置了双十一的图标,等快到双十一的时候在动态更换,然后过了双十一那段时间,又将APP的桌面图标变成普通的icon。

1.2知识点
      动态更换APP 桌面icon的引述;
      activity组件及定义“同盟”组件activity-alias;
      PackageManager类进行启用/禁用组件;
      PackageInfo的简介;
      新名词记录{PackageInfo:Androidmanifest.xml文件描述类}

1.3使用Activity-alias
<activity
    android:name="com.aliasicon.MainActivity"
    android:enabled="false"
    android:exported="true"
    >
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

<activity-alias
    android:name="com.zztzt.android.simple.activity.tztCommHeadPageGenearlActivity"
    android:configChanges="orientation|keyboardHidden|fontScale|screenSize"
    android:enabled="true"
    android:exported="true"
    android:icon="@drawable/tzt_icon"
    android:label="@string/app_general_name"
    android:screenOrientation="portrait"
    android:targetActivity=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity-alias>
<activity-alias
    android:name="com.zztzt.android.simple.activity.tztCommHeadPageLicaiActivity"
    android:configChanges="orientation|keyboardHidden|fontScale|screenSize"
    android:enabled="false"
    android:exported="true"
    android:icon="@drawable/tzt_icon_licai"
    android:label="@string/app_licai_name"
    android:screenOrientation="portrait"
    android:targetActivity=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity-alias>
String systemPath = "com.aliasicon.MainActivity";
String springPath = "com.zztzt.android.simple.activity.tztCommHeadPageAliasActivity";
String licaiPath = "com.zztzt.android.simple.activity.tztCommHeadPageLicaiActivity";
String genearlPath = "com.zztzt.android.simple.activity.tztCommHeadPageGenearlActivity";
String finalPath = "";
ComponentName genearlComponent;
ComponentName licaiComponent;
ComponentName springComponent;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    genearlComponent = new ComponentName(getApplication(), genearlPath);
    licaiComponent = new ComponentName(getApplication(), licaiPath);
    springComponent = new ComponentName(getApplication(), springPath);

//第一个默认按钮
    Button btnDefault = (Button) findViewById(R.id.tztToDefault);
    btnDefault.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            disableComponent(MainActivity.this, licaiComponent);
            disableComponent(MainActivity.this, springComponent);
            enableComponent(MainActivity.this, genearlComponent);
        }
    });
    //理财按钮
    Button btnLiCai = (Button) findViewById(R.id.tztToLiCai);
    btnLiCai.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            disableComponent(MainActivity.this, genearlComponent);
            disableComponent(MainActivity.this, springComponent);
            enableComponent(MainActivity.this, licaiComponent);
        }
    });
    //春节按钮
    Button btnSpring = (Button) findViewById(R.id.tztToSpring);
    btnSpring.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            disableComponent(MainActivity.this, genearlComponent);
            disableComponent(MainActivity.this, licaiComponent);
            enableComponent(MainActivity.this, springComponent);
        }
    });
}

/**
 * 启用组件 * 
 * @param componentName
 * 重要方法
 */
private void enableComponent(Activity activity, ComponentName componentName) {
    PackageManager pm = activity.getPackageManager();
    int state = pm.getComponentEnabledSetting(componentName);
    if (PackageManager.COMPONENT_ENABLED_STATE_ENABLED == state) {
        //已经启用
        return;
    }
    pm.setComponentEnabledSetting(componentName,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);
}

/**
 * 禁用组件 * 
 * @param componentName
 * 重要方法
 */
private void disableComponent(Activity activity, ComponentName componentName) {
    PackageManager pm = activity.getPackageManager();
    int state = pm.getComponentEnabledSetting(componentName);
    if (PackageManager.COMPONENT_ENABLED_STATE_DISABLED == state) {
        //已经禁用
        return;
    }
    pm.setComponentEnabledSetting(componentName,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP);
}

public void saveData(String savePath) {
    SharedPreferences sp = getSharedPreferences("Icon", Context.MODE_PRIVATE);
    //获取到edit对象
    SharedPreferences.Editor edit = sp.edit();
    //通过editor对象写入数据
    edit.putString("Value", savePath);
    //提交数据存入到xml文件中
    edit.commit();
}

public String getData() {
    SharedPreferences sp = getSharedPreferences("Icon", Context.MODE_PRIVATE);
    return sp.getString("Value", "");
}

2、巨坑
      通过上面的程序能够实现却换图标;如果代码里通过节假日的时间进行控制,则客户打开app会自动的切换图标;

是不是很神奇?先别高兴太早。

2.1App的覆盖
      任何App都会更新,进行覆盖安装。覆盖安装的Manifest的配置不当导致出现难以挽回的问题。

1、从上面的xml里配置可见,一个Activity和两个Activity-alisa的配置情况:

Activity的android:enabled="false"
            第一个Activity-alias的android:enabled="true"
            第二个Activity-alias的android:enabled="false"

所以App打开,桌面上默认的就是使用第一个Activity-alias的名字和图标。

2、如果新版本的配置还是按照这个配置(即使添加了新的alias,只要默认的Activity-alias不发生变化)客户端额升级覆盖安装,是不会出现错误的。

3、我们称之为“方案一”

2.2桌面上出现两个图标的问题
      1、如果新版本把Activity的enable设置为true(方案二),则桌面上除了原来的Activity-alias图标之外,还拥有了该Activity的图标,即有了两个图标;

Activity的android:enabled="true"
      第一个Activity-alias的android:enabled="false"
      第二个Activity-alias的android:enabled="false"

3、如果试图使用使用上面的代码里的disableComponent方法或者android:enabled="false"隐藏显示的Activity-alias图标,则导致两个图标都消失;

2.3桌面上图标消失的问题
      1、方案二会出现两个图标,如果再使用方案一进行覆盖,则两个图标都消失。

2、如果再次使用方案二进行覆盖,则图标还是能重新显示出来的。

2.4总结
      1、如果使用方案一进行覆盖安装,不管图标怎么动态的变换,再使用方案一进行覆盖安装,是正常的;

2、如果使用方案二进行覆盖安装,不管配置的图标是什么样的,再使用方案二进行覆盖安装,也是正常的;

3、如果使用方案一进行覆盖安装,如果图标没有动态切换的情况下,再使用方案二进行覆盖安装,也是正常的;

4、如果使用方案一进行覆盖安装,如果图标已经经过动态切换的情况下,再使用方案二进行覆盖安装,会出现双图标的;

5、如果使用方案一进行覆盖安装,如果图标已经经过动态切换的情况下,再使用方案二进行覆盖安装,会出现双图标的;如果在进行使用代码试图隐藏其中一个,则两个图标都消失;

6、如果使用方案一进行覆盖安装,如果图标没有动态切换的情况下,再使用方案二进行覆盖安装,也是正常的,再使用方案一进行覆盖安装,也是正常的;

2.5最终方案(方案一)
      采用方案一的方案,即通过代码动态变动图标,一定要注意以下事项:

1、Activity的android:enabled="false"

如果设置为true了,则会出现双图标;

2、Activity-alias的android:enabled="true"的默认显示的项不要中途进行变动,如果确实需要使用新的默认值,则使用代码进行动态变换;

3、Activity-alias的android:enabled="true"的不要设置为多个,否则会出现多个图标,如果试图通过代码进行隐藏其中的一个或者几个,可能会出现图标消失的情况

Android如何动态更换桌面图标(巨坑)相关推荐

  1. Android之动态更换桌面图标

    Android之动态更换桌面图标 文章链接:http://blog.csdn.net/qq_16628781/article/details/69054325 知识点 动态更换APP 桌面icon的引 ...

  2. Android中动态更换桌面图标Icon(记录)

    问题描述:支付宝.美团.淘宝之类的在某些节日的时候,桌面图标会进行自动进行变化,但是并没有进行APP更新之类的,想做这样的效果,怎么弄? 解决方案: (1)使用activity-alias来定义多个程 ...

  3. Android动态修改桌面图标新坑总结

    一.优秀文章概述 下面的文章描述动态修改桌面图标的基本方法,并且总结了很多坑及解决方案,以下是在此文章基础上的补充 <Android动态修改应用图标和名称> 二.第一个新坑 Android ...

  4. android实现动态图标,android实现动态更换应用图标

    1.配置activity别名 android:enabled 属性,布尔类型,是否开启别名设置,默认值为 true: android:exported 属性,布尔类型,是否支持其他应用通过这个别名访问 ...

  5. Android 动态改变桌面图标

    其实很简单,利用 AndroidManifest.xml 文件中的 <activity-alias> 标签即可实现. <activity-alias> 介绍 大家知道,对于 A ...

  6. Unity动态更换APP图标及名称

    Unity动态更换APP图标及名称 参考链接:https://blog.csdn.net/fu908323236/article/details/78813136 本文环境:(本文为安卓版) Unit ...

  7. (0042) iOS 开发之iOS10.3新特性:如何动态更换APP图标

    iOS新特性: iOS10.3教你如何动态更换APP图标? 1.iOS 10.3 开放了更换 app 图标的 API,核心方法是下面这个: [[UIApplication sharedApplicat ...

  8. 计算机更换桌面图标,Win10系统如何更换桌面图标呢?电脑更换桌面程序图标的操作方法...

    Win10系统电脑桌面上的图标对于熊孩子来说简介就是"秀色可餐"十分美观,在家里使用电脑时,有时候一不小心,熊孩子就在电脑上面乱点击,在日常工作中,其实我们可以将电脑桌面图标更改的 ...

  9. Android动态更换APP图标及名称

    前言 本来想研究一加手机上的天气APP,会随着每天的天气.温度不同动态的改变APP的图标是如何实现的,但始终没有想出和查阅到相关方法,毕竟是人家自己的系统APP.但是也找到了一种能动态改变图标的方法, ...

最新文章

  1. 分享实录|区块链技术与智能合约入门(开发实例)
  2. Android系统的进程分类
  3. oracle01507报错,oracle报错ORA-01507
  4. 【十二省联考2019】希望【点边容斥】【换根dp】【长链剖分】【线性数据结构】【回退数据结构】【离线逆元】
  5. C语言 按位或 正整数与负整数 之间
  6. SQL批量提交修改业务
  7. HTML5中volume样式自定义,html5中关于volume属性的使用详解
  8. 技术改变生活,统一通信走向深度融合
  9. android mtk平台,android mtk平台默认输入法
  10. 利用WaitForInputIdle等待初始化完成CreateProcess
  11. html4多文件上传,jQuery h5拖拽多文件上传
  12. spring-第七篇之深入理解容器中的bean
  13. canvas 加载图片
  14. JAVA全栈工程师学习线路
  15. UWB测距及定位原理
  16. openresty实现隧道代理
  17. 超低功耗MCU的选择方法
  18. html5游戏防止作弊,html5 canvas模拟的小球躲避小游戏
  19. Exchange 2019数据库切换
  20. 1262: 魔法宝石 (“玲珑杯”河南工业大学ACM程序设计大赛)

热门文章

  1. SCA可达性分析基础知识普及
  2. 一文详解激光雷达的障碍物检测
  3. C# VBA 提取word中图片方法
  4. 利用python进行数据分析——透视表与交叉表
  5. 程序员难以逃避的几个坎儿及解决方法
  6. RE合同记账会计凭证
  7. 经济法基础(2020年)——第三章 支付结算法律制度
  8. 在家使用IPv6访问NAS服务器
  9. 为什么你需要一台NAS(网盘云盘vs路由器硬盘vsNAS)
  10. P1196 [NOI2002] 银河英雄传说 (并查集 合并