activity-alias
在 AndroidManifest.xml
中为不同的图标创建别名,
使用 activity-alias
标签,并指定 targetActivity,设置 icon 和 label,enable 是否启用这个图标入口(目标 activity 和 这些 activity-alias 都可以设置enable,并且效果相同)
<application
...>
<activity
android:name=".MainActivity"
android:enabled="true"
android:exported="true"
android:label="切换图标 Default"
android:theme="@style/Theme.TestAppIcon">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity-alias
android:name=".MainActivityAlias1"
android:enabled="false"
android:exported="true"
android:icon="@drawable/icon_chrome"
android:label="切换图标 Icon1"
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=".MainActivityAlias2"
android:enabled="false"
android:exported="true"
android:icon="@drawable/icon_conan"
android:label="切换图标 Icon2"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
</application>
在代码中,可以通过启用或禁用别名来动态切换图标
fun enableComponent(componentName: String) {
val pm = applicationContext.packageManager
pm.setComponentEnabledSetting(
ComponentName(applicationContext.packageName, componentName),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
}
fun disableComponent(componentName: String) {
val pm = applicationContext.packageManager
pm.setComponentEnabledSetting(
ComponentName(applicationContext.packageName, componentName),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
}
// 更新指定入口
fun updateComponent(componentNameList: List<String>, enableComponentName: String) {
// 禁用所有
componentNameList.forEach {
disableComponent(it)
}
// 启用指定的入口
enableComponent(enableComponentName)
}
使用上述定义的方法切换图标
val componentNameList = listOf(
"${packageName}.MainActivity",
"${packageName}.MainActivityAlias1",
"${packageName}.MainActivityAlias2",
)
// 切换
updateComponent(componentNameList, componentNameList[0]) // 使用 index 为 0 的 Activity
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.TestAppIcon"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:enabled="true"
android:exported="true"
android:label="切换图标 Default"
android:theme="@style/Theme.TestAppIcon">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity-alias
android:name=".MainActivityAlias1"
android:enabled="false"
android:exported="true"
android:icon="@drawable/icon_chrome"
android:label="切换图标 Icon1"
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=".MainActivityAlias2"
android:enabled="false"
android:exported="true"
android:icon="@drawable/icon_conan"
android:label="切换图标 Icon2"
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>
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
val componentNameList = listOf(
"${packageName}.MainActivity",
"${packageName}.MainActivityAlias1",
"${packageName}.MainActivityAlias2",
)
setContent {
TestAppIconTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
UI(
modifier = Modifier.padding(innerPadding),
componentNameList,
) {
updateComponent(componentNameList, componentNameList[it])
}
}
}
}
}
fun enableComponent(componentName: String) {
val pm = applicationContext.packageManager
pm.setComponentEnabledSetting(
ComponentName(applicationContext.packageName, componentName),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
}
fun disableComponent(componentName: String) {
val pm = applicationContext.packageManager
pm.setComponentEnabledSetting(
ComponentName(applicationContext.packageName, componentName),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
}
// 更新指定入口
fun updateComponent(componentNameList: List<String>, enableComponentName: String) {
// 禁用所有
componentNameList.forEach {
disableComponent(it)
}
// 启用指定的入口
enableComponent(enableComponentName)
}
}
@Composable
fun UI(modifier: Modifier = Modifier, componentNameList: List<String>, click: (Int) -> Unit) {
val context = LocalContext.current
var enableActivity by remember { mutableStateOf("") }
// 检查启用了的组件
LaunchedEffect(Unit) { // 首次渲染时使用 packageManager 获取
for (activityName in componentNameList) {
val enableState = context.packageManager.getComponentEnabledSetting(ComponentName(context, activityName))
// 判断 3 种状态即可,
// 0: 默认, 1: 启用, 2: 禁用,
val isEnabled = enableState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
if (isEnabled) {
enableActivity = activityName
break
}
}
}
// 弹窗控制变量
var showDialog by remember { mutableStateOf(false) }
var selectedIconIndex by remember { mutableStateOf(0) }
// 确认弹窗
if (showDialog) {
AlertDialog(
onDismissRequest = { showDialog = false },
title = { Text("确认切换图标") },
text = { Text("切换图标成功后可能会自动退出App,是否继续?") },
confirmButton = {
Button(
onClick = {
click.invoke(selectedIconIndex)
enableActivity = componentNameList[selectedIconIndex]
showDialog = false
}
) {
Text("确认")
}
},
dismissButton = {
Button(onClick = { showDialog = false }) {
Text("取消")
}
}
)
}
Column(
modifier = modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
"当前图标: ${
when (enableActivity) {
componentNameList[0] -> {
"默认图标"
}
componentNameList[1] -> {
"Icon1"
}
componentNameList[2] -> {
"Icon2"
}
else -> {
"未知"
}
}
}"
)
Button({
selectedIconIndex = 0
showDialog = true
}) { Text("切换到 默认图标") }
Button({
selectedIconIndex = 1
showDialog = true
}) { Text("切换到 Icon1") }
Button({
selectedIconIndex = 2
showDialog = true
}) { Text("切换到 Icon2") }
}
}