Android 在线更新APP icon技术调研

需求描述

当前app的桌面icon没法实现在线静默更换,为了满足节假日运营需求,现在必须通过发布新版本的方式才能更新appicon。所以希望app能实现在线静默更新appicon。

具体要求

目前来看app对于icon的更新频次并不高,并且运营需求也相对简单不复杂。所以,app预置一到两个版本的icon,并在特定的时间静默生效就能满足基本的需求。

技术原理

在AndroidManifest.xml中增加<activity-alias>标签,在代码中通过PackageManager的setComponentEnabledSetting方法来动态打开enabled属性从而显示对应icon。

官方API说明:

https://developer.android.google.cn/guide/topics/manifest/activity-alias-element

https://developer.android.google.cn/reference/android/content/pm/PackageManager?hl=en#setComponentEnabledSetting(android.content.ComponentName,%20int,%20int)

实现

  1. 在AndroidManifest.xml中声明<activity-alias>,配置文件里面可以声明多个<activity-alias>,也就对应多个icon。
<activity-alias
android:name=".MainActivity1"
android:enabled="false"
android:icon="@mipmap/icon_1"
android:label="@string/app_name"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity-alias>

属性enabled默认为false,在为true时,桌面就会显示图标icon_1,如果没有关闭主icon的话,桌面就会出现两个icon。

而<intent-filter>的作用就和activity组件是一样的,<activity-alias>虽然不是真身,但是也可以当作activity组件。所以这里也需要桌面启动的<intent-filter>。

2. 动态切换icon的代码

private void changeLauncher(String name) {

PackageManager pm = getPackageManager();

 //隐藏之前显示的桌面组件

 pm.setComponentEnabledSetting(getComponentName(), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);

 //显示新的桌面组件
 
pm.setComponentEnabledSetting(new ComponentName(MainActivity.this, name), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); }

都是调用PackageManager的setComponentEnabledSetting方法,第一个参数表示操作的组件是哪个,第二个参数表示显示还是隐藏,第三个组件表示是否关掉app。

说明

从官方文档以及相关资料来看,该技术有以下几点需要注意

  1. 该技术只能通过内置icon来实现替换,无法从服务器获取来更新icon。
  2. targetActivity 目标必须与别名在同一应用中,并且在清单中必须在别名<activity-alias>之前进行声明。
  3. setComponentEnabledSetting在执行切换的时候,系统会杀掉app进程。所以不适合app在前台时执行切换逻辑。

存在的坑

结合自己测试以及相关资料来看主要是覆盖安装存在较多的坑。

参考资料:

https://zhuanlan.zhihu.com/p/151781520

https://juejin.cn/post/6844903758971797518

已测场景:

如果9.0当前已切换到A活动icon,新版本9.1没有9.0 A活动icon对应的alias,存在图标消失或者打不开应用的情况(不同机型表现可能不一样)。

9.0当前已切换到A活动icon,新版本9.1仍然存在9.0 A活动icon对应的alias,但是默认关闭,默认打开B活动icon对应的alias。安装结果:桌面还是9.0的A活动icon,可以正常打开。

当前9.0是主icon,新版本9.1默认打开A活动icon,安装结果还是9.0的主icon。

当前版本9.0切换到A活动icon后,用户没有打开过app,这时候更新为新版本9.1,新版本有9.0 A活动icon对应的alias,不过没有打开enabled,结果:这种情况桌面图标还是A活动icon,也能正常打开应用。

当前版本9.0切换到A活动icon后,升级新版本9.1,不过9.1版本A活动对应的alias已经把icon替换成新的B活动icon,结果:安装成功,桌面显示活动B的icon,正常打开。

结论:

通过<activity-alias>内置icon这种方式来实现动态切换icon的话,新版本就必须一直保留对应<activity-alias>,要不然就存在图标消失或者打不开的情况。

解决措施:

  1. 按照增量方式增加<activity-alias>来增加一套活动icon:

需要注意的点,增加一套icon图相应的会增加资源,从而会增加包体积,并且需要永远去考虑市场上已有的版本已经存在的<activity-alias>。

结合Android的icon标准来看,一套icon图4848 =2.18kB, 7272 = 3.53kB, 9696= 5.1kB, 144144= 5.57KB, 总共16.38KB < 20KB。

2. 固定一到两个<activity-alias>不变,只在新版本中替换icon资源,通过版本管理来控制不同版本生效切换。(综合来看,此方案后台版本管理复杂点,但是客户端风险更小。)

初步方案设计

  1. 后台配置策略

后台控制客户端不同版本的生效标志,客户端不同版本获取不同的标志(比如,生效icon:A,B,C)并存在本地,待下次拉取到最新配置后,更新到本地缓存。

  1. 前端无感生效策略。

如何才能无感更新?所以必须用户没有操作app,并且用户没有关注桌面。

最佳更新时机,就是app在后台并且灭屏后启动切换。如果用户亮屏或者app回到前台就取消暂停切换。不过不在乎体验的话,就可以在app置后台后直接延时几十秒触发切换,这种情况用户可能看到,而且可能用户正在交易页面,短暂置后台,等他回来操作时就不在了,可能影响用户体验。

判断app是否在后台的技术实现:

依赖已有的activity生命周期监听接口ActivityLifecycleCallbacks去判断app是否在后台。只要有一个activity回调了resume,那就肯定在前台。所以只要在pause回调时延迟一段时间去判断是否有resume去更新了标志位。这样就可以判断pause回调时是不是置后台还是跳转acitivity。

市场主流app情况调研:

下载了天猫,淘宝,抖音,拼多多,支付宝,京东apk,直接解压查看了AndroidManifest.xml问题,发现它们都没有在配置文件中定义<activity-alias>,比对了同一个app的多个版本也没有发现声明此标签。

在豌豆荚网站查看淘宝的历史版本来看,发布的版本较多,并且具备活动icon的版本也是新版本。

屏幕快照 2021-01-29 17.07.42.png

比对了淘宝9.17.0,9.18.0,9.20.0三个版本。

发现它们的AndroidManifest文件中都没有定义<activity-alias>。而且资源文件中对应桌面icon都是同名但不同资源。这说明淘宝app是通过发布新版本来更新它的桌面icon。

image2021-1-29_17-12-1.png
image2021-1-29_17-12-15.png
image2021-1-29_17-12-35.png

调研结论:

动态切换icon的技术不难,但是由于存在版本升级和不同版本管理的坑,存在一定的风险并且需要付出更多控制风险的成本,实际带来效益也并不高。结合主流app的情况来,完全依赖发布新版本来切换icon也能满足需求,并且成本和风险都更小。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352