/   今日科技快讯   /

近日,蚂蚁集团发布首次公开发行股票并在科创板上市发行公告,发行人和联席主承销商根据初步询价结果,协商确定本次发行价格为68.80元/股,公司股票代码688688。A+H股IPO拟募集约345亿美元。以发行价计算,蚂蚁集团市值已经超过贵州茅台。

/   作者简介   /

本篇文章来自椎锋陷陈的投稿,和大家分享了一个给app自动换图标的功能,相信会对大家有所帮助!同时也感谢作者贡献的精彩文章!

椎锋陷陈的博客地址:

https://www.jianshu.com/u/9bfd80e684ad

/   前言   /

也许你也注意到了,在临近双11之际,手机上电商类APP的应用图标已经悄无声息换成了双11专属图标,比如某宝和某东:

可能你会说,这有什么奇怪的,应用市场开启自动更新不就可以了么?

真的是这样吗?

为此,我特意查看了我手机上的某宝APP的当前版本,并对比了历史版本上的图标,发现并不对应。

/   知识储备   /

<activity-alias>

某一个Activity 的别名,用于实例化该目标Activity。目标必须与别名在同一应用中,并且在清单中必须在别名之前进行声明。

介绍下几个重要的属性:

  • android:enabled:必须设为“true”,系统才能通过别名实例化目标 Activity

  • android:icon:通过别名呈现给用户时目标 Activity 的图标。

  • android:name:别名的唯一名称。与目标 Activity 的名称不同,别名名称是任意的,它不引用实际类。

  • android:targetActivity:可通过别名激活的 Activity 的名称。

PackageManager#setComponentEnabledSetting

可以利用 PackageManager 在清单文件中所定义的任何组件上切换启用状态,包括您想启用或停用的任何一个Activity。

有了以上知识储备后,下面就该剖析一下这个需求的具体场景了。

/   场景剖析   /

以电商类APP双11活动为例,在双11活动开始前的某个时间点(比如10天前)就要开始对活动的预热,此时就要实现图标的自动更换,而在活动结束之后,也必须要能更换回正常图标,并且要求过程尽量对用户无感知,更不能影响用户对APP的正常使用。

具体拆分成要实现的功能点便是:图标更换、自动操作、用户无感知。

/   方案实现   /

1.图标更换:禁用Launcher组件,启用Alias组件,并将targetActivity指向原先的Launcher组件。

2.自动操作:指定日期转换为时间戳,并与当前时间戳对比,超过预设时间则执行替换操作。

3.用户无感知:尽量选择APP不活跃的阶段的,比如切换应用/回到桌面时。

/   代码实现   /

首先,我们需要在AndroidManifest清单文件中添加<activity-alias>元素,默认为禁用状态,name属性作为我们找到此组件的唯一标志,而icon属性即是我们要替换的图标资源,并通过targetActivity属性将作为LANCHUER的SplashActivity作为实例化的目标 Activity:

<activity android:name=".SplashActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>
</activity><!--88会员节专属Activity别名-->
<activity-aliasandroid:name=".SplashAliasActivity"android:enabled="false"android:icon="@mipmap/ic_launcher_88"android:targetActivity=".SplashActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>
</activity-alias><!--双11专属Activity别名-->
<activity-aliasandroid:name=".SplashAlias2Activity"android:enabled="false"android:icon="@mipmap/ic_launcher_11_11"android:targetActivity=".SplashActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>
</activity-alias>

随后,我们图标替换的工作视作一项任务,定义一个数据类:

/*** 切换图标任务*/
data class SwitchIconTask (val launcherComponentClassName: String,  // 启动器组件类名val aliasComponentClassName: String,  // 别名组件类名val presetTime: Long,            // 预设时间val outDateTime: Long)           // 过期时间

定义一个LauncherIconManager单例,负责图标更换相关的工作。开放添加图标切换任务的接口,做好参数合法性的校验:

/*** 启动器图标管理器*/
object LauncherIconManager {/** 切换图标任务Map */private val taskMap: LinkedHashMap<String, SwitchIconTask> = LinkedHashMap()/*** 添加图标切换任务* @param newTasks 新任务,可以传多个*/fun addNewTask(vararg newTasks: SwitchIconTask) {for (newTask in newTasks) {// 防止重复添加任务if (taskMap.containsKey(newTask.aliasComponentClassName)) return// 校验任务的预设时间和过期时间for (queuedTask in taskMap.values) {if (newTask.presetTime > newTask.outDateTime) throw IllegalArgumentException("非法的任务预设时间${newTask.presetTime}, 不能晚于过期时间")if (newTask.presetTime <= queuedTask.outDateTime) throw IllegalArgumentException("非法的任务预设时间${newTask.presetTime}, 不能早于已添加任务的过期时间")}taskMap[newTask.aliasComponentClassName] = newTask}}...
}
LauncherIconManager.addNewTask(SwitchIconTask(SplashActivity::class.java.name,"$packageName.SplashAliasActivity",format.parse("2020-08-02").time,format.parse("2020-08-09").time),SwitchIconTask(SplashActivity::class.java.name,"$packageName.SplashAlias2Activity",format.parse("2020-11-05").time,format.parse("2020-11-12").time)
)

通过Application#registerActivityLifecycleCallbacks方法注册了对应用内Activity生命周期的监听,通过是否有活跃状态的Activity判断应用是否进入了后台:

/*** 应用运行状态注册器*/
object RunningStateRegister {fun register(application: Application, callback: StateCallback) {application.registerActivityLifecycleCallbacks(object : SimpleActivityLifecycleCallbacks() {private var startedActivityCount = 0override fun onActivityStarted(activity: Activity) {if (startedActivityCount == 0) {callback.onForeground()}startedActivityCount++}override fun onActivityStopped(activity: Activity) {startedActivityCount--if (startedActivityCount == 0) {callback.onBackground()}}})}}   
class BaseApplication : Application() {override fun onCreate() {super.onCreate()LauncherIconManager.register(this)}
}

判断应用进入后台后,就可以开始对图标的更换工作了:

/*** 启动器图标管理器*/
object LauncherIconManager {.../*** 注册以监听应用运行状态*/fun register(application: Application) {RunningStateRegister.register(application, object: RunningStateRegister.StateCallback{override fun onForeground() {}override fun onBackground() {proofreadingInOrder(application)}})}/*** 依次校对预设时间* @param context 上下文*/fun proofreadingInOrder(context: Context) {for (task in taskMap.values) {if (proofreading(context, task)) break}}/*** 校对预设时间/过期时间* @param context 上下文* @return true 已过预设时间      false 未达预设时间或已过期*/private fun proofreading(context: Context, task: SwitchIconTask) =when {isPassedOutDateTime(task) -> {disableComponent(context, ActivityUtil.getLauncherActivityName(context)!!)enableComponent(context, task.launcherComponentClassName)false}isPassedPresetTime(task) -> {disableComponent(context, ActivityUtil.getLauncherActivityName(context)!!)enableComponent(context, task.aliasComponentClassName)true}else -> false}/*** 是否已超过预设时间* @param task 任务*/private fun isPassedPresetTime(task: SwitchIconTask) =System.currentTimeMillis() > task.presetTime/*** 是否已超过过期时间* @param task 任务**/private fun isPassedOutDateTime(task: SwitchIconTask) =System.currentTimeMillis() > task.outDateTime...
}        

以上代码均已上传到GitHub。核心的类都封装到Library模块了,并提供Demo模块演示如何使用。如果觉得项目不错的话点个Star吧~

GitHub地址:

https://github.com/madchan/LauncherIconLib

/   代码实现   /

通过以上构建的方案,便可让我们的APP在预设的时间点实现对应用图标的自动替换,缺点是只能加载随APK打包的图片资源,适用于运营活动时间相对固定的的场景。

参考官网文章:

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

推荐阅读:

我的新书,《第一行代码 第3版》已出版!

分享我成为GDE(Google开发者专家)的经历

萌新面试经,赶紧来看看!

欢迎关注我的公众号

学习技术或投稿

长按上图,识别图中二维码即可关注

双十一来了,给自己的应用做个icon换脸小功能相关推荐

  1. 用 UE 虚幻引擎做个捏脸小功能~~

    最近在学习 UE 相关的使用,正好看到一篇文章讲解用 Control Rig 实现简单捏脸功能,这种小而美的完整案例挺适合来练手的,涉及到了 UI.蓝图.动画.骨骼等方面,值得推荐一下. 从这个小功能 ...

  2. 1小时教你做360度全景“小星球”效果图 Skillshare – Create a Panoramic ‘Little Planet’ from Anywhere

    1小时教你做360度全景"小星球"效果图 Skillshare – Create a Panoramic 'Little Planet' from Anywhere 1小时教你做3 ...

  3. C#做的在线升级小程序

    转自原文C#做的在线升级小程序 日前收到一个小任务,要做一个通用的在线升级程序.更新的内容包括一些dll或exe或.配置文件.升级的大致流程是这样的,从服务器获取一个更新的配置文件,经过核对后如有新的 ...

  4. 使用vue-cli+element-ui+expsess+mysql做一个简易的登录功能

    使用vue-cli+element-ui+expsess+mysql做一个简易的登录功能 1使用webpack下载vue模板 vue init webpack aaa(aaa为项目名称) cd到aaa ...

  5. 用c语言简单办法做一个字典_幼儿园手工,用废纸筒做一个简单的小蝴蝶,有教程...

    幼儿园的手工,除了用卡纸做各种简单的小制作外,纸筒也是常用的手工材料. 下面用纸筒做一个简单的小蝴蝶,做法很简单. 制作过程: 准备材料 废纸筒.剪刀.胶.水彩笔,纸板. 在纸筒上剪下五个圈圈 剪完的 ...

  6. 社区团购怎么做_分享有哪些方法可以做社区团购小程序

    今天我们要分享的是社区团购,那么有的小伙伴就会问了什么是社区团购呢,我们简单的来说下社区团购是一种新型的团购模式,刚开始主要是通过团长搭建社群来发布相应的优惠活动,然后吸引用户下单,最后由团长进行订单 ...

  7. python开发跟淘宝有关联微_为什么微商和淘宝卖家不得不做公众号和小程序?

    文/王爷 整理/叨叨 最近一个月,微信方面的动作比较多,尤其是有关微信小程序方面的动态,起码更新了4次.或许很多人还不知道什么是微信小程序,简单来说就是一个无需安装.即用即走的生长在微信上的一个应用. ...

  8. 用 typescript 做一个贪吃蛇小游戏

    typescript 做一个贪吃蛇小游戏 搭建环境 创建 tscofig.json 文件 配置如下 {"compilerOptions": {"target": ...

  9. 美食类短视频怎么做?几个小方法来帮忙,简单很好学

    美食类短视频怎么做?几个小方法来帮忙,简单很好学 民以食为天,尤其是在当今时代,因为疫情的影响,很多人宅在家里刷短视频,也大多会对美食类短视频更加的感兴趣,毕竟闲来无事在家,不能出门享受美食,自己跟着 ...

最新文章

  1. Arrays练习:字符串倒序排列
  2. Android API 中文(77)——AdapterView.OnItemSelectedListener
  3. xx Chrome浏览器更新2020版本:黑暗模式一样使用
  4. lombok之@NoArgsConstructor、@AllArgsConstructor和@Data注解
  5. 【模糊滑模】基于模糊切换增益调节的滑模控制
  6. RedisTemplate 常用方法、序列化方式、基于 Redis 实现分布式锁
  7. Sketch 52.2 轻量易用的矢量设计工具(下载) Sketch汉化
  8. PVE直通Intel核显虚拟机配置ffmpeg-qsv硬件加速
  9. Unable to read entire header; 80 bytes read; expected 512 bytes
  10. 单细胞测序——基本知识
  11. Python自动化体系学习思维导图、知识点整理
  12. 声纹识别demo_语音识别、声纹识别的区别及测试
  13. 【数据库】MySQL 加锁处理分析
  14. 纯js版本网页连连看原理分析和实现
  15. SPSS多元线性回归残差分析的基本方法
  16. 关于new Map()
  17. 云效x钉钉:让研发工作更简单
  18. 带你了解网络解说--链路聚合技术
  19. 大数据 Hadoop 生态体系介绍
  20. C程序---编程统计候选人得票数

热门文章

  1. win10忘记密码_Win10系统设置u盘密码的操作过程
  2. 金融科技争做“超级接口”,度小满有了“送水工”的样子
  3. 【愚人节专场】Java实现定时发送小情话
  4. 操作系统13章(个人笔记)
  5. 【Mysql数据库 第10章】MySQL的存储函数使用
  6. JAVA后台对接苹果APNS(VOIP)实现推送
  7. 移动端1px边框实现
  8. linux 安装 zookeeper
  9. 火车运煤算法--全面解析
  10. 腾讯T9级到底需要什么样的技术水平?我们又该如何学习?