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

简介:

221affbf94c26b396f1c82df813846bc0e5409a8

动态更换应用Icon

产品:我们可以动态更换App在Launcher里面的Icon吗

开发:不可以

产品:我们可以动态更换App在Launcher里面的Icon吗

开发:不可以

产品:我们可以动态更换App在Launcher里面的Icon吗

开发:不可以

产品:我们可以动态更换App在Launcher里面的Icon吗

开发:让我想想……


效果图:

640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=

原理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会自动刷新图标。

效果参考下图。

640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=

原文发布时间为:2018-10-12

本文作者:yuer

本文来自云栖社区合作伙伴“终端研发部”,了解相关信息可以关注“终端研发部”。

相关文章
|
4月前
|
数据可视化 Go 开发工具
cggit 简化 Git 提交、合并、分支偏移小神器,提升开发、修BUG效率!
cggit 简化 Git 提交、合并、分支偏移小神器,提升开发、修BUG效率!
39 0
|
7月前
|
开发工具 git
强迫症如何干净删除 commit 记录
强迫症如何干净删除 commit 记录
|
8月前
uniapp bug记录(后续更新)
uniapp bug记录(后续更新)
70 0
|
9月前
idea 更新代码后,未提交的代码丢失
idea 更新代码后,未提交的代码丢失
372 0
|
11月前
|
测试技术 数据库
项目上线出bug怎么处理
项目上线出bug怎么处理
|
Java 应用服务中间件 Docker
同事嫌我改Bug慢,原来是没掌握这些代码Debug技巧
代码Debug调试是研发工程师日常工作中必不可少的重要组成部分。进行代码Debug调试的目的无非就两个,一个是自我检查代码逻辑是否有问题,便于自己将Bug消灭在测试介入之前;另一个是进行线上问题排查定位,找到实际在跑业务的过程中出现的Bug。
同事嫌我改Bug慢,原来是没掌握这些代码Debug技巧
|
前端开发
前端工作小结12-工具里面代码提交
前端工作小结12-工具里面代码提交
56 0
前端工作小结12-工具里面代码提交
|
JSON JavaScript 前端开发
前端工作小结18-报错简单记录
前端工作小结18-报错简单记录
87 0
|
JSON 数据可视化 JavaScript
开发改了接口,经常忘通知测试,有什么好的解决方案吗?
不知道大家有没有同感,做接口测试麻烦的不是测试本身,而是接口它会变,更麻烦的不是接口变了,而是它变了而你不知道。等到你测完,开发才悠悠跟你说——“那个接口我改了点东西,你再看一眼哈”。
开发改了接口,经常忘通知测试,有什么好的解决方案吗?
|
存储 Unix 程序员
被通知一个月后离职,我改了重要项目里的代码注释
假如你已经对某个开发人员下发解雇通知,你还会让他深度参与重要项目甚至把项目做完再走吗?放在今天,这个答案往往是显而易见的:不会。但如果是几十年前,那就未必了。
206 0
被通知一个月后离职,我改了重要项目里的代码注释