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

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

动态更换应用Icon

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

开发:不可以

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

开发:不可以

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

开发:不可以

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

开发:让我想想……

原理1——activity-alias

在AndroidMainifest中,有两个属性:

  1. // 决定应用程序***启动的Activity 
  2.  
  3. android.intent.action.MAIN 
  4.  
  5. // 决定应用程序是否显示在程序列表里 
  6.  
  7. android.intent.category.LAUNCHER  

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

原理2——PM.setComponentEnabledSetting

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

使用方式异常简单: 

  1. private void enableComponent(ComponentName componentName) { 
  2.  
  3.     mPm.setComponentEnabledSetting(componentName, 
  4.  
  5.             PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 
  6.  
  7.             PackageManager.DONT_KILL_APP); 
  8.  
  9.  
  10.   
  11.  
  12. private void disableComponent(ComponentName componentName) { 
  13.  
  14.     mPm.setComponentEnabledSetting(componentName, 
  15.  
  16.             PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 
  17.  
  18.             PackageManager.DONT_KILL_APP); 
  19.  
  20.  

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

动态换Icon

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

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

  1. <activity android:name=".MainActivity"
  2.  
  3.     <intent-filter> 
  4.  
  5.         <action android:name="android.intent.action.MAIN"/> 
  6.  
  7.   
  8.  
  9.         <category android:name="android.intent.category.LAUNCHER"/> 
  10.  
  11.     </intent-filter> 
  12.  
  13. </activity> 
  14.  
  15.   
  16.  
  17. <activity-alias 
  18.  
  19.     android:name=".Test11" 
  20.  
  21.     android:enabled="false" 
  22.  
  23.     android:icon="@drawable/s11" 
  24.  
  25.     android:label="双11" 
  26.  
  27.     android:targetActivity=".MainActivity"
  28.  
  29.     <intent-filter> 
  30.  
  31.         <action android:name="android.intent.action.MAIN"/> 
  32.  
  33.   
  34.  
  35.         <category android:name="android.intent.category.LAUNCHER"/> 
  36.  
  37.     </intent-filter> 
  38.  
  39. </activity-alias> 
  40.  
  41.   
  42.  
  43. <activity-alias 
  44.  
  45.     android:name=".Test12" 
  46.  
  47.     android:enabled="false" 
  48.  
  49.     android:icon="@drawable/s12" 
  50.  
  51.     android:label="双12" 
  52.  
  53.     android:targetActivity=".MainActivity"
  54.  
  55.     <intent-filter> 
  56.  
  57.         <action android:name="android.intent.action.MAIN"/> 
  58.  
  59.   
  60.  
  61.         <category android:name="android.intent.category.LAUNCHER"/> 
  62.  
  63.     </intent-filter> 
  64.  
  65. </activity-alias>  

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

  1. public class MainActivity extends AppCompatActivity { 
  2.  
  3.   
  4.  
  5.     private ComponentName mDefault; 
  6.  
  7.     private ComponentName mDouble11; 
  8.  
  9.     private ComponentName mDouble12; 
  10.  
  11.     private PackageManager mPm; 
  12.  
  13.   
  14.  
  15.     @Override 
  16.  
  17.     protected void onCreate(Bundle savedInstanceState) { 
  18.  
  19.         super.onCreate(savedInstanceState); 
  20.  
  21.         setContentView(R.layout.activity_main); 
  22.  
  23.         mDefault = getComponentName(); 
  24.  
  25.         mDouble11 = new ComponentName( 
  26.  
  27.                 getBaseContext(), 
  28.  
  29.                 "com.xys.changeicon.Test11"); 
  30.  
  31.         mDouble12 = new ComponentName( 
  32.  
  33.                 getBaseContext(), 
  34.  
  35.                 "com.xys.changeicon.Test12"); 
  36.  
  37.         mPm = getApplicationContext().getPackageManager(); 
  38.  
  39.     } 
  40.  
  41.   
  42.  
  43.     public void changeIcon11(View view) { 
  44.  
  45.         disableComponent(mDefault); 
  46.  
  47.         disableComponent(mDouble12); 
  48.  
  49.         enableComponent(mDouble11); 
  50.  
  51.     } 
  52.  
  53.   
  54.  
  55.     public void changeIcon12(View view) { 
  56.  
  57.         disableComponent(mDefault); 
  58.  
  59.         disableComponent(mDouble11); 
  60.  
  61.         enableComponent(mDouble12); 
  62.  
  63.     } 
  64.  
  65.   
  66.  
  67.     private void enableComponent(ComponentName componentName) { 
  68.  
  69.         mPm.setComponentEnabledSetting(componentName, 
  70.  
  71.                 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 
  72.  
  73.                 PackageManager.DONT_KILL_APP); 
  74.  
  75.     } 
  76.  
  77.   
  78.  
  79.     private void disableComponent(ComponentName componentName) { 
  80.  
  81.         mPm.setComponentEnabledSetting(componentName, 
  82.  
  83.                 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 
  84.  
  85.                 PackageManager.DONT_KILL_APP); 
  86.  
  87.     } 
  88.  
  89.  

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

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

效果参考下图。 

 

 

[[180569]] 

专栏作者简介

eclipse_xu:Android 高级开发工程师;《Android群英传》、《Android群英传:神兵利器》作者、慕课网Android讲师;CSDN博客专家

责任编辑:庞桂玉 来源: 安卓开发精选
相关推荐

2016-12-02 08:53:18

Python一行代码

2017-04-05 11:10:23

Javascript代码前端

2022-04-09 09:11:33

Python

2014-02-12 13:43:50

代码并行任务

2022-04-11 11:38:44

Python代码游戏

2020-04-10 15:20:40

数据库SQL索引

2017-04-13 19:20:18

Python代码并行任务

2021-08-31 09:49:37

CPU执行语言

2020-08-19 10:30:25

代码Python多线程

2021-11-02 16:25:41

Python代码技巧

2020-09-09 16:00:22

Linux进程

2023-09-12 10:10:57

开发者工具开源

2019-12-25 14:08:50

Pandas数据计算

2020-08-12 14:54:00

Python代码开发

2020-09-28 12:34:38

Python代码开发

2020-08-03 09:05:48

代码程序员案例

2021-02-24 14:30:59

JavaScript语言开发

2020-07-15 09:40:37

代码Python浏览记录

2020-01-10 22:56:56

Python图像处理Linux

2021-05-28 07:39:17

SQL代码操作
点赞
收藏

51CTO技术栈公众号