對於動態更新應用圖標和名稱這個小功能還是有一定使用場景的。比如節假日或者特惠活動時候我們需要展示一些特殊的圖標。要是重新打包發布那豈不是很麻煩。
我最近使用迅雷APP,就發現了有這個功能,會員還可以享受會員專享圖標,展示你的與眾不同。
那怎么實現這個功能,下面就來詳細介紹下,要實現這個功能主要涉及兩個知識點:activity-alias和setComponentEnabledSetting
activity-alias
這是在清單文件里面配置的屬性,字面意思就是活動的別名。
<activity-alias
android:name="launcherB"
android:enabled="true"
android:exported="true"
android:icon="@mipmap/ic_launcher_b"
android:label="B圖標應用"
android:roundIcon="@mipmap/ic_launcher_b_round"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
屬性基本和<activity>一樣,唯一區別android:targetActivity指定該活動別名跳轉的頁面。當我們在清單文件配置上述的內容后,就會在桌面多出來一個啟動應用的圖標,當你點擊該圖標時候就會跳轉到MainActivity。

setComponentEnabledSetting
setComponentEnabledSetting(@NonNull ComponentName componentName,
@EnabledState int newState, @EnabledFlags int flags);
該方法是包管理器PackageManger中的方法,可以配置清單文件中組件是否可用。而第二個參數其實就是android:enabled="true"該屬性的配置。
正如上面我們配置了enable=true所以桌面會顯示B圖標,當配置為enable=false,那么B圖標就不會顯示。setComponentEnabledSetting就是起到這樣一個效果。
============================================
有了上面兩個知識點我們就可以實現切換圖標和名稱。
1. 首先我們在清單文件中配置好啟動頁面和活動別名
...
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity-alias
android:name="launcherA"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/ic_launcher_a"
android:label="A圖標應用"
android:roundIcon="@mipmap/ic_launcher_a_round"
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="launcherB"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/ic_launcher_b"
android:label="B圖標應用"
android:roundIcon="@mipmap/ic_launcher_b_round"
android:targetActivity=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
</application>
這里需要注意,launcherA和launcherB的android:enable屬性要配置為false,要不然你應用安裝界面就會有三個圖標了,豈不是很尷尬。
2. 我們在MainActivity中實現切換圖標
MainActivity.kt
class MainActivity : AppCompatActivity() {
private var app: String = LauncherSwitch.APP
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.show_switch_launcher)
findViewById<RadioGroup>(R.id.rg_app).setOnCheckedChangeListener { _, checkedId ->
app = when (checkedId) {
R.id.rb_app_a -> LauncherSwitch.APP_A
R.id.rb_app_b -> LauncherSwitch.APP_B
else -> LauncherSwitch.APP
}
}
findViewById<Button>(R.id.btn_switch_launcher).setOnClickListener {
LauncherSwitch.enableLauncher(this, app)
}
}
}
show_switch_launcher.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RadioGroup
android:id="@+id/rg_app"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:checkedButton="@id/rb_app_origin"
android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RadioButton
android:id="@+id/rb_app_origin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@mipmap/ic_launcher"
android:text="原應用" />
<RadioButton
android:id="@+id/rb_app_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@mipmap/ic_launcher_a"
android:text="A應用" />
<RadioButton
android:id="@+id/rb_app_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@mipmap/ic_launcher_b"
android:text="B應用" />
</RadioGroup>
<Button
android:id="@+id/btn_switch_launcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="切換圖標和應用"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
LauncherSwitch.kt
/**
* 應用圖標和名稱更新工具類
*/
object LauncherSwitch {
const val APP = "com.sample.MainActivity"
const val APP_A = "com.sample.launcherA"
const val APP_B = "com.sample.launcherB"
@StringDef(
value = [APP, APP_A, APP_B]
)
@kotlin.annotation.Retention(AnnotationRetention.SOURCE)
annotation class AppLauncher
fun enableLauncher(context: Context, @AppLauncher name: String) {
context.packageManager.run {
setComponentEnabledSetting(
ComponentName(context, APP),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
setComponentEnabledSetting(
ComponentName(context, APP_A),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
setComponentEnabledSetting(
ComponentName(context, APP_B),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
setComponentEnabledSetting(
ComponentName(context, name),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
}
}
}
這樣我們就可以實現動態切換圖標和名稱,
其實我們看看迅雷的清單文件也是通過配置多個活動別名來實現切換啟動圖標和名稱

