运行时更改Android应用程序图标

设想一下,当我们正在开发一款应用。随着某个节日的临近,我们可能希望通过更改应用图标来增强用户的节日氛围,例如在图标上添“新年特惠”或者“龙年大吉”等标签。

这种小小的改变看似不经意,却能够吸引用户的注意。

运行时更改应用程序图标

首先,应用程序图标是从清单文件设置的,就像任何其他应用程序组件一样。 Android系统读取manifest文件并相应地设置应用程序图标。

目前无法直接使用相关的代码在运行时更改应用程序图标,但有一个解决方案,就是使用activity-alias。

步骤1:准备图标资源🖼️

应用程序图标图片资源

步骤2:修改AndroidManifest.xml📄

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher1"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.TestAndroid"tools:targetApi="31"><activityandroid:name=".MainActivity"android:exported="true"android:theme="@style/Theme.TestAndroid"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity-aliasandroid:name=".MainActivityAlias"android:enabled="false"android:exported="true"android:icon="@mipmap/ic_launcher2"android:targetActivity=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity-alias></application></manifest>

我们定义了一个activity 和一个activity-alias, 并在activity-alias中设置了新的icon。默认情况下disable activity-alias,也就是设置android:enabled=“false”。
应用安装时,启动的是MainActivity,然后我们可以调用代码将主Activity设置成MainActivityAlias,就可以实现运行时更改Android 应用程序图标的内容了。(即disable MainActivity,enable MainActivityAlias。)
如何设置呢,就要使用到PackageManager 这个类了。

步骤3:编写更改图标的代码🔀 (假设我们使用Compose)

// 编写Activity的扩展方法
fun Activity.changeEnabledComponent(enabledPkgName: String,disabledPkgName: String,
) {packageManager.setComponentEnabledSetting(ComponentName(this, enabledPkgName),PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP)packageManager.setComponentEnabledSetting(ComponentName(this, disabledPkgName),PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP)
}@Composable
fun ChangeIconViews(activity: Activity, enabledPkgName: String, disabledPkgName: String) {Column(horizontalAlignment = Alignment.CenterHorizontally) {val btnModifier = Modifier.padding(vertical = 2.5.dp)Button(modifier = btnModifier, onClick = {activity.changeEnabledComponent(enabledPkgName = enabledPkgName,disabledPkgName = disabledPkgName)}) {Text(text = "切换成Test 1")}Button(modifier = btnModifier, onClick = {activity.changeEnabledComponent(enabledPkgName = disabledPkgName,disabledPkgName = enabledPkgName)}) {Text(text = "切换成Test 2")}}
}class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {TestAndroidTheme {Surface(modifier = Modifier.fillMaxSize().padding(vertical = 5.dp),color = MaterialTheme.colorScheme.background) {Box(contentAlignment = Alignment.Center) {ChangeIconViews(activity = this@MainActivity,enabledPkgName = "com.example.testandroid.MainActivity",disabledPkgName = "com.example.testandroid.MainActivityAlias")}}}}}
}
  1. 函数 changeEnabledComponent用于启用或禁用指定的组件,使用 packageManager 对象的 setComponentEnabledSetting 方法来设置组件的启用状态。
  2. 函数 ChangeIconViews 是一个Composable函数,用于显示一个列(Column)布局,并包含两个按钮。
  3. 最后在MainActivity的 onCreate 方法中放置ChangeIconViews。

然后就能够实现在运行时更改Android应用程序图标这个需求了。

步骤4:优化我们的代码📚

但是作为一名开发人员,我们想要我们的代码更整洁更灵活的话,我们就应该考虑优化我们的代码,比如硬编码就不是很合适:

ChangeIconViews(activity = this@MainActivity,enabledPkgName = "com.example.testandroid.MainActivity",disabledPkgName = "com.example.testandroid.MainActivityAlias"
)

假设我们使用最新版的Android Studio工具开发,使用build.gradle.kts编写我们的编译脚本(使用build.gradle的话其实也差不多,就是语法不大一样),就可以像下面这样:

...
private val mainActivity = "com.example.testandroid.MainActivity"
private val mainActivityAlias = "com.example.testandroid.MainActivityAlias"
android {...defaultConfig {...buildConfigField("String", "main_activity", "\"${mainActivity}\"")buildConfigField("String", "main_activity_alias", "\"${mainActivityAlias}\"")}...buildFeatures {...// 使用自定义的buildConfig需要开启这个功能buildConfig = true}...
}

所以我们的MainActivity的onCreate就可以换成下面的代码:

class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {TestAndroidTheme {Surface(modifier = Modifier.fillMaxSize().padding(vertical = 5.dp),color = MaterialTheme.colorScheme.background) {Box(contentAlignment = Alignment.Center) {ChangeIconViews(activity = this@MainActivity,enabledPkgName = BuildConfig.main_activity,disabledPkgName = BuildConfig.main_activity_alias)}}}}}
}

除此之外我们发现AndroidManifest.xml中也有关于mainActivity和mainActivityAlias的硬编码,比如下面的代码:

<activityandroid:name=".MainActivity"...>...
</activity><activity-aliasandroid:name=".MainActivityAlias"...android:targetActivity=".MainActivity">...
</activity-alias>

所以我们做一下优化:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher1"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.TestAndroid"tools:targetApi="31"><activityandroid:name="${main_activity}"android:exported="true"android:theme="@style/Theme.TestAndroid"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity-aliasandroid:name="${main_activity_alias}"android:enabled="false"android:exported="true"android:icon="@mipmap/ic_launcher2"android:targetActivity="${main_activity}"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity-alias></application></manifest>
android {...defaultConfig {...manifestPlaceholders.apply {set("main_activity", mainActivity)set("main_activity_alias", mainActivityAlias)}buildConfigField("String", "main_activity", "\"${mainActivity}\"")buildConfigField("String", "main_activity_alias", "\"${mainActivityAlias}\"")}...
}

完整代码地址

感谢阅读,Best Regards!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/258295.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网安领域含金量最高的证书有哪些?看这1篇就足够了!

文章目录 一、前言二、CISP三、CISAW四、NISP五、为什么很多人考不下来 一、前言 现在想找网络安全之类的工作&#xff0c;光有技术是不够的&#xff0c;还得有东西证明自己&#xff0c;网安三大敲门砖&#xff1a;CTF、漏洞证明和专业证书。 对于CTF的话只是少数人能参加的&…

Redis保证高可用的三种方式

Redis保证高可用主要有三种方式&#xff1a;主从、哨兵、集群。 主从复制了解吗&#xff1f; Redis主从复制简图 主从复制&#xff0c;是指将一台 Redis 服务器的数据&#xff0c;复制到其他的 Redis 服务器。前者称为 主节点(master)&#xff0c;后者称为 从节点(slave)。且…

html、css类名命名思路整理

开发页面时&#xff0c;老是遇到起名问题&#xff0c;越想越头疼&#xff0c;严重影响开发进度&#xff0c;都是在想名字&#xff0c;现在做一下梳理&#xff0c;统一一下思想&#xff0c;希望以后能减少这块的痛苦。 命名规则 [功能名称]__[组成部分名称]--[样式名称] 思路…

C语言数组(下)

我希望各位可以在思考之后去看本期练习&#xff0c;并且在观看之后独立编写一遍&#xff0c;以加深理解&#xff0c;巩固知识点。 练习一&#xff1a;编写代码&#xff0c;演⽰多个字符从两端移动&#xff0c;向中间汇聚 我们依旧先上代码 //编写代码&#xff0c;演⽰多个字…

C //例10.3 从键盘读入若干个字符串,对它们按字母大小的顺序排序,然后把排好序的字符串送到磁盘文件中保存。

C程序设计 &#xff08;第四版&#xff09; 谭浩强 例10.3 例10.3 从键盘读入若干个字符串&#xff0c;对它们按字母大小的顺序排序&#xff0c;然后把排好序的字符串送到磁盘文件中保存。 IDE工具&#xff1a;VS2010 Note: 使用不同的IDE工具可能有部分差异。 代码块 方法…

HttpComponents: 领域对象的设计

1. HTTP协议 1.1 HTTP请求 HTTP请求由请求头、请求体两部分组成&#xff0c;请求头又分为请求行(request line)和普通的请求头组成。通过浏览器的开发者工具&#xff0c;我们能查看请求和响应的详情。 下面是一个HTTP请求发送的完整内容。 POST https://track.abc.com/v4/tr…

c语言怎么“简单”表示9个变量互不相等?

c语言怎么“简单”表示9个变量互不相等? 在开始前我有一些资料&#xff0c;是我根据自己从业十年经验&#xff0c;熬夜搞了几个通宵&#xff0c;精心整理了一份「C语言从专业入门到高级教程工具包」&#xff0c;点个关注&#xff0c;全部无偿共享给大家&#xff01;&#xff0…

第二次上机测试:Javascript. (第一组)

需求&#xff1a;&#xff08;注意在规定的时间&#xff0c;在自己的博客提交作品&#xff0c;便于统计测试的完成情况。博客题目《第二次上机测试&#xff1a;Javascript.》&#xff09; 1、点击按钮&#xff0c;将图片加上边框 2、点击按钮&#xff0c;将图片缩小为长和宽都…

服务器配置免密SSH

在当今互联网时代&#xff0c;远程工作和网络安全已成为信息技术领域的热点话题。无论是管理远程服务器、维护网络设备还是简单地从家中连接到办公室&#xff0c;安全始终是首要考虑的因素。这就是为什么 SSH&#xff08;Secure Shell&#xff09;成为了网络专业人士的首选工具…

这把养生局~

查看原文请移步~ &#x1f308;9款好喝解腻水果茶 ✅苹果热橙茶 苹果橙子柠檬红茶冰糖 ✅金桔话梅乌龙茶 柠檬话梅金桔乌龙茶冰糖 ✅柠檬百香果乌龙茶 橙子柠檬百香果乌龙茶冰糖 ✅港式柠檬茶 柠檬青柠红茶冰糖 ✅山楂苹果消食茶 山楂苹果红茶冰糖 ✅桂圆热红茶 桂圆红茶冰糖 …

Java第二十一章

网络程序设计基础 网络程序设计编写的是与其他计算机进行通信的程序。Java 已经将网络程序所需要的元素封装成不同的类&#xff0c;用户只要创建这些类的对象&#xff0c;使用相应的方法&#xff0c;即使不具备有关的网络支持&#xff0c;也可以编写出高质量的网络通信程序。 …

C++基础 -42- STL库之list链表

———————STL库之list链表——————— &#x1f384; list链表的格式(需要定义头文件) list<int> data1(4, 100);list<int> data2(4, 500);&#x1f384;list链表的合并接口 &#x1f384;举例使用合并接口并且验证 data2.merge(data1);list<int>::…