上次发版我就改了一行代码!

简介: 动态更换应用Icon产品:我们可以动态更换App在Launcher里面的Icon吗 开发:不可以 产品:我们可以动态更换App在Launcher里面的Icon吗 开发:不可以 产品...

动态更换应用Icon

产品:我们可以动态更换App在Launcher里面的Icon吗
开发:不可以
产品:我们可以动态更换App在Launcher里面的Icon吗
开发:不可以
产品:我们可以动态更换App在Launcher里面的Icon吗
开发:不可以
产品:我们可以动态更换App在Launcher里面的Icon吗
开发:让我想想……

原理1——activity-alias

在AndroidMainifest中,有两个属性:

// 决定应用程序最先启动的Activity
android.intent.action.MAIN 
// 决定应用程序是否显示在程序列表里
android.intent.category.LAUNCHER 

另外,还有一个activity-alias属性,这个属性可以用于创建多个不同的入口,相信做过系统Setting和Launcher开发的开发者在系统的源码中应该见过很多。

原理2——PM.setComponentEnabledSetting

PackageManager是一个大统领类,可以管理所有的系统组件,当然,如果Root了,你还可以管理其它App的所有组件,一些系统优化工具就是通过这个方式来禁用一些后台Service的。

使用方式异常简单:

private void enableComponent(ComponentName componentName) {
    mPm.setComponentEnabledSetting(componentName,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);
}

private void disableComponent(ComponentName componentName) {
    mPm.setComponentEnabledSetting(componentName,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP);
}

根据PackageManager.COMPONENT_ENABLED_STATE_ENABLED和PackageManager.COMPONENT_ENABLED_STATE_DISABLED这两个标志量和对应的ComponentName,就可以控制一个组件的是否启用。

动态换Icon

有了上面的两个原理,来实现动态更换Icon就只剩下思路问题了。

首先,我们创建一个Activity,作为默认的入口并带着默认的图片,再创建一个双11的activity-alias,指向默认的Activity并带有双11的图片,再创建一个双12的activity-alias,指向默认的Activity并带有双12的图片……等等等。

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

<activity-alias
    android:name=".Test11"
    android:enabled="false"
    android:icon="@drawable/s11"
    android:label="双11"
    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=".Test12"
    android:enabled="false"
    android:icon="@drawable/s12"
    android:label="双12"
    android:targetActivity=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity-alias>

等等,这样有个问题,那就是这样会在Launcher上显示3个入口,所以,默认我们会把这些activity-alias先禁用,等到要用的时候再启用,养兵千日,用兵一时。

public class MainActivity extends AppCompatActivity {

    private ComponentName mDefault;
    private ComponentName mDouble11;
    private ComponentName mDouble12;
    private PackageManager mPm;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDefault = getComponentName();
        mDouble11 = new ComponentName(
                getBaseContext(),
                "com.xys.changeicon.Test11");
        mDouble12 = new ComponentName(
                getBaseContext(),
                "com.xys.changeicon.Test12");
        mPm = getApplicationContext().getPackageManager();
    }

    public void changeIcon11(View view) {
        disableComponent(mDefault);
        disableComponent(mDouble12);
        enableComponent(mDouble11);
    }

    public void changeIcon12(View view) {
        disableComponent(mDefault);
        disableComponent(mDouble11);
        enableComponent(mDouble12);
    }

    private void enableComponent(ComponentName componentName) {
        mPm.setComponentEnabledSetting(componentName,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
    }

    private void disableComponent(ComponentName componentName) {
        mPm.setComponentEnabledSetting(componentName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
    }
}

OK了,禁用默认的Activity后,启用双11的activity-alias,结果不变还是指向了默认的Activity,但图标已经发生了改变。

根据ROM的不同,在禁用了组件之后,会等一会,Launcher会自动刷新图标。

效果参考下图。

这里写图片描述

目录
相关文章
|
存储 并行计算 算法
C++进程间通信之共享内存
C++进程间通信之共享内存
1226 0
|
11月前
|
自然语言处理 资源调度 并行计算
从本地部署到企业级服务:十种主流LLM推理框架的技术介绍与对比
本文深入探讨了十种主流的大语言模型(LLM)服务引擎和工具,涵盖从轻量级本地部署到高性能企业级解决方案,详细分析了它们的技术特点、优势及局限性,旨在为研究人员和工程团队提供适合不同应用场景的技术方案。内容涉及WebLLM、LM Studio、Ollama、vLLM、LightLLM、OpenLLM、HuggingFace TGI、GPT4ALL、llama.cpp及Triton Inference Server与TensorRT-LLM等。
1462 7
|
8月前
|
域名解析 网络协议 Ubuntu
dig 命令深入学习
dig 命令(Domain Information Groper)是一个用于查询 DNS (域名系统)记录的强大工具,它提供了详细的DNS信息,主要用于帮助用户诊断、调试和验证与域名解析相关的问题。
|
11月前
|
机器学习/深度学习 数据采集 人工智能
《人工智能如何加速药物研发进程:从新药发现到临床试验的突破》
在医药领域,药物研发复杂且成本高昂,新药推出面临诸多挑战。人工智能(AI)通过分析海量生物数据,加速靶点识别、药物分子设计及临床试验设计与数据分析,显著提升研发效率和质量。AI利用机器学习算法和大数据分析,优化试验方案,预测药物疗效与安全性,助力智能化药物研发平台的建设。尽管存在数据质量和隐私等挑战,AI仍为药物研发带来巨大潜力与创新机遇。
522 10
|
安全 NoSQL Redis
服务器又被攻击了,我这样做...
近期遭遇阿里云服务器频繁报警,经分析发现是由于测试服务器所有端口对公网开放,导致自动化程序对其扫描。黑客可能利用类似Redis的未授权访问漏洞进行攻击。为避免此类问题,建议:1. 不开放不必要的端口;2. 避免以root权限运行服务;3. 设置服务器IP白名单;4. 定期更换密码。保持良好安全习惯可保障服务器安全。
3972 4
服务器又被攻击了,我这样做...
|
监控 Java 数据库连接
EMQ
|
消息中间件 物联网 网络安全
2023 年最适用于工业物联网领域的三款开源 MQTT Broker
本文对比分析了 2023 年工业物联网领域最优秀的三款 MQTT Broker,介绍了它们的优点、缺点和应用场景。
EMQ
1867 0
2023 年最适用于工业物联网领域的三款开源 MQTT Broker
|
JSON API 数据格式
在钉钉中,你可以使用API来获取文件或文件夹的信息
在钉钉中,你可以使用API来获取文件或文件夹的信息
450 2
|
缓存 NoSQL 前端开发
springboot+vue前后端分离实现企业人事管理系统
系统是前后端分离的项目,直接启动Springboot应用程序类后,再启动前端工程访问即可。主要实现 了企业的人事管理功能,主要包含员工管理、薪资管理、职位管理、权限管理、网盘文件分享管理等模块。 系统亮点:使用REDIS进行数据缓存,优化查询性能;使用分布式文件系统进行文件存储服务;基于Springboot+vue实现前后端分离开发
711 0
springboot+vue前后端分离实现企业人事管理系统
|
Shell Linux
Linux安装Anaconda(Anaconda3-2022.10-Linux-x86_64.sh版本)(1)
Linux安装Anaconda(Anaconda3-2022.10-Linux-x86_64.sh版本)(1)
890 0
Linux安装Anaconda(Anaconda3-2022.10-Linux-x86_64.sh版本)(1)