Android之動態更換桌面圖標
文章鏈接:http://blog.csdn.net/qq_16628781/article/details/69054325
知識點
- 動態更換APP 桌面icon的引述;
- activity組件及定義“同盟”組件activity-alias;
- PackageManager類進行啓用/禁用組件;
- PackageInfo的簡介;
- 新名詞記錄{PackageInfo:Androidmanifest.xml文件描述類}
概述
APP,在中國電商行業中,某寶和某東是行業的標杆。其中有一點挺讓人好奇的,那就是在雙十一臨近之時,他們的APP桌面圖標突然變成了帶有雙十一字樣的圖標。但是明明記得那段時間並沒有更新過,那麼唯一的可能就是本來就內置了雙十一的圖標,等快到雙十一的時候在動態更換,然後過了雙十一那段時間,又將APP的桌面圖標變成普通的icon。
既然圖標本來就在APP裏頭(或者是網絡下載下來的,只是猜測,有知道的小夥伴可以給我留言),那麼就很好奇了,它們的圖標到底是怎麼樣進行動態的更換的呢?
探索1
對於Android來說,所有的activity都是一個組件,我們可以對每個組件進行管理。
關於程序的入口,我們知道android.intent.action.MAIN進行的指定的。
<activity
android:name=".HomeActivity"
android:label="@string/app_name"
android:theme="@style/AppThemeToolbar">
<intent-filter>
//指定應用程序最先啓動的Activity
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
對於android.intent.category.LAUNCHER,這個又是設置什麼的呢?這個是決定應用程序是否顯示在程序列表裏頭。
另外,還有一個activity-alias屬性,這個屬性可以用於創建多個不同的入口。用法如下所示:
<activity
android:name=".HomeActivity"
android:label="@string/app_name"
android:theme="@style/AppThemeToolbar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--name:組件名字-->
<!--enabled:該組件是否啓動-->
<!--icon:組件圖標-->
<!--label:組件標籤說明-->
<!--targetActivity:組件的類-->
<activity-alias
android:name=".HomeActivity2"
android:enabled="false"
android:icon="@drawable/icon2"
android:label="icon2"
android:targetActivity=".HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".HomeActivity3"
android:enabled="false"
android:icon="@drawable/icon3"
android:label="icon3"
android:targetActivity=".HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
如上面代碼顯示,這裏有3個程序的入口,其中第二和第三個是被禁用掉的,如果enable缺省值,那麼默認是true。既然可以XML中禁用,那麼對應的也可以在代碼中啓動組件了。
探索2
APP的icon是對於整個包範圍的,既然是要動用到APP包,那麼是不是系統就給我們提供了一個管理整個包的類呢?事實上,系統給我們提供了PackageManager這個類,這個類能夠獲取到當前應用裏不同類型的信息。定義了一系列比如的服務的字段常量,低功耗ble藍牙,相機==,以及一系列有關包操作的抽象方法。此類可以管理所有的系統組件。
我們知道APP上每一個對象都是系統裏的一個組件,那麼我們可以在PackageManager類裏面看到有關於組件的操作方法;
這個方法有以下比較重要的方法:
//設置特定組件是否可以啓動方法
public abstract void setComponentEnabledSetting(ComponentName componentName, int newState, int flags);
//相反,得到特定組件是否啓動的方法
public abstract int getComponentEnabledSetting(ComponentName componentName);
參數1:組件的名稱;
參數2:組件新的狀態;
參數3:標誌是否要killapp;
有了以上兩個方法,我們就可以根據給定不同的組件名稱+狀態進行設置是否可用了。結合探索1裏面定義的3個組件的啓動和禁止情況,我們可以進行對應的enable操作。
結合使用
private PackageManager mPackageManager;
//默認組件
private ComponentName componentNameDefault;
private ComponentName componentName2;
private ComponentName componentName3;
/**
* 設置第icon2圖標生效
*/
private void enableComponentName2() {
disableComponent(componentNameDefault);
disableComponent(componentName3);
enableComponent(componentName2);
}
/**
* 設置第icon3圖標生效
*/
private void enableComponentName3() {
disableComponent(componentNameDefault);
disableComponent(componentName2);
enableComponent(componentName3);
}
/**
* 啓動組件
*
* @param componentName 組件名
*/
private void enableComponent(ComponentName componentName) {
//此方法用以啓用和禁用組件,會覆蓋Androidmanifest文件下定義的屬性
mPackageManager.setComponentEnabledSetting(componentName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
/**
* 禁用組件
*
* @param componentName 組件名
*/
private void disableComponent(ComponentName componentName) {
mPackageManager.setComponentEnabledSetting(componentName,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
//最後調用
public void pmTest() {
//獲取到包管理類實例
mPackageManager = getPackageManager();
//得到此activity的全限定名
componentNameDefault = getComponentName();
//根據全限定名創建一個組件,即activity-alias 節點下的name:HomeActivity2 對應的組件
componentName2 = new ComponentName(getBaseContext(), "com.yaojt.HomeActivity2");
componentName3 = new ComponentName(getBaseContext(), "com.yaojt.HomeActivity3");
String action = getActionFromServer();//從後臺獲取到應該使用那一個組件,或者根據時間來判斷
if ("comp2".equals(action)){
enableComponentName2();
}else if ("comp3".equals(action)){
enableComponentName3();
}
//如果沒有,則顯示默認圖標
}
通過以上的代碼,可以清楚的看到,如何獲取已經在XML文件裏面定義好的組件。然後根據不同需求,來啓用或者禁止對應的組件,從而達到更新APP桌面圖標的功能。(可能需要一段時間刷新,才能看到新的APP桌面圖標)
課外知識
PackageInfo:裝載Androidmanifest.xml文件所有信息的類。
所有的信息都來自AndroidManifest.xml文件;例如,包名packageName、版本號versionCode、sharedUserId共享id、apk第一次和最後一次安裝時間、聲明的activity,service、receiver、provider和請求的權限等等的信息。
總結
以上就是其中一種動態桌面更換圖標的方法,需要的是預先放入需要更換的icon進去,或許還可以支持動態的設置icon,但是這部分我還沒有仔細的去研究。如果你知道,請留言告知我,大家共同學習進步。
如有任何問題,請及時與我聯繫。謝謝