美文网首页
Android 是否可以动态配置 launcher icon

Android 是否可以动态配置 launcher icon

作者: 半老Coder | 来源:发表于2020-06-29 17:50 被阅读0次

今天接到这样一个需求,要求 APP 图标可以动态配置,也就是通过后台接口能灵活配置让用户看到不同的桌面启动 icon 。比如双11当天,用户看到自己桌面上的 icon 底部带了双11的标记 。


淘宝双 11 icon

是不是很美好, 发版都不需要了。只需要运营配置好节日当天显示就可以了。节日过了之后再换回来 ,堪称完美。但是系统当真允许我们这样搞么 ?

前言

我们知道Android的启动图标是放到 AndroidManifest application 标签下的 android:icon 对应的图片, 并且这张图片必须是 apk 包里的,而且官方 api 没有方案可以更改这个属性值。那么跟产品怼回去说技术方案不可行 ?然而产品已经把市面上已经实现了此功能的方案APP拿到了面前。你告诉产品或许应用市场帮你把 APP 自动更新了, 产品:"我不听 我不听 我不听 "。

按照传统一顿 Google 之后 , 产品需要的效果是可以实现的。但是坑得自己踩。废话不再多说正文开始。

正文

上文已经说明,没有api 可以直接换 launcher icon , 那如何实现呢?

官方 api 是提供同一个app 多个入口能力的 ,上代码

<activity-alias
    android:name=".changeicon.TwoLauncherAlias"
    android:enabled="false"
    android:icon="@drawable/logo_two"
    android:label="Two"
    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=".changeicon.OneLauncherAlias"
    android:enabled="false"
    android:icon="@drawable/logo_one"
    android:label="One"
    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 并且指定不同的 icon ,在enable 设置为true的情况下,app 会显示多个 icon ,跳转到的Activity 页面 对应 targetActivity value 。在以上 enable 都设置为true的情况下 桌面显示如下,图片是我随便放的

从左到右、第一个为主app launcher icon 后两个对应activity-alias 配置的icon

我们可以看到,不光 icon 可以动态, APP name 也是可以动态变化的。但是 icon 需要的图片 以及 name 对应的字符串,都必须预埋到 apk 包内

实现动态切换 icon 能力,就是从此功能延伸。代码可以动态控制 activity-alias enable value ,从而可以实现看起来的动态 切换 icon 的效果。代码控制enable value 如下

getPackageManager().setComponentEnabledSetting(
        new ComponentName(this, OneLauncherAlias.class),
        PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
        PackageManager.DONT_KILL_APP);

getPackageManager().setComponentEnabledSetting(
        new ComponentName(this, MainActivity.class),
        PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
        PackageManager.DONT_KILL_APP);

也就是 上述 xml 中两个 activity-alias enable 均设置为 false ,我们将上述代码 放到 button 的 onClick 事件中 。app 主 icon 为Android机器人 , 点击按钮之后变为 对号 icon 。 动图如下 (请耐心等待最后效果)

动态

效果这就结束了么? 当然不是, 这才刚刚开始。

从动图可以看出, onClick 后执行上述代码 , app icon 并没有马上切换,这台小米机器大概 10 秒左右的时间会切换 ,并且 会闪一下

然后我们发现另外一个问题 , 在 icon 执行切换的时候 。点击 icon 会提示找不到此应用 ,一两秒后恢复

问:什么时候执行icon切换代码 ?我可以在 app 启动的时候执行切换么?

细心的朋友已经发现了,动图上我手动退出到桌面等待 app 切换生效了,那如果我没有手动退出 app 到桌面会怎样呢 ?答案是 当前进程会被kill掉 。看起来跟你的app 闪退了一模一样 ,所以这个效果是绝对不能接受的

问:切换中代码 有标识 PackageManager.DONT_KILL_APP 为什么还会kill 掉app 呢?

这个真不清楚

问:那应该怎么办呢

我做过的尝试如下

1、把切换代码放到 Service 中执行是不是可以呢?

那我一条push 下来就可以了。 结果是失败的, 一样 kill 掉进程 。

2、尝试把service 运行到单独的进程中

结果也是一样 ,app 进程 kill ,看起来跟 挂了一样。

所以只能把 切换icon 的逻辑放到了 "再点一次退出APP" , 相信绝大多数APP都有这个逻辑 。这样是我找到的对用户影响最小的方式。(也就是还是会闪一下)。APP 启动后拉取配置缓存起来, 在 "再点一次退出APP" 这个时机读取配置进行 APP icon 更换。

问:那就没问题可以上线了吧

开始我也是这么觉得的,直到 QA 报了一个 Critical 的bug, 覆盖安装之后 APP 从手机上消失了。并且还 复现不了

现在你应该已经开始怀疑人生了,并且 你搜了国内外 论坛 & blog 发现有人遇到了此问题,并且没有找到解决方案 。人生就是这么奇妙。

最终我们还是定位到了这个问题,原因是 QA 首先安装了新包,从服务器拉到了配置并且 icon 切换到了活动 icon ,然后覆盖安装了前一天的包,一个不包含 activity-alias 的包,这个时候从桌面已经没有办法找到 我们的APP了。

那APP是被卸载了么?

答案是并没有,在应用程序列表还是能找到的,只是入口没了。

那我从应用市场重新下一个安装是不是就可以了呢?

如果应用市场上的包不包含 activity-alias 的话,市场覆盖安装也是没有用的,并且 连卸载都没法卸载

问:这种情况能避免么,怎么避免?

答案是可以的 。

1、代码中一旦配置过 activity-alias 是绝对不允许删除的。

解释一下上述结论原因,既然需要配置,配置就有不生效的可能性。假设这样一种场景 , 用户在活动当天打开 APP 并且成功切换到活动icon了, 之后再也没打开过 APP , 过了一段时间用户更新新版本(注意此时用户手机上还是活动icon),新版本把包含 活动icon的 activity-alias 代码移除掉了,升级成功后这个时候 APP 就从桌面永远消失了。 一旦出现,这个问题很难解决。

2、配置活动图标后,活动结束一定及时换回来,也就是换回 APP 的主 launcher icon 。


总结一下

优点

产品要求 icon 能变的效果是可以实现的

局限性 & 风险

1、需要把 icon 预埋到客户端

2、icon 切换的时机有限制

3、icon 切换的时候会闪一下

4、icon 切换的时候 ,会有1秒左右时间 点击 icon 会提示找不到此应用

5、需要及时换回来

6、代码管理不善,有 APP 从桌面再也找不到的风险

此方案过了QA 团队 , 经历了线上 百万活跃用户的考验。这个功能上的时候我还是很忐忑的,最终经受住了考验,还是很欣慰的。如果这篇文章能帮到你很开心,我是乐(yue)进 , 公众号"乐进说" ,有问题欢迎找我探讨。

相关文章

网友评论

      本文标题:Android 是否可以动态配置 launcher icon

      本文链接:https://www.haomeiwen.com/subject/ftlafktx.html