Android動態更換APP圖標及名稱 [復制鏈接]

2018-9-11 10:46
EmailLi 閱讀:670 評論:0 贊:0
Tag:  

前言

本來想研究一加手機上的天氣APP,會隨著每天的天氣、溫度不同動態的改變APP的圖標是如何實現的,但始終沒有想出和查閱到相關方法,畢竟是人家自己的系統APP。但是也找到了一種能動態改變圖標的方法,這里做一下簡單的記錄。

效果圖

這里點擊完“改變圖標”后,桌面上的APP圖標不會立即改變,會有一定的延遲,需要等待Launcher刷新。

基礎原理

多入口配置:activity-alias 
alias是別名的意思,顧名思義,就是可以給Activity配置別名。在AndroidManifest.xml中,與基本的Activity的配置大體相似,如:

        <activity
            android:name=".MainActivity"
            android:label="改變前的">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity-alias
            android:name=".test"
            android:enabled="false"
            android:icon="@mipmap/icon_test"
            android:label="改變后的"
            android:targetActivity=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity-alias>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

上面的默認的,下面的是配置的別名,也就是另一個入口。 
android:name:就是注冊這個組件的名字,不需要去創建test.java這個類,就是個名字,我這里的這個名稱是,com.fu.changeicondemo.test 
android:enabled:是否啟用這個組件,也就是是否顯示這個入口。 
android:icon:圖標 
android:label:名稱 
android:targetActivity:這個需要注意,默認的activity沒有這個屬性,這個屬性就是指定目標activity,與默認的activity中的name屬性是一樣的,需要有相應的java類文件。 
然后intent-filter是一樣的。

我們把別名activity的android:enabled設為true,就是開啟它,桌面上就有兩個入口了。 
如圖: 

 
點擊這兩個圖標效果是一樣的,都是進入MainActivity。

講到這里,相信讀者應該已經明白了,如何動態改變圖標了,其實就啟用不同的入口就行,然后每次就只有一個入口被啟用就行了,在默認情況下,我們就讓啟動的默認組件,其他入口組件全部禁用,需要用哪個就啟用哪個,并且把其他的關閉了,避免出現多個入口,那么如何通過代碼動態的設置啟動或禁用呢?

如何動態設置是否啟用? 
那就需要packageManager,有一個這個方法:

        packageManager.setComponentEnabledSetting(componentName,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
  • 1
  • 2
  • 3

第一個參數是組件,第二個參數就是是否啟用,第三個參數一般就填不殺死APP。 
然后組件通過自己定義的組件名字來獲取到,如

        //拿到我們注冊的MainActivity組件
        defaultComponent = new ComponentName(getBaseContext(), "com.fu.changeicondemo.MainActivity");  //拿到默認的組件
        //拿到我注冊的別名test組件
        testComponent = new ComponentName(getBaseContext(), "com.fu.changeicondemo.test");
  • 1
  • 2
  • 3
  • 4

到了這里,相信大家已經很清楚了如何實現了,下面附上代碼。

代碼

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private ComponentName defaultComponent;
    private ComponentName testComponent;
    private PackageManager packageManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //拿到當前activity注冊的組件名稱
        ComponentName componentName = getComponentName();

        //拿到我們注冊的MainActivity組件
        defaultComponent = new ComponentName(getBaseContext(), "com.fu.changeicondemo.MainActivity");  //拿到默認的組件
        //拿到我注冊的別名test組件
        testComponent = new ComponentName(getBaseContext(), "com.fu.changeicondemo.test");

        packageManager = getApplicationContext().getPackageManager();
    }

    public void changeIcon(View view) {
        disableComponent(defaultComponent);
        enableComponent(testComponent);
    }

    public void changeDefaultIcon(View view) {
        enableComponent(defaultComponent);
        disableComponent(testComponent);
    }

    /**
     * 啟用組件
     *
     * @param componentName
     */
    private void enableComponent(ComponentName componentName) {
        int state = packageManager.getComponentEnabledSetting(componentName);
        if (state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
            //已經啟用
            return;
        }
        packageManager.setComponentEnabledSetting(componentName,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
    }

    /**
     * 禁用組件
     *
     * @param componentName
     */
    private void disableComponent(ComponentName componentName) {
        int state = packageManager.getComponentEnabledSetting(componentName);
        if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
            //已經禁用
            return;
        }
        packageManager.setComponentEnabledSetting(componentName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.fu.changeicondemo.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="改變圖標"
        android:onClick="changeIcon"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="改回默認圖標"
        android:onClick="changeDefaultIcon" />

</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.fu.changeicondemo">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity
            android:name=".MainActivity"
            android:label="改變前的">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity-alias
            android:name=".test"
            android:enabled="false"
            android:icon="@mipmap/icon_test"
            android:label="改變后的"
            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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

總結

這個方法能動態改變圖標和名稱、但是需要提前把“坑位”站住,需要用哪個就用哪個。還有一個問題就是,在調用完相應的改變圖標的方法時候需要等待Launcher刷新,而在這個時間里,在去點擊圖標就會提示“未安裝該應用”。


我來說兩句
您需要登錄后才可以評論 登錄 | 立即注冊
facelist
所有評論(0)
領先的中文移動開發者社區
18620764416
7*24全天服務
意見反饋:[email protected]

掃一掃關注我們

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粵ICP備15117877號 )

两码中特期期