前言
今天来了一个新需求需要面对不同的用户使用不同的图标以及欢迎界面,应用内部是一样的,如果每次都手动替换icon以及欢迎界面,无疑是很不程序员的做法,刚巧今早在wanandroid看到了一篇关于如何动态更新应用图标的博文,很受启发,故记录一二,顺便分享给大家。
实现
首先是动态icon的实现,其实这个在很多的应用上面都已经存在了,比如支付宝快到双十一的时候就会显示另外一个图标可是我们并没有下载新版的支付宝,关键原理就是使用了activity-alias标签。我们可以通过此标签给一个Activity设置一个"别名",相当于一个Activity有两个入口,当我们给启动类设置"别名"以后,Launcher上面会同时显示两个图标,我们可以通过代码设置其中一个为不可用,那么就只会剩下我们想显示的那个了。
activity-alias标签的使用与activity一样,可以设置icon、label、name等,不同的是其有一个targetActivity属性用来指向真实被启动的Activity。所以我们可以预先在某一个版本中埋下不同的图标,然后在程序中控制,在某一段时间内显示对应的图标。代码如下。
private void enableComponent(ComponentName componentName) { getPackageManager().setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); } private void disableComponent(ComponentName componentName) { getPackageManager().setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); }
然后是在AndroidManifest.xml中埋下我们需要显示的图标。可以看到,我除了定义主Activity以外还定义了两个activity-alias分别对应"双十一"、"双十二"两个activity-alias并设置好了name、icon、label等属性,由于默认的时候不需要显示,所以android:enabled="false"
<activity android:name=".MainActivity" android:icon="@mipmap/ic_default" android:label="默认"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity-alias android:name=".MainActivity1111" android:enabled="false" android:icon="@mipmap/ic_1111" android:label="双十一" 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=".MainActivity1212" android:enabled="false" android:icon="@mipmap/ic_1212" android:label="双十二" 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设置为可用/不可用即可。
public class MainActivity extends AppCompatActivity { private ComponentName mComponentName1111; private ComponentName mComponentName1212; private ComponentName mComponentNameDefault; @Override protected void onCreate(Bundle savedInstanceState) { String packageName = getPackageName(); mComponentName1111 = new ComponentName(this, packageName + ".MainActivity1111"); mComponentName1212 = new ComponentName(this, packageName + ".MainActivity1212"); mComponentNameDefault = new ComponentName(this, packageName + ".MainActivity"); } /** * 双十一图标 */ public void onChangeIconFor1111(View view) { enableComponent(mComponentName1111); disableComponent(mComponentName1212); disableComponent(mComponentNameDefault); } private void enableComponent(ComponentName componentName) { getPackageManager().setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); } private void disableComponent(ComponentName componentName) { getPackageManager().setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); } }
通过上面的设置我们就可以通过业务逻辑决定显示什么icon了,不过由于ROM的不同,当设置以后,可能不是即时的刷新图标,需要等待一段时间Launcher才会刷新图标的。
如果有业务需要实现对于不同的入口显示不同的欢迎界面或者其他的一些特殊处理逻辑,我们可以在Activity中使用getTitle()获取到android:label设置的值,通过其即可判断用户是通过什么图标进入到我们的应用的。