上次發(fā)版我就改了一行代碼!
動態(tài)更換應用Icon
產品:我們可以動態(tài)更換App在Launcher里面的Icon嗎
開發(fā):不可以
產品:我們可以動態(tài)更換App在Launcher里面的Icon嗎
開發(fā):不可以
產品:我們可以動態(tài)更換App在Launcher里面的Icon嗎
開發(fā):不可以
產品:我們可以動態(tài)更換App在Launcher里面的Icon嗎
開發(fā):讓我想想……
原理1——activity-alias
在AndroidMainifest中,有兩個屬性:
- // 決定應用程序***啟動的Activity
- android.intent.action.MAIN
- // 決定應用程序是否顯示在程序列表里
- android.intent.category.LAUNCHER
另外,還有一個activity-alias屬性,這個屬性可以用于創(chuàng)建多個不同的入口,相信做過系統(tǒng)Setting和Launcher開發(fā)的開發(fā)者在系統(tǒng)的源碼中應該見過很多。
原理2——PM.setComponentEnabledSetting
PackageManager是一個大統(tǒng)領類,可以管理所有的系統(tǒng)組件,當然,如果Root了,你還可以管理其它App的所有組件,一些系統(tǒng)優(yōu)化工具就是通過這個方式來禁用一些后臺Service的。
使用方式異常簡單:
- private void enableComponent(ComponentName componentName) {
- mPm.setComponentEnabledSetting(componentName,
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
- PackageManager.DONT_KILL_APP);
- }
- private void disableComponent(ComponentName componentName) {
- mPm.setComponentEnabledSetting(componentName,
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- }
根據(jù)PackageManager.COMPONENT_ENABLED_STATE_ENABLED和PackageManager.COMPONENT_ENABLED_STATE_DISABLED這兩個標志量和對應的ComponentName,就可以控制一個組件的是否啟用。
動態(tài)換Icon
有了上面的兩個原理,來實現(xiàn)動態(tài)更換Icon就只剩下思路問題了。
首先,我們創(chuàng)建一個Activity,作為默認的入口并帶著默認的圖片,再創(chuàng)建一個雙11的activity-alias,指向默認的Activity并帶有雙11的圖片,再創(chuàng)建一個雙12的activity-alias,指向默認的Activity并帶有雙12的圖片……等等等。
- <activity android:name=".MainActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- <activity-alias
- android:name=".Test11"
- android:enabled="false"
- android:icon="@drawable/s11"
- android:label="雙11"
- 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=".Test12"
- android:enabled="false"
- android:icon="@drawable/s12"
- android:label="雙12"
- android:targetActivity=".MainActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity-alias>
等等,這樣有個問題,那就是這樣會在Launcher上顯示3個入口,所以,默認我們會把這些activity-alias先禁用,等到要用的時候再啟用,養(yǎng)兵千日,用兵一時。
- public class MainActivity extends AppCompatActivity {
- private ComponentName mDefault;
- private ComponentName mDouble11;
- private ComponentName mDouble12;
- private PackageManager mPm;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mDefault = getComponentName();
- mDouble11 = new ComponentName(
- getBaseContext(),
- "com.xys.changeicon.Test11");
- mDouble12 = new ComponentName(
- getBaseContext(),
- "com.xys.changeicon.Test12");
- mPm = getApplicationContext().getPackageManager();
- }
- public void changeIcon11(View view) {
- disableComponent(mDefault);
- disableComponent(mDouble12);
- enableComponent(mDouble11);
- }
- public void changeIcon12(View view) {
- disableComponent(mDefault);
- disableComponent(mDouble11);
- enableComponent(mDouble12);
- }
- private void enableComponent(ComponentName componentName) {
- mPm.setComponentEnabledSetting(componentName,
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
- PackageManager.DONT_KILL_APP);
- }
- private void disableComponent(ComponentName componentName) {
- mPm.setComponentEnabledSetting(componentName,
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- }
- }
OK了,禁用默認的Activity后,啟用雙11的activity-alias,結果不變還是指向了默認的Activity,但圖標已經(jīng)發(fā)生了改變。
根據(jù)ROM的不同,在禁用了組件之后,會等一會,Launcher會自動刷新圖標。
效果參考下圖。
專欄作者簡介
eclipse_xu:Android 高級開發(fā)工程師;《Android群英傳》、《Android群英傳:神兵利器》作者、慕課網(wǎng)Android講師;CSDN博客專家