APP,在中国电商行业中,某宝和某东是行业的标杆。其中有一点挺让人好奇的,那就是在双十一临近之时,他们的APP桌面图标突然变成了带有双十一字样的图标。但是明明记得那段时间并没有更新过,那么唯一的可能就是本来就内置了双十一的图标,等快到双十一的时候在动态更换,然后过了双十一那段时间,又将APP的桌面图标变成普通的icon。
既然图标本来就在APP里头(或者是网络下载下来的,只是猜测,有知道的小伙伴可以给我留言),那么就很好奇了,它们的图标到底是怎么样进行动态的更换的呢?
对于Android来说,所有的activity都是一个组件,我们可以对每个组件进行管理。
关于程序的入口,我们知道android.intent.action.MAIN进行的指定的。
<activity
android:name=".HomeActivity"
android:label="@string/app_name"
android:theme="@style/AppThemeToolbar">
<intent-filter>
//指定应用程序最先启动的Activity
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity>
对于android.intent.category.LAUNCHER,这个又是设置什么的呢?这个是决定应用程序是否显示在程序列表里头。
另外,还有一个activity-alias属性,这个属性可以用于创建多个不同的入口。用法如下所示:
<activity
android:name=".HomeActivity"
android:label="@string/app_name"
android:theme="@style/AppThemeToolbar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity>
<activity-alias
android:name=".HomeActivity2"
android:enabled="false"
android:icon="@drawable/icon2"
android:label="icon2"
android:targetActivity=".HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity-alias>
<activity-alias
android:name=".HomeActivity3"
android:enabled="false"
android:icon="@drawable/icon3"
android:label="icon3"
android:targetActivity=".HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity-alias>
如上面代码显示,这里有3个程序的入口,其中第二和第三个是被禁用掉的,如果enable缺省值,那么默认是true。既然可以XML中禁用,那么对应的也可以在代码中启动组件了。
APP的icon是对于整个包范围的,既然是要动用到APP包,那么是不是系统就给我们提供了一个管理整个包的类呢?事实上,系统给我们提供了PackageManager这个类,这个类能够获取到当前应用里不同类型的信息。定义了一系列比如的服务的字段常量,低功耗ble蓝牙,相机==,以及一系列有关包操作的抽象方法。此类可以管理所有的系统组件。
我们知道APP上每一个对象都是系统里的一个组件,那么我们可以在PackageManager类里面看到有关于组件的操作方法;
这个方法有以下比较重要的方法:
//设置特定组件是否可以启动方法
public abstract void setComponentEnabledSetting(ComponentName componentName, int newState, int flags);
//相反,得到特定组件是否启动的方法
public abstract int getComponentEnabledSetting(ComponentName componentName);
参数1:组件的名称;
参数2:组件新的状态;
参数3:标志是否要killapp;
有了以上两个方法,我们就可以根据给定不同的组件名称+状态进行设置是否可用了。结合探索1里面定义的3个组件的启动和禁止情况,我们可以进行对应的enable操作。
private PackageManager mPackageManager;
//默认组件
private ComponentName componentNameDefault;
private ComponentName componentName2;
private ComponentName componentName3;
/**
* 设置第icon2图标生效
*/
private void enableComponentName2() {
disableComponent(componentNameDefault);
disableComponent(componentName3);
enableComponent(componentName2);
}
/**
* 设置第icon3图标生效
*/
private void enableComponentName3() {
disableComponent(componentNameDefault);
disableComponent(componentName2);
enableComponent(componentName3);
}
/**
* 启动组件
*
* @param componentName 组件名
*/
private void enableComponent(ComponentName componentName) {
//此方法用以启用和禁用组件,会覆盖Androidmanifest文件下定义的属性
mPackageManager.setComponentEnabledSetting(componentName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
/**
* 禁用组件
*
* @param componentName 组件名
*/
private void disableComponent(ComponentName componentName) {
mPackageManager.setComponentEnabledSetting(componentName,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
//最后调用
public void pmTest() {
//获取到包管理类实例
mPackageManager = getPackageManager();
//得到此activity的全限定名
componentNameDefault = getComponentName();
//根据全限定名创建一个组件,即activity-alias 节点下的name:HomeActivity2 对应的组件
componentName2 = new ComponentName(getBaseContext(), "com.yaojt.HomeActivity2");
componentName3 = new ComponentName(getBaseContext(), "com.yaojt.HomeActivity3");
String action = getActionFromServer();//从后台获取到应该使用那一个组件,或者根据时间来判断
if ("comp2".equals(action)){
enableComponentName2();
}else if ("comp3".equals(action)){
enableComponentName3();
}
//如果没有,则显示默认图标
}
通过以上的代码,可以清楚的看到,如何获取已经在XML文件里面定义好的组件。然后根据不同需求,来启用或者禁止对应的组件,从而达到更新APP桌面图标的功能。(可能需要一段时间刷新,才能看到新的APP桌面图标)
PackageInfo:装载Androidmanifest.xml文件所有信息的类。
所有的信息都来自AndroidManifest.xml文件;例如,包名packageName、版本号versionCode、sharedUserId共享id、apk第一次和最后一次安装时间、声明的activity,service、receiver、provider和请求的权限等等的信息。
以上就是其中一种动态桌面更换图标的方法,需要的是预先放入需要更换的icon进去,或许还可以支持动态的设置icon,但是这部分我还没有仔细的去研究。如果你知道,请留言告知我,大家共同学习进步。
如有任何问题,请及时与我联系。谢谢