Android之動態更換桌面圖標

Android之動態更換桌面圖標

文章鏈接:http://blog.csdn.net/qq_16628781/article/details/69054325

知識點

  1. 動態更換APP 桌面icon的引述;
  2. activity組件及定義“同盟”組件activity-alias;
  3. PackageManager類進行啓用/禁用組件;
  4. PackageInfo的簡介;
  5. 新名詞記錄{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,但是這部分我還沒有仔細的去研究。如果你知道,請留言告知我,大家共同學習進步。

如有任何問題,請及時與我聯繫。謝謝

發佈了135 篇原創文章 · 獲贊 70 · 訪問量 51萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章