Android动态更换ICON方案

前言

1
2
3
4
5
细心的用户会发现,一到某些节日如双11,某些网购平台的App会自动更换其Logo。

事实上这是一个很古老的技术点,但如果控制不好,会带来一定的风险。

本人在年末便有一个这样的需求,需要在过年期间自动更换为新年Logo

1、技术原理

  • 技术原理很简单,就是给App配置多个入口,然后通过 enabled 属性来控制入口的显示和隐藏。
  • 一种方案是配置多个入口 Activity
  • 另一种方案是给 Activity 配置 <activity-alias>,这和第一种方案类似,但又有不同。

2、activity-alias 方案

2.1、配置桌面入口

  • 以下为 AndroidManifest.xml 中的代码片段:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- 原 ICON 对应的 Activity -->
<activity
android:name=".SplashActivity"
android:enabled="true"
android:exported="true"
android:icon="@mipmap/ic_launcher"
android:theme="@style/AppLauncherTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 节日 ICON -->
<activity-alias
android:name=".Special"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/ic_festival"
android:targetActivity=".SplashActivity"
android:theme="@style/AppLauncherTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
  • 从代码中可以看出,我们从 Launcher 启动的是 SplashActivity
  • 通过 activity-alias 配置了一个 Special 代作为活动时的入口,其对应的 android:targetActivity 仍然是原来的 SplashActivity
  • 由于配置了 android:enabled="false",故在桌面上只会显示一个图标。

2.2、代码调用

  • 在节日触发的地方需要更换对应的图标。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
val pm = packageManager
val sp = getSharedPreferences("logo_special", MODE_PRIVATE)
val isSpecial = sp.getString("isSpecial", "")
val componentDefault = ComponentName(packageName, "$packageName.SplashActivity")
val componentSpecial = ComponentName(packageName, "$packageName.Special")
if (isSpecial != null && isSpecial.isNotEmpty()) {
Log.i(tag, "run Special Page..")
if (pm.getComponentEnabledSetting(componentDefault) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
pm.setComponentEnabledSetting(
componentDefault,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
pm.setComponentEnabledSetting(
componentSpecial,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
}
} else {
Log.i(tag, "run Default Page..")
if (pm.getComponentEnabledSetting(componentSpecial) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
pm.setComponentEnabledSetting(
componentSpecial,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
pm.setComponentEnabledSetting(
componentDefault,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
}
}
  • 通过 pm.setComponentEnabledSetting(component) 来设置某一个 Activityandroid:enabledtruefalse

3、风险点

3.1、App自动退出

  • 通过调用该代码会发现,在切换 Icon 时会主动退出 App,且没有任何报错。
  • 切换图标需要时间,大部分机型只需要3秒,某为的机型需要10秒。
  • 切换图标的过程中,如果点击图标,无法正常打开 App,会提示应用未安装。
1
提示: 针对自动退出问题,可以采用在程序退出或在后台时,进行Icon切换。


Android动态更换ICON方案
http://jxr202.github.io/android/android_001-e4af71b30634/
作者
Jiang
发布于
2022年12月2日
许可协议